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