github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/xcrypt/aes.go (about) 1 package xcrypt 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "encoding/hex" 8 "errors" 9 ) 10 11 const AesCipherKeySize = 32 // aes key size, 256 bit 12 13 // AesEncryptRaw encrypt original `data` with `key` and initializer vector `iv` 14 // iv should have at least `aes.BlockSize` length 15 func AesEncryptRaw(data []byte, key []byte, iv []byte) ([]byte, error) { 16 if len(key) < AesCipherKeySize { 17 return nil, errors.New("err: key too short, length less than 32") 18 } 19 key = key[:AesCipherKeySize] 20 if len(iv) < aes.BlockSize { 21 return nil, errors.New("err: cipher iv too short, length less than 16") 22 } 23 iv = iv[:aes.BlockSize] 24 block, _ := aes.NewCipher(key) // ignore not reachable error 25 blockMode := cipher.NewCBCEncrypter(block, iv) 26 encodedData := pkcs5Padding(data, block.BlockSize()) 27 encryptedData := make([]byte, len(encodedData)) 28 blockMode.CryptBlocks(encryptedData, encodedData) 29 dst := make([]byte, hex.EncodedLen(len(encryptedData))) 30 hex.Encode(dst, encryptedData) 31 return dst, nil 32 } 33 34 // AesDecryptRaw decrypt original `data` with `key` and initializer vector `iv` 35 // iv should have at least `aes.BlockSize` length 36 func AesDecryptRaw(data []byte, key []byte, iv []byte) ([]byte, error) { 37 if len(key) < AesCipherKeySize { 38 return nil, errors.New("err: key too short, length less than 32") 39 } 40 key = key[:AesCipherKeySize] 41 if len(iv) < aes.BlockSize { 42 return nil, errors.New("err: cipher iv too short, length less than 16") 43 } 44 iv = iv[:aes.BlockSize] 45 decodedLen := hex.DecodedLen(len(data)) 46 decodedData := make([]byte, decodedLen) 47 if _, err := hex.Decode(decodedData, data); err != nil { 48 return nil, err 49 } 50 block, _ := aes.NewCipher(key) // ignore not reachable error 51 blockMode := cipher.NewCBCDecrypter(block, iv) 52 blockMode.CryptBlocks(decodedData, decodedData) 53 return pkcs5UnPadding(decodedData[:decodedLen]), nil 54 } 55 56 func pkcs5Padding(cipherText []byte, blockSize int) []byte { 57 padding := blockSize - len(cipherText)%blockSize 58 padText := bytes.Repeat([]byte{byte(padding)}, padding) 59 return append(cipherText, padText...) 60 } 61 62 func pkcs5UnPadding(origData []byte) []byte { 63 length := len(origData) 64 unpadding := int(origData[length-1]) 65 return origData[:(length - unpadding)] 66 }