golang/go · error

mldsa: invalid semi-expanded private key size

Error message

mldsa: invalid semi-expanded private key size

What it means

TestingOnlyNewPrivateKeyFromSemiExpanded accepts the NIST 'semi-expanded' private-key form (ρ || K || tr || s1 || s2 || t0) and infers the parameter set purely from the total byte length. If the slice matches none of the three expected sizes it returns errInvalidSeedLength's sibling 'invalid semi-expanded private key size'. This API exists for ACVP (FIPS CAVP) conformance testing only and is not part of the public surface.

Solutions

  1. Ensure the input is exactly the semi-expanded form produced by TestingOnlyPrivateKeySemiExpandedBytes for the same variant.
  2. Round-trip the bytes through TestingOnlyPrivateKeySemiExpandedBytes in the test harness to confirm sizes line up.
  3. Do not use this API outside ACVP testing; for production use NewPrivateKey*/GenerateKey*.

Example fix

// before
priv, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(fullNistBlob)

// after
semi := mldsa.TestingOnlyPrivateKeySemiExpandedBytes(referencePriv)
priv, err := mldsa.TestingOnlyNewPrivateKeyFromSemiExpanded(semi)
Defensive patterns

Strategy: validation

Validate before calling

ok := len(sk) == semiExpandedSize44 ||
    len(sk) == semiExpandedSize65 ||
    len(sk) == semiExpandedSize87
if !ok { return ErrBadSemiExpandedSize }

Type guard

func isSemiExpandedSize(n int) bool {
    return n == semiExpandedSize44 || n == semiExpandedSize65 || n == semiExpandedSize87
}

Prevention

When it happens

Trigger: Calling TestingOnlyNewPrivateKeyFromSemiExpanded(sk) with a slice whose length is not semiExpandedPrivKeySize(params44/65/87).

Common situations: Feeding the expanded (full) NIST key instead of the semi-expanded form; truncating/over-reading the byte buffer; using this test helper with production data.

Related errors


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

Appendix: source

Thrown at src/crypto/internal/fips140/mldsa/semiexpanded.go:48

}

// TestingOnlyNewPrivateKeyFromSemiExpanded creates a PrivateKey from a
// semi-expanded private key encoding, for testing purposes. It rejects
// inconsistent keys.
//
// [PrivateKey.Bytes] must NOT be called on the resulting key, as it will
// produce a random value.
func TestingOnlyNewPrivateKeyFromSemiExpanded(sk []byte) (*PrivateKey, error) {
	var p parameters
	switch len(sk) {
	case semiExpandedPrivKeySize(params44):
		p = params44
	case semiExpandedPrivKeySize(params65):
		p = params65
	case semiExpandedPrivKeySize(params87):
		p = params87
	default:
		return nil, errors.New("mldsa: invalid semi-expanded private key size")
	}
	k, l := p.k, p.l

	ρ, K, tr, s1, s2, t0, err := skDecode(sk, p)
	if err != nil {
		return nil, err
	}

	priv := &PrivateKey{pub: PublicKey{p: p}}
	priv.k = K
	priv.pub.tr = tr
	A := priv.a[:k*l]
	computeMatrixA(A, ρ[:], p)
	for r := range l {
		priv.s1[r] = ntt(s1[r])
	}
	for r := range k {
		priv.s2[r] = ntt(s2[r])

View on GitHub (pinned to b6b368adc5)