github.com/s7techlab/cckit@v0.10.5/extensions/encryption/aes.go (about)

     1  package encryption
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  // From bccsp/sw/aes
    11  func pkcs7Padding(src []byte) []byte {
    12  	padding := aes.BlockSize - len(src)%aes.BlockSize
    13  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    14  	return append(src, padtext...)
    15  }
    16  
    17  func pkcs7UnPadding(src []byte) ([]byte, error) {
    18  	length := len(src)
    19  	unpadding := int(src[length-1])
    20  
    21  	if unpadding > aes.BlockSize || unpadding == 0 {
    22  		return nil, errors.New("Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)")
    23  	}
    24  
    25  	pad := src[len(src)-unpadding:]
    26  	for i := 0; i < unpadding; i++ {
    27  		if pad[i] != byte(unpadding) {
    28  			return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)")
    29  		}
    30  	}
    31  
    32  	return src[:(length - unpadding)], nil
    33  }
    34  
    35  func aesCBCEncryptWithIV(IV []byte, key, s []byte) ([]byte, error) {
    36  	if len(s)%aes.BlockSize != 0 {
    37  		return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
    38  	}
    39  
    40  	if len(IV) != aes.BlockSize {
    41  		return nil, errors.New("Invalid IV. It must have length the block size")
    42  	}
    43  
    44  	block, err := aes.NewCipher(key)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	ciphertext := make([]byte, aes.BlockSize+len(s))
    50  	copy(ciphertext[:aes.BlockSize], IV)
    51  
    52  	mode := cipher.NewCBCEncrypter(block, IV)
    53  	mode.CryptBlocks(ciphertext[aes.BlockSize:], s)
    54  
    55  	return ciphertext, nil
    56  }
    57  
    58  // AESCBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
    59  func AESCBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
    60  	// First decrypt
    61  	pt, err := aesCBCDecrypt(key, src)
    62  	if err == nil {
    63  		return pkcs7UnPadding(pt)
    64  	}
    65  	return nil, err
    66  }
    67  
    68  func aesCBCDecrypt(key, src []byte) ([]byte, error) {
    69  	block, err := aes.NewCipher(key)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	if len(src) < aes.BlockSize {
    75  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
    76  	}
    77  	iv := src[:aes.BlockSize]
    78  	src = src[aes.BlockSize:]
    79  
    80  	if len(src)%aes.BlockSize != 0 {
    81  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
    82  	}
    83  
    84  	mode := cipher.NewCBCDecrypter(block, iv)
    85  
    86  	mode.CryptBlocks(src, src)
    87  
    88  	return src, nil
    89  }
    90  
    91  func EncryptBytes(key, value []byte) ([]byte, error) {
    92  	// IV temporary blank
    93  	return aesCBCEncryptWithIV(make([]byte, 16), key, pkcs7Padding(value))
    94  }
    95  
    96  func DecryptBytes(key, value []byte) ([]byte, error) {
    97  	return AESCBCPKCS7Decrypt(key, value)
    98  }