golang/go · error

mldsa: context too long

Error message

mldsa: context too long

What it means

ML-DSA binds an optional context string into the signed message digest (the ctx in FIPS 204's M' construction). The standard caps this context at 255 bytes so it fits in a single length-prefixed byte. computeMessageHash enforces the cap on behalf of both Sign and Verify; anything longer is rejected before any hashing happens. The same context must be supplied to both Sign and Verify or verification will later fail.

Source

Thrown at src/crypto/internal/fips140/mldsa/mldsa.go:332

		return nil, errInvalidPublicKeyLength
	}

	// We don't precompute A and t1Hat here, because they would make the
	// PublicKey over 68KB. Unlike private keys, public keys are often used to
	// verify a signature only once, so precomputation doesn't help as often,
	// but they can stay around in memory, for example as part of a TLS
	// connection's PeerCertificates, so their size is more of a concern.
	// Instead, we compute A and t1Hat on demand in Verify.

	pub.p = p
	copy(pub.raw[:], pk)
	pub.tr = computePublicKeyHash(pk)

	return pub, nil
}

var (
	errContextTooLong    = errors.New("mldsa: context too long")
	errMessageHashLength = errors.New("mldsa: invalid message hash length")
	errRandomLength      = errors.New("mldsa: invalid random length")
)

func Sign(priv *PrivateKey, msg []byte, context string) ([]byte, error) {
	fipsSelfTest()
	fips140.RecordApproved()
	var random [32]byte
	drbg.Read(random[:])
	μ, err := computeMessageHash(priv.pub.tr[:], msg, context)
	if err != nil {
		return nil, err
	}
	return signInternal(priv, &μ, &random), nil
}

func SignDeterministic(priv *PrivateKey, msg []byte, context string) ([]byte, error) {
	fipsSelfTest()

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Cap the context at 255 bytes; if a longer domain separator is needed, hash it down with SHA-256/SHA3-256 and pass the 32-byte digest as the context (the FIPS 204 scheme does not forbid a hash output as ctx).
  2. Validate len(context) <= 255 at the API boundary and surface a clear validation error to the caller.
  3. Keep context a short, stable identifier (application name + version) rather than free-form metadata.

Example fix

// before
sig, err := mldsa.Sign(priv, msg, longDomainString)

// after
if len(context) > 255 {
    sum := sha3.Sum256([]byte(longDomainString))
    context = string(sum[:])
}
sig, err := mldsa.Sign(priv, msg, context)
Defensive patterns

Strategy: validation

Validate before calling

if len(context) > 255 {
    return fmt.Errorf("mldsa context limited to 255 bytes, got %d", len(context))
}

Type guard

func isValidContext(ctx string) bool { return len(ctx) <= 255 }

Prevention

When it happens

Trigger: Calling mldsa.Sign(priv, msg, context) or mldsa.Verify(pub, msg, sig, context) with len(context) > 255.

Common situations: Embedding a long URI, JWT, certificate chain, or concatenated metadata blob as the context; copying a 'domain' string from config without length-checking; logging context that grew over time.

Related errors


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