{"record":{"id":"e90c5bf340caa90f","repo":"golang/go","slug":"cipher-newgcmwithrandomnonce-requires-aes-block","errorCode":null,"errorMessage":"cipher: NewGCMWithRandomNonce requires aes.Block","messagePattern":"cipher: NewGCMWithRandomNonce requires aes\\.Block","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/cipher/gcm.go","lineNumber":92,"sourceCode":"\t\treturn nil, err\n\t}\n\treturn g, nil\n}\n\n// NewGCMWithRandomNonce returns the given cipher wrapped in Galois Counter\n// Mode, with randomly-generated nonces. The cipher must have been created by\n// [crypto/aes.NewCipher].\n//\n// It generates a random 96-bit nonce, which is prepended to the ciphertext by Seal,\n// and is extracted from the ciphertext by Open. The NonceSize of the AEAD is zero,\n// while the Overhead is 28 bytes (the combination of nonce size and tag size).\n//\n// A given key MUST NOT be used to encrypt more than 2^32 messages, to limit the\n// risk of a random nonce collision to negligible levels.\nfunc NewGCMWithRandomNonce(cipher Block) (AEAD, error) {\n\tc, ok := cipher.(*aes.Block)\n\tif !ok {\n\t\treturn nil, errors.New(\"cipher: NewGCMWithRandomNonce requires aes.Block\")\n\t}\n\tg, err := gcm.New(c, gcmStandardNonceSize, gcmTagSize)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn gcmWithRandomNonce{g}, nil\n}\n\ntype gcmWithRandomNonce struct {\n\t*gcm.GCM\n}\n\nfunc (g gcmWithRandomNonce) NonceSize() int {\n\treturn 0\n}\n\nfunc (g gcmWithRandomNonce) Overhead() int {\n\treturn gcmStandardNonceSize + gcmTagSize","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/cipher/gcm.go#L74-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nblock := &loggingBlock{inner: aesBlock} // wraps *aes.Block\na, err := cipher.NewGCMWithRandomNonce(block) // assertion fails\n\n// after: pass the bare *aes.Block\na, err := cipher.NewGCMWithRandomNonce(aesBlock)","handlingStrategy":"type-guard","validationCode":"func newRandomNonceAEAD(block cipher.Block) (cipher.AEAD, error) {\n    if _, ok := block.(*aes.Block); !ok {\n        return nil, errors.New(\"NewGCMWithRandomNonce requires *aes.Block\")\n    }\n    return cipher.NewGCMWithRandomNonce(block)\n}","typeGuard":"func isAESBlock(b cipher.Block) bool {\n    _, ok := b.(*aes.Block)\n    return ok\n}","tryCatchPattern":"a, err := cipher.NewGCMWithRandomNonce(block)\nif err != nil && strings.Contains(err.Error(), \"requires aes.Block\") {\n    // Reconstruct from key via aes.NewCipher and retry.\n}","preventionTips":["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."],"tags":["crypto","aes","gcm","type-assertion","constructor"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}