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 }