package utils import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" "io" ) // Encrypt encrypts plain text using AES-GCM with the given 32-byte key. func Encrypt(plainText string, key []byte) (string, error) { if len(key) != 32 { return "", fmt.Errorf("encryption key must be 32 bytes") } block, err := aes.NewCipher(key) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } nonce := make([]byte, gcm.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return "", err } // The nonce should be prepended to the ciphertext cipherText := gcm.Seal(nonce, nonce, []byte(plainText), nil) return base64.StdEncoding.EncodeToString(cipherText), nil } // Decrypt decrypts base64-encoded cipher text using AES-GCM with the given 32-byte key. func Decrypt(encodedCipherText string, key []byte) (string, error) { if len(key) != 32 { return "", fmt.Errorf("encryption key must be 32 bytes") } cipherText, err := base64.StdEncoding.DecodeString(encodedCipherText) if err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } nonceSize := gcm.NonceSize() if len(cipherText) < nonceSize { return "", fmt.Errorf("cipher text too short") } nonce, actualCipherText := cipherText[:nonceSize], cipherText[nonceSize:] plainText, err := gcm.Open(nil, nonce, actualCipherText, nil) if err != nil { return "", err } return string(plainText), nil }