golang/go · critical
cipher: message authentication failed
Error message
cipher: message authentication failed
What it means
errOpen is the sentinel returned by gcmFallback.Open (GCM decryption) when authentication fails. In the shown region it fires when the ciphertext is shorter than the configured tag size; the same error is returned later when the recomputed GCM authentication tag does not match the tag embedded in the ciphertext, which signals tampering or a key/nonce/additional-data mismatch.
Source
Thrown at src/crypto/cipher/gcm.go:269
if alias.AnyOverlap(out, additionalData) {
panic("crypto/cipher: invalid buffer overlap of output and additional data")
}
var H, counter, tagMask [gcmBlockSize]byte
g.cipher.Encrypt(H[:], H[:])
deriveCounter(&H, &counter, nonce)
gcmCounterCryptGeneric(g.cipher, tagMask[:], tagMask[:], &counter)
gcmCounterCryptGeneric(g.cipher, out, plaintext, &counter)
var tag [gcmTagSize]byte
gcmAuth(tag[:], &H, &tagMask, out[:len(plaintext)], additionalData)
copy(out[len(plaintext):], tag[:])
return ret
}
var errOpen = errors.New("cipher: message authentication failed")
func (g *gcmFallback) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
if len(nonce) != g.nonceSize {
panic("crypto/cipher: incorrect nonce length given to GCM")
}
if g.tagSize < gcmMinimumTagSize {
panic("crypto/cipher: incorrect GCM tag size")
}
if len(ciphertext) < g.tagSize {
return nil, errOpen
}
if uint64(len(ciphertext)) > uint64((1<<32)-2)*gcmBlockSize+uint64(g.tagSize) {
return nil, errOpen
}
ret, out := sliceForAppend(dst, len(ciphertext)-g.tagSize)
if alias.InexactOverlap(out, ciphertext) {View on GitHub (pinned to b6b368adc5)
Solutions
- Verify the full ciphertext including the trailing tag is passed unmodified to Open.
- Ensure encrypt and decrypt sides use the exact same key, nonce, and additionalData.
- Never reuse a nonce with the same key; generate a fresh random 12-byte nonce per message.
- Treat this error as a security event (possible forgery); do not silently retry or strip the tag.
Defensive patterns
Strategy: try-catch
Try / catch
plaintext, err := gcm.Open(nil, nonce, ciphertext, aad)
if err != nil {
if errors.Is(err, cipher.ErrAuth) /* or the package's auth sentinel */ {
// Authentication failure: treat as tampering/forgery. Do NOT retry
// with truncated tags or fall back; log and reject the message.
return ErrCiphertextRejected
}
return err
} Prevention
- Generate a fresh random 12-byte nonce per message and transmit it alongside the ciphertext.
- Pin the same additionalData on both encrypt and decrypt sides; treat it as part of the contract.
- Never reuse a (key, nonce) pair; rotate keys if a nonce collision is possible.
- Log authentication failures as security events, not routine errors.
When it happens
Trigger: Calling gcm.Open(...) with len(ciphertext) < g.tagSize; or with ciphertext whose trailing tag bytes do not match the tag recomputed from the plaintext, nonce, key, or additionalData.
Common situations: Truncated ciphertext in transit; bit-flips or corruption on the wire; nonce reuse across messages under the same key; decrypting with the wrong key; passing different additionalData than was used at encryption time.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- cipher: message authentication failed
- cipher: NewGCM requires 128-bit block cipher
- crypto/des: use of DES is not allowed in FIPS 140-only mode
- crypto/des: use of TripleDES is not allowed in FIPS 140-only
- crypto/dsa: invalid public key
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/2a69c5283a3a9c67.
Report an issue: GitHub.