When confidentiality is required, use an authenticated-encryption API rather than combining an arbitrary cipher with a checksum. This lesson uses AES-GCM through Go’s nonce-managing wrapper.
The API requires Go 1.24 or later. It generates and prepends the random nonce during Seal and extracts it during Open. The application does not accept a caller nonce, reducing a common misuse surface.
For this particular wrapper, NonceSize is zero and callers pass nil as the nonce argument. The sealed result includes 12 nonce bytes and 16 tag bytes, so overhead is 28. This does not mean ordinary GCM can reuse a fixed zero nonce.
The exercise supplies key construction and Seal. Complete bounded Open, including AAD and error handling. A changed key, ciphertext, tag or AAD must fail without returning trusted plaintext.
package main
import ("fmt";"crypto/aes";"crypto/cipher")
func main(){
block,_:=aes.NewCipher(make([]byte,32));aead,_:=cipher.NewGCMWithRandomNonce(block);sealed:=aead.Seal(nil,nil,[]byte("record"),[]byte("lab.notes"));plain,err:=aead.Open(nil,nil,sealed,[]byte("lab.notes"));fmt.Println(len(sealed),string(plain),err==nil)
}The public tests include two published AES-256-GCM decryption vectors from BoringSSL’s test corpus. Their fixed all-zero key/nonce combinations are interoperability fixtures, not application secrets or a repeated encryption strategy.
Application encryption uses secure random key generation and the library’s random nonce. Go documents a per-key maximum of 2^32 messages for this wrapper; a real application must enforce a rotation/usage policy before reaching that bound. This small exercise does not claim to implement a key-management service.
A valid empty plaintext is distinct from authentication failure. Always inspect the error. The wrapper normalizes failed authentication to one error and returns no plaintext bytes.
package main
import ("fmt";"crypto/aes";"crypto/cipher")
func main(){
block,_:=aes.NewCipher(make([]byte,32));aead,_:=cipher.NewGCMWithRandomNonce(block);sealed:=aead.Seal(nil,nil,nil,nil);plain,err:=aead.Open(nil,nil,sealed,nil);fmt.Println(len(plain),err==nil)
}Complete Open and test published vectors, empty/exact-limit plaintext, changed AAD, wrong key, a flipped tag and truncated input. Do not expose unauthenticated output.
Next we separate password-storage policy from these ordinary hash/MAC/encryption operations.