golang/go · error
crypto/cipher: incorrect nonce length given to SetNoncePrefi
Error message
crypto/cipher: incorrect nonce length given to SetNoncePrefixAndMask
What it means
Returned by GCMWithXORCounterNonce.SetNoncePrefixAndMask (the XOR-counter nonce variant used by QUIC) when the supplied nonce is not exactly gcmStandardNonceSize (12) bytes. The first 4 bytes are the fixed prefix and the last 8 bytes are the XOR mask, so a 12-byte input is mandatory.
Source
Thrown at src/crypto/internal/fips140/aes/gcm/gcm_nonces.go:231
g GCM
ready bool
prefix uint32
mask uint64
next uint64
}
// SetNoncePrefixAndMask sets the fixed prefix and XOR mask for the nonces used
// in Seal. It must be called before the first call to Seal.
//
// The first 32 bits of nonce are used as the fixed prefix, and the last 64 bits
// are used as the XOR mask.
//
// Note that Seal expects the nonce to be already XOR'd with the mask. The mask
// is provided here only to allow Seal to enforce that the counter is strictly
// increasing.
func (g *GCMWithXORCounterNonce) SetNoncePrefixAndMask(nonce []byte) error {
if len(nonce) != gcmStandardNonceSize {
return errors.New("crypto/cipher: incorrect nonce length given to SetNoncePrefixAndMask")
}
if g.ready {
return errors.New("crypto/cipher: SetNoncePrefixAndMask called twice or after first Seal")
}
g.prefix = byteorder.BEUint32(nonce[:4])
g.mask = byteorder.BEUint64(nonce[4:])
g.ready = true
return nil
}
func (g *GCMWithXORCounterNonce) NonceSize() int { return gcmStandardNonceSize }
func (g *GCMWithXORCounterNonce) Overhead() int { return gcmTagSize }
// Seal implements the [cipher.AEAD] interface, checking that the nonce prefix
// is stable and that the counter is strictly increasing.
//
// It is not safe for concurrent use.View on GitHub (pinned to b6b368adc5)
Solutions
- Ensure the IV is exactly 12 bytes (gcmStandardNonceSize).
- Prefer NewGCMForQUIC(cipher, iv) and validate iv length at the call site.
- If the source material is shorter/longer, derive a 12-byte value via HKDF rather than padding naively.
Example fix
// before
g.SetNoncePrefixAndMask(connID) // connID may be 8 or 20 bytes
// after
iv := make([]byte, 12)
hkdf.Expand(h, secret, []byte("quic iv")).Read(iv)
g.SetNoncePrefixAndMask(iv) Defensive patterns
Strategy: validation
Validate before calling
func validQUICNonce(iv []byte) bool { return len(iv) == 12 }
if !validQUICNonce(iv) { return errors.New("QUIC IV must be 12 bytes") }
g, err := gcm.NewGCMForQUIC(block, iv) Type guard
// n/a
Try / catch
if err := g.SetNoncePrefixAndMask(iv); err != nil {
return fmt.Errorf("set nonce prefix: %w", err)
} Prevention
- Derive the 12-byte QUIC IV via HKDF-Expand from the connection secret.
- Validate IV length at the QUIC handshake boundary.
- Do not pass raw connection IDs as IVs.
When it happens
Trigger: Calling g.SetNoncePrefixAndMask(iv) with len(iv) != 12, or indirectly via NewGCMForQUIC(cipher, iv) with a wrong-length iv.
Common situations: Passing a QUIC connection ID-derived IV that was not padded/truncated to 12 bytes; passing a 16-byte AES-GCM IV by mistake; config-derived IV whose length varies.
Related errors
- cipher: incorrect tag size given to GCM
- cipher: the nonce can't have zero length
- cipher: NewGCM requires 128-bit block cipher
- crypto/cipher: SetNoncePrefixAndMask called twice or after f
- crypto/aes: GCM tag and nonce sizes can't be non-standard at
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/e73c0da5f185e9e9.
Report an issue: GitHub.