golang/go · error

mlkem: invalid ciphertext length

Error message

mlkem: invalid ciphertext length

What it means

Thrown by Decapsulate768 when the ciphertext byte slice is not exactly CiphertextSize768 bytes. 768 analogue of error 383.

Source

Thrown at src/crypto/internal/fips140/mlkem/mlkem768.go:463

	v := polyAdd(polyAdd(inverseNTT(vNTT), e2), μ)

	c := cc[:0]
	for _, f := range u {
		c = ringCompressAndEncode10(c, f)
	}
	c = ringCompressAndEncode4(c, v)

	return c
}

// Decapsulate generates a shared key from a ciphertext and a decapsulation key.
// If the ciphertext is not valid, Decapsulate returns an error.
//
// The shared key must be kept secret.
func (dk *DecapsulationKey768) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) {
	fipsSelfTest()
	if len(ciphertext) != CiphertextSize768 {
		return nil, errors.New("mlkem: invalid ciphertext length")
	}
	c := (*[CiphertextSize768]byte)(ciphertext)
	// Note that the hash check (step 3 of the decapsulation input check from
	// FIPS 203, Section 7.3) is foregone as a DecapsulationKey is always
	// validly generated by ML-KEM.KeyGen_internal.
	return kemDecaps(dk, c), nil
}

// kemDecaps produces a shared key from a ciphertext.
//
// It implements ML-KEM.Decaps_internal according to FIPS 203, Algorithm 18.
func kemDecaps(dk *DecapsulationKey768, c *[CiphertextSize768]byte) (K []byte) {
	fips140.RecordApproved()
	m := pkeDecrypt(&dk.decryptionKey, c)
	g := sha3.New512()
	g.Write(m[:])
	g.Write(dk.h[:])
	G := g.Sum(make([]byte, 0, 64))

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Assert len(ciphertext) == CiphertextSize768 before calling Decapsulate.
  2. Confirm the ciphertext was produced by Encapsulate768 against a 768 encapsulation key.
  3. Strip any framing/header before passing raw ciphertext.
  4. Decode base64/hex into a fixed-length byte array.

Example fix

// before
shared, err := dk.Decapsulate(ct) // ct is 1024-size
// after
if len(ct) != mlkem768.CiphertextSize768 {
    return fmt.Errorf("ct len %d != %d", len(ct), mlkem768.CiphertextSize768)
}
shared, err := dk.Decapsulate(ct)
Defensive patterns

Strategy: validation

Validate before calling

if len(ct) != mlkem768.CiphertextSize768 {
    return fmt.Errorf("ciphertext len %d != %d", len(ct), mlkem768.CiphertextSize768)
}

Type guard

func isMLKEM768Ciphertext(b []byte) bool {
    return len(b) == mlkem768.CiphertextSize768
}

Try / catch

shared, err := dk.Decapsulate(ct)
if err != nil {
    return fmt.Errorf("decapsulate failed (ct len=%d): %w", len(ct), err)
}

Prevention

When it happens

Trigger: Passing a 1024-size ciphertext, a framed/transport-wrapped ciphertext, an un-decoded base64 string, or a mis-sliced buffer.

Common situations: Cross-parameter-set mix-ups, network framing not stripped, base64 not decoded, or off-by-one slicing.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/a5db9143ee9f7a1c. Report an issue: GitHub.