package crypto import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" "io" ) // Base64AESEncode AES encode func Base64AESEncode(key []byte, text string) (string, error) { plaintext := []byte(text) block, err := aes.NewCipher(key) if err != nil { return "", err } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. ciphertext := make([]byte, aes.BlockSize+len(plaintext)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return "", err } stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) // convert to base64 return base64.StdEncoding.EncodeToString(ciphertext), nil } // Base64AESDecode AES decode func Base64AESDecode(key []byte, cryptoText string) (string, error) { ciphertext, _ := base64.StdEncoding.DecodeString(cryptoText) block, err := aes.NewCipher(key) if err != nil { return "", err } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. if len(ciphertext) < aes.BlockSize { return "", fmt.Errorf("ciphertext too short") } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] stream := cipher.NewCFBDecrypter(block, iv) // XORKeyStream can work in-place if the two arguments are the same. stream.XORKeyStream(ciphertext, ciphertext) return fmt.Sprintf("%s", ciphertext), nil }