package myth import ( "bytes" "crypto/aes" "crypto/cipher" "errors" ) var ( aesKey string aesIV string ) // AesCrypto define type AesCrypto struct { Key []byte IV []byte } // SetAesCryptoKey set key, // key/iv length:16, 24, 32 bytes to AES-128, AES-192, AES-256 func SetAesCryptoKey(password, iv string) { aesKey = password aesIV = iv } // GetAesCryptoKey get current key/iv func GetAesCryptoKey() (string, string) { return aesKey, aesIV } // NewAesCrypto new AesCrypto func NewAesCrypto() *AesCrypto { return &AesCrypto{Key: []byte(aesKey), IV: []byte(aesIV)} } // SetKey set key func (a *AesCrypto) SetKey(key, iv string) { a.Key = []byte(key) a.IV = []byte(iv) } // Encrypt encrypt data func (a *AesCrypto) Encrypt(data []byte) ([]byte, error) { block, err := aes.NewCipher(a.Key) if err != nil { return nil, err } blockSize := block.BlockSize() data = pkcs7Padding(data, blockSize) blockMode := cipher.NewCBCEncrypter(block, a.IV[:blockSize]) crypted := make([]byte, len(data)) blockMode.CryptBlocks(crypted, data) return crypted, nil } // Decrypt decrypt data func (a *AesCrypto) Decrypt(crypted []byte) ([]byte, error) { block, err := aes.NewCipher(a.Key) if err != nil { return nil, err } n := len(crypted) blockSize := block.BlockSize() if n%blockSize != 0 { return nil, errors.New(`crypto/cipher: input not full blocks`) } blockMode := cipher.NewCBCDecrypter(block, a.IV[:blockSize]) origData := make([]byte, n) blockMode.CryptBlocks(origData, crypted) origData = pkcs7UnPadding(origData) return origData, nil } func pkcs7Padding(cipherText []byte, blockSize int) []byte { padding := blockSize - len(cipherText)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(cipherText, padtext...) } func pkcs7UnPadding(data []byte) []byte { length := len(data) unpadding := int(data[length-1]) if unpadding >= length { return []byte(``) } return data[:(length - unpadding)] }