AES-GCM Encryption and Decryption (Authenticated)
Helper for encrypting and decrypting byte slices with AES-GCM using random nonces and returning nonce plus ciphertext payloads.
main.go
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"log"
)
func encryptAESGCM(key, plaintext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
out := append(nonce, ciphertext...)
return out, nil
}
func decryptAESGCM(key, payload []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(payload) < gcm.NonceSize() {
return nil, fmt.Errorf("payload too short")
}
nonce := payload[:gcm.NonceSize()]
ciphertext := payload[gcm.NonceSize():]
return gcm.Open(nil, nonce, ciphertext, nil)
}
func main() {
key := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
log.Fatalf("key: %v", err)
}
plaintext := []byte("secret message")
payload, err := encryptAESGCM(key, plaintext)
if err != nil {
log.Fatalf("encrypt: %v", err)
}
log.Printf("payload(b64)=%s", base64.RawStdEncoding.EncodeToString(payload))
decoded, err := decryptAESGCM(key, payload)
if err != nil {
log.Fatalf("decrypt: %v", err)
}
log.Printf("decoded=%q", string(decoded))
}How It Works
Helper for encrypting and decrypting byte slices with AES-GCM using random nonces and returning nonce plus ciphertext payloads.
Generates a random 32-byte key and 12-byte nonce, creates a GCM cipher, seals plaintext into a combined buffer, and later splits the nonce to call Open and verify authenticity.
Key Concepts
- 1Authenticated encryption prevents tampering and detects corruption.
- 2Random nonce per message is mandatory for GCM security.
- 3Payload layout of nonce followed by ciphertext simplifies storage or transport.
When to Use This Pattern
- Encrypting secrets before persisting them.
- Securing messages exchanged between services.
- Protecting files or blobs stored in object storage.
Best Practices
- Never reuse a nonce with the same key.
- Store keys securely and rotate periodically.
- Check errors from Open and refuse to use unauthenticated data.
Go Version1.18+
Difficultyintermediate
Production ReadyYes
Lines of Code70