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 + gcmTagSize

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pass the *aes.Block returned directly by aes.NewCipher — do not wrap or re-typedef it.
  2. If you need instrumentation, instrument aes.NewCipher at construction time and return the original *aes.Block to the AEAD layer.
  3. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/e90c5bf340caa90f. Report an issue: GitHub.