package crypto import ( "crypto/cipher" "crypto/rand" "encoding/base64" "encoding/json" "fmt" "io" ) func packCipherData(cipherText, iv []byte) ([]byte, error) { return json.Marshal([]string{ base64.StdEncoding.EncodeToString(cipherText), base64.StdEncoding.EncodeToString(iv), }) } func unpackCipherData(data []byte) ([]byte, []byte, error) { var cipherData []string err := json.Unmarshal(data, &cipherData) if err != nil { return nil, nil, err } if len(cipherData) != 2 { return nil, nil, fmt.Errorf("invalid cipher data") } cipherText, err := base64.StdEncoding.DecodeString(cipherData[0]) if err != nil { return nil, nil, err } iv, err := base64.StdEncoding.DecodeString(cipherData[1]) if err != nil { return nil, nil, err } return cipherText, iv, nil } func EncryptAesCbc(aes cipher.Block, plainTextBytes []byte) ([]byte, error) { iv := make([]byte, 16) if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } encrypter := cipher.NewCBCEncrypter(aes, iv) plainTextBytes, err := pkcs7Pad(plainTextBytes, encrypter.BlockSize()) if err != nil { return nil, err } cipherText := make([]byte, len(plainTextBytes)) encrypter.CryptBlocks(cipherText, plainTextBytes) return packCipherData(cipherText, iv) } func DecryptAesCbc(aes cipher.Block, data []byte) ([]byte, error) { encrypted, iv, err := unpackCipherData(data) if err != nil { return nil, err } decryptor := cipher.NewCBCDecrypter(aes, iv) decryptedBytes := make([]byte, len(encrypted)) decryptor.CryptBlocks(decryptedBytes, encrypted) decryptedBytes, err = pkcs7Unpad(decryptedBytes, decryptor.BlockSize()) if err != nil { return nil, err } return decryptedBytes, nil }