golang/go · error
cipher: NewGCMWithRandomNonce requires aes.Block
Error message
cipher: NewGCMWithRandomNonce requires aes.Block
What it means
NewGCMWithRandomNonce requires its argument to be *aes.Block because the underlying gcm.New implementation is hard-coded to the AES round structure for the GHASH multiply. The constructor type-asserts unconditionally (no FIPS gating needed) and returns this error if the assertion fails.
Source
Thrown at src/crypto/cipher/gcm.go:92
return nil, err
}
return g, nil
}
// NewGCMWithRandomNonce returns the given cipher wrapped in Galois Counter
// Mode, with randomly-generated nonces. The cipher must have been created by
// [crypto/aes.NewCipher].
//
// It generates a random 96-bit nonce, which is prepended to the ciphertext by Seal,
// and is extracted from the ciphertext by Open. The NonceSize of the AEAD is zero,
// while the Overhead is 28 bytes (the combination of nonce size and tag size).
//
// A given key MUST NOT be used to encrypt more than 2^32 messages, to limit the
// risk of a random nonce collision to negligible levels.
func NewGCMWithRandomNonce(cipher Block) (AEAD, error) {
c, ok := cipher.(*aes.Block)
if !ok {
return nil, errors.New("cipher: NewGCMWithRandomNonce requires aes.Block")
}
g, err := gcm.New(c, gcmStandardNonceSize, gcmTagSize)
if err != nil {
return nil, err
}
return gcmWithRandomNonce{g}, nil
}
type gcmWithRandomNonce struct {
*gcm.GCM
}
func (g gcmWithRandomNonce) NonceSize() int {
return 0
}
func (g gcmWithRandomNonce) Overhead() int {
return gcmStandardNonceSize + gcmTagSizeView on GitHub (pinned to b6b368adc5)
Solutions
- Pass the *aes.Block returned directly by aes.NewCipher — do not wrap or re-typedef it.
- If you need instrumentation, instrument aes.NewCipher at construction time and return the original *aes.Block to the AEAD layer.
- For test fakes, build a real AES key for tests rather than a fake Block.
Example fix
// before
block := &loggingBlock{inner: aesBlock} // wraps *aes.Block
a, err := cipher.NewGCMWithRandomNonce(block) // assertion fails
// after: pass the bare *aes.Block
a, err := cipher.NewGCMWithRandomNonce(aesBlock) Defensive patterns
Strategy: type-guard
Validate before calling
func newRandomNonceAEAD(block cipher.Block) (cipher.AEAD, error) {
if _, ok := block.(*aes.Block); !ok {
return nil, errors.New("NewGCMWithRandomNonce requires *aes.Block")
}
return cipher.NewGCMWithRandomNonce(block)
} Type guard
func isAESBlock(b cipher.Block) bool {
_, ok := b.(*aes.Block)
return ok
} Try / catch
a, err := cipher.NewGCMWithRandomNonce(block)
if err != nil && strings.Contains(err.Error(), "requires aes.Block") {
// Reconstruct from key via aes.NewCipher and retry.
} Prevention
- Always thread the *aes.Block from aes.NewCipher directly — do not wrap it.
- If you need logging, instrument key generation, not the Block value.
- Add a type assertion test in your crypto-wrapper tests.
When it happens
Trigger: Calling cipher.NewGCMWithRandomNonce(block) where block was not produced by crypto/aes.NewCipher. Custom cipher.Block implementations, third-party block ciphers, and even wrapped AES blocks fail the assertion.
Common situations: Wrapping *aes.Block in another type for instrumentation/logging, passing a test fake that satisfies cipher.Block, or accidentally using a different algorithm's NewCipher function.
Related errors
- crypto/cipher: use of GCM with non-AES ciphers is not allowe
- crypto/cipher: use of GCM with arbitrary IVs is not allowed
- cipher: NewGCM requires 128-bit block cipher
- crypto/aes: GCM tag and nonce sizes can't be non-standard at
- cipher: message authentication failed
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/e90c5bf340caa90f.
Report an issue: GitHub.