github.com/defanghe/fabric@v2.1.1+incompatible/bccsp/sw/aes.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sw
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/aes"
    22  	"crypto/cipher"
    23  	"crypto/rand"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  
    28  	"github.com/hyperledger/fabric/bccsp"
    29  )
    30  
    31  // GetRandomBytes returns len random looking bytes
    32  func GetRandomBytes(len int) ([]byte, error) {
    33  	if len < 0 {
    34  		return nil, errors.New("Len must be larger than 0")
    35  	}
    36  
    37  	buffer := make([]byte, len)
    38  
    39  	n, err := rand.Read(buffer)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	if n != len {
    44  		return nil, fmt.Errorf("Buffer not filled. Requested [%d], got [%d]", len, n)
    45  	}
    46  
    47  	return buffer, nil
    48  }
    49  
    50  func pkcs7Padding(src []byte) []byte {
    51  	padding := aes.BlockSize - len(src)%aes.BlockSize
    52  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    53  	return append(src, padtext...)
    54  }
    55  
    56  func pkcs7UnPadding(src []byte) ([]byte, error) {
    57  	length := len(src)
    58  	unpadding := int(src[length-1])
    59  
    60  	if unpadding > aes.BlockSize || unpadding == 0 {
    61  		return nil, errors.New("Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)")
    62  	}
    63  
    64  	pad := src[len(src)-unpadding:]
    65  	for i := 0; i < unpadding; i++ {
    66  		if pad[i] != byte(unpadding) {
    67  			return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)")
    68  		}
    69  	}
    70  
    71  	return src[:(length - unpadding)], nil
    72  }
    73  
    74  func aesCBCEncrypt(key, s []byte) ([]byte, error) {
    75  	return aesCBCEncryptWithRand(rand.Reader, key, s)
    76  }
    77  
    78  func aesCBCEncryptWithRand(prng io.Reader, key, s []byte) ([]byte, error) {
    79  	if len(s)%aes.BlockSize != 0 {
    80  		return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
    81  	}
    82  
    83  	block, err := aes.NewCipher(key)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	ciphertext := make([]byte, aes.BlockSize+len(s))
    89  	iv := ciphertext[:aes.BlockSize]
    90  	if _, err := io.ReadFull(prng, iv); err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	mode := cipher.NewCBCEncrypter(block, iv)
    95  	mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
    96  
    97  	return ciphertext, nil
    98  }
    99  
   100  func aesCBCEncryptWithIV(IV []byte, key, s []byte) ([]byte, error) {
   101  	if len(s)%aes.BlockSize != 0 {
   102  		return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
   103  	}
   104  
   105  	if len(IV) != aes.BlockSize {
   106  		return nil, errors.New("Invalid IV. It must have length the block size")
   107  	}
   108  
   109  	block, err := aes.NewCipher(key)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	ciphertext := make([]byte, aes.BlockSize+len(s))
   115  	copy(ciphertext[:aes.BlockSize], IV)
   116  
   117  	mode := cipher.NewCBCEncrypter(block, IV)
   118  	mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
   119  
   120  	return ciphertext, nil
   121  }
   122  
   123  func aesCBCDecrypt(key, src []byte) ([]byte, error) {
   124  	block, err := aes.NewCipher(key)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	if len(src) < aes.BlockSize {
   130  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
   131  	}
   132  	iv := src[:aes.BlockSize]
   133  	src = src[aes.BlockSize:]
   134  
   135  	if len(src)%aes.BlockSize != 0 {
   136  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
   137  	}
   138  
   139  	mode := cipher.NewCBCDecrypter(block, iv)
   140  
   141  	mode.CryptBlocks(src, src)
   142  
   143  	return src, nil
   144  }
   145  
   146  // AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding
   147  func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
   148  	// First pad
   149  	tmp := pkcs7Padding(src)
   150  
   151  	// Then encrypt
   152  	return aesCBCEncrypt(key, tmp)
   153  }
   154  
   155  // AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding using as prng the passed to the function
   156  func AESCBCPKCS7EncryptWithRand(prng io.Reader, key, src []byte) ([]byte, error) {
   157  	// First pad
   158  	tmp := pkcs7Padding(src)
   159  
   160  	// Then encrypt
   161  	return aesCBCEncryptWithRand(prng, key, tmp)
   162  }
   163  
   164  // AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding, the IV used is the one passed to the function
   165  func AESCBCPKCS7EncryptWithIV(IV []byte, key, src []byte) ([]byte, error) {
   166  	// First pad
   167  	tmp := pkcs7Padding(src)
   168  
   169  	// Then encrypt
   170  	return aesCBCEncryptWithIV(IV, key, tmp)
   171  }
   172  
   173  // AESCBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
   174  func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
   175  	// First decrypt
   176  	pt, err := aesCBCDecrypt(key, src)
   177  	if err == nil {
   178  		return pkcs7UnPadding(pt)
   179  	}
   180  	return nil, err
   181  }
   182  
   183  type aescbcpkcs7Encryptor struct{}
   184  
   185  func (e *aescbcpkcs7Encryptor) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) ([]byte, error) {
   186  	switch o := opts.(type) {
   187  	case *bccsp.AESCBCPKCS7ModeOpts:
   188  		// AES in CBC mode with PKCS7 padding
   189  
   190  		if len(o.IV) != 0 && o.PRNG != nil {
   191  			return nil, errors.New("Invalid options. Either IV or PRNG should be different from nil, or both nil.")
   192  		}
   193  
   194  		if len(o.IV) != 0 {
   195  			// Encrypt with the passed IV
   196  			return AESCBCPKCS7EncryptWithIV(o.IV, k.(*aesPrivateKey).privKey, plaintext)
   197  		} else if o.PRNG != nil {
   198  			// Encrypt with PRNG
   199  			return AESCBCPKCS7EncryptWithRand(o.PRNG, k.(*aesPrivateKey).privKey, plaintext)
   200  		}
   201  		// AES in CBC mode with PKCS7 padding
   202  		return AESCBCPKCS7Encrypt(k.(*aesPrivateKey).privKey, plaintext)
   203  	case bccsp.AESCBCPKCS7ModeOpts:
   204  		return e.Encrypt(k, plaintext, &o)
   205  	default:
   206  		return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   207  	}
   208  }
   209  
   210  type aescbcpkcs7Decryptor struct{}
   211  
   212  func (*aescbcpkcs7Decryptor) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) ([]byte, error) {
   213  	// check for mode
   214  	switch opts.(type) {
   215  	case *bccsp.AESCBCPKCS7ModeOpts, bccsp.AESCBCPKCS7ModeOpts:
   216  		// AES in CBC mode with PKCS7 padding
   217  		return AESCBCPKCS7Decrypt(k.(*aesPrivateKey).privKey, ciphertext)
   218  	default:
   219  		return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   220  	}
   221  }