{"record":{"id":"071aa8b52d40208a","repo":"FiloSottile/age","slug":"failed-to-decrypt-and-authenticate-final-chunk-w","errorCode":null,"errorMessage":"failed to decrypt and authenticate final chunk: %w","messagePattern":"failed to decrypt and authenticate final chunk: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/stream/stream.go","lineNumber":402,"sourceCode":"\t}\n\n\t// Check that size is valid by decrypting the final chunk.\n\tchunks, err := EncryptedChunkCount(size)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfinalChunkIndex := chunks - 1\n\tfinalChunkOff := finalChunkIndex * encChunkSize\n\tfinalChunkSize := size - finalChunkOff\n\tfinalChunk := make([]byte, finalChunkSize)\n\tif err := readFullAt(src, finalChunk, finalChunkOff); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read final chunk: %w\", err)\n\t}\n\tnonce := nonceForChunk(finalChunkIndex)\n\tsetLastChunkFlag(nonce)\n\tplaintext, err := aead.Open(finalChunk[:0], nonce[:], finalChunk, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decrypt and authenticate final chunk: %w\", err)\n\t}\n\tcache := &cachedChunk{off: finalChunkOff, data: plaintext}\n\n\tplaintextSize := size - chunks*chacha20poly1305.Overhead\n\tr := &DecryptReaderAt{a: aead, src: src, size: plaintextSize, chunks: chunks}\n\tr.cache.Store(cache)\n\treturn r, nil\n}\n\nfunc (r *DecryptReaderAt) ReadAt(p []byte, off int64) (n int, err error) {\n\tif off < 0 || off > r.size {\n\t\treturn 0, fmt.Errorf(\"offset out of range [0:%d]: %d\", r.size, off)\n\t}\n\tif len(p) == 0 {\n\t\treturn 0, nil\n\t}\n\tvar cacheUpdate *cachedChunk\n\tchunk := make([]byte, encChunkSize)","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/internal/stream/stream.go#L384-L420","documentation":"NewDecryptReaderAt authenticates the final chunk with ChaCha20Poly1305 using the last-chunk nonce. This error means the final chunk's ciphertext failed AEAD verification: the data is not the authentic final chunk for this key. Unlike error [73], the bytes were read successfully but decryption/authentication failed, which age treats as corruption or tampering (or a wrong key).","triggerScenarios":"NewDecryptReaderAt(key, src, size) where aead.Open on the final chunk (nonce = chunk index with last-chunk flag) fails: wrong key, wrong size causing the wrong 'final chunk' window, or ciphertext modified in place.","commonSituations":"Decrypting with the wrong key/identity; the ciphertext file was edited, corrupted in transit, or re-padded; the file was produced by a different scheme or a different final-chunk convention; using a stale size with a rewritten file.","solutions":["Confirm you are using the correct key for this recipient/file; wrong keys surface as authentication failure.","Verify the ciphertext is byte-for-byte intact (checksum against the source of truth); re-download or restore if corrupted.","Ensure the size argument matches this exact ciphertext version; a mismatched size shifts the final-chunk offset and guarantees failure.","If files come from a mixed toolchain, re-encrypt with the same age STREAM implementation to rule out incompatibilities."],"exampleFix":"// before\nkey := deriveKey(wrongPassphrase)\nr, err := stream.NewDecryptReaderAt(key, f, size)\n// after\nkey := deriveKey(correctPassphrase) // verify key provenance\nr, err := stream.NewDecryptReaderAt(key, f, size)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"r, err := stream.NewDecryptReaderAt(key, src, size)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to decrypt and authenticate final chunk\") {\n        return fmt.Errorf(\"wrong key or corrupted ciphertext: %w\", err)\n    }\n    return err\n}","preventionTips":["Verify the key/identity matches the recipient before decrypting.","Keep ciphertext files immutable while in use (no in-place edits).","Ship and verify checksums alongside ciphertext to detect transport corruption.","Use one consistent encryption toolchain/version."],"tags":["stream","crypto","authentication","corrupt-data","go"],"backgroundTag":"aead-authentication-failed","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}