golang/go · error
mlkem: inconsistent H(ek) in encoded bytes
Error message
mlkem: inconsistent H(ek) in encoded bytes
What it means
Thrown by TestingOnlyNewDecapsulationKey1024 when the 32-byte H(ek) digest embedded in the NIST blob does not match SHA3-256 of the encapsulation-key portion just parsed. FIPS 203 binds the decapsulation key to its public counterpart via this hash; a mismatch means the blob is internally inconsistent (the sk and ek halves are not from the same keypair).
Source
Thrown at src/crypto/internal/fips140/mlkem/mlkem1024.go:187
var err error
dk.s[i], err = polyByteDecode[nttElement](b[:encodingSize12])
if err != nil {
return nil, errors.New("mlkem: invalid secret key encoding")
}
b = b[encodingSize12:]
}
ek, err := NewEncapsulationKey1024(b[:EncapsulationKeySize1024])
if err != nil {
return nil, err
}
dk.ρ = ek.ρ
dk.h = ek.h
dk.encryptionKey1024 = ek.encryptionKey1024
b = b[EncapsulationKeySize1024:]
if !bytes.Equal(dk.h[:], b[:32]) {
return nil, errors.New("mlkem: inconsistent H(ek) in encoded bytes")
}
b = b[32:]
copy(dk.z[:], b)
// Generate a random d value for use in Bytes(). This is a safety mechanism
// that avoids returning a broken key vs a random key if this function is
// called in contravention of the TestingOnlyNewDecapsulationKey1024 function
// comment advising against it.
drbg.Read(dk.d[:])
return dk, nil
}
// kemKeyGen1024 generates a decapsulation key.
//
// It implements ML-KEM.KeyGen_internal according to FIPS 203, Algorithm 16, and
// K-PKE.KeyGen according to FIPS 203, Algorithm 13. The two are merged to saveView on GitHub (pinned to b6b368adc5)
Solutions
- Re-derive the blob from a single keypair so H(ek) is recomputed over the exact ek bytes embedded.
- Validate the 32-byte hash field equals sha3.Sum256(ek_bytes) before calling the constructor.
- Prefer NewDecapsulationKey1024 with the 64-byte seed so all derived fields stay consistent.
- Discard hand-assembled blobs; obtain fresh ACVP vectors from a vetted source.
Example fix
// before
dk, err := mlkem1024.TestingOnlyNewDecapsulationKey1024(assembled) // H(ek) stale
// after
h := sha3.New256()
h.Write(assembled[offset : offset+EncapsulationKeySize1024])
want := h.Sum(nil)
if !bytes.Equal(want, assembled[hashOff:hashOff+32]) {
return errors.New("blob hash field stale; regenerate")
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the embedded H(ek) field against the ek half of the blob.
import "golang.org/x/crypto/sha3"
ekStart := k*encodingSize12 // after s-vector
ekEnd := ekStart + mlkem1024.EncapsulationKeySize1024
h := sha3.New256(); h.Write(b[ekStart:ekEnd])
want := h.Sum(nil)
if !bytes.Equal(want, b[ekEnd:ekEnd+32]) {
return errors.New("H(ek) inconsistent; regenerate blob")
} Type guard
func blobHashConsistent(b []byte) bool {
ekStart := 2*encodingSize12 // k=2 for 1024
h := sha3.New256(); h.Write(b[ekStart : ekStart+mlkem1024.EncapsulationKeySize1024])
return bytes.Equal(h.Sum(nil), b[ekStart+mlkem1024.EncapsulationKeySize1024:ekStart+mlkem1024.EncapsulationKeySize1024+32])
} Try / catch
dk, err := mlkem1024.TestingOnlyNewDecapsulationKey1024(b)
if err != nil && strings.Contains(err.Error(), "inconsistent H(ek)") {
return errors.New("blob is internally inconsistent; regenerate from one keypair")
} Prevention
- Never hand-assemble dk||ek||H(ek)||z from separate sources.
- Persist the 64-byte seed instead; derive all fields from it.
- Treat an H(ek) mismatch as a sign of corruption, not a recoverable parse error.
When it happens
Trigger: The byte slice has correct total length and decodable s-vector + ek, but the trailing 32-byte hash field was computed over a different ek, was zeroed, or came from concatenating two unrelated key blobs. Also fires if byte order/endianness was altered in transit.
Common situations: Manually concatenating dk_seed || ek || H(ek) || z from separate sources, base64/hex decode mismatch truncating the hash, mixing test vectors across ML-KEM parameter sets, or a copy-paste that swapped ek halves between keys.
Related errors
- mlkem: inconsistent H(ek) in encoded bytes
- mlkem: invalid secret key encoding
- mlkem: invalid NIST decapsulation key length
- mlkem: invalid secret key encoding
- mlkem: invalid encapsulation key length
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/7dd592a9a1a65c21.
Report an issue: GitHub.