github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/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  	if len(s)%aes.BlockSize != 0 {
    76  		return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
    77  	}
    78  
    79  	block, err := aes.NewCipher(key)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	ciphertext := make([]byte, aes.BlockSize+len(s))
    85  	iv := ciphertext[:aes.BlockSize]
    86  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	mode := cipher.NewCBCEncrypter(block, iv)
    91  	mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
    92  
    93  	return ciphertext, nil
    94  }
    95  
    96  func aesCBCDecrypt(key, src []byte) ([]byte, error) {
    97  	block, err := aes.NewCipher(key)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	if len(src) < aes.BlockSize {
   103  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
   104  	}
   105  	iv := src[:aes.BlockSize]
   106  	src = src[aes.BlockSize:]
   107  
   108  	if len(src)%aes.BlockSize != 0 {
   109  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
   110  	}
   111  
   112  	mode := cipher.NewCBCDecrypter(block, iv)
   113  
   114  	mode.CryptBlocks(src, src)
   115  
   116  	return src, nil
   117  }
   118  
   119  // AESCBCPKCS7Encrypt combines CBC encryption and PKCS7 padding
   120  func AESCBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
   121  	// First pad
   122  	tmp := pkcs7Padding(src)
   123  
   124  	// Then encrypt
   125  	return aesCBCEncrypt(key, tmp)
   126  }
   127  
   128  // AESCBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
   129  func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
   130  	// First decrypt
   131  	pt, err := aesCBCDecrypt(key, src)
   132  	if err == nil {
   133  		return pkcs7UnPadding(pt)
   134  	}
   135  	return nil, err
   136  }
   137  
   138  type aescbcpkcs7Encryptor struct{}
   139  
   140  func (*aescbcpkcs7Encryptor) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) {
   141  	switch opts.(type) {
   142  	case *bccsp.AESCBCPKCS7ModeOpts, bccsp.AESCBCPKCS7ModeOpts:
   143  		// AES in CBC mode with PKCS7 padding
   144  		return AESCBCPKCS7Encrypt(k.(*aesPrivateKey).privKey, plaintext)
   145  	default:
   146  		return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   147  	}
   148  }
   149  
   150  type aescbcpkcs7Decryptor struct{}
   151  
   152  func (*aescbcpkcs7Decryptor) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) {
   153  	// check for mode
   154  	switch opts.(type) {
   155  	case *bccsp.AESCBCPKCS7ModeOpts, bccsp.AESCBCPKCS7ModeOpts:
   156  		// AES in CBC mode with PKCS7 padding
   157  		return AESCBCPKCS7Decrypt(k.(*aesPrivateKey).privKey, ciphertext)
   158  	default:
   159  		return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   160  	}
   161  }