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.
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)
Solutions
- Ensure the input is exactly the semi-expanded form produced by TestingOnlyPrivateKeySemiExpandedBytes for the same variant.
- Round-trip the bytes through TestingOnlyPrivateKeySemiExpandedBytes in the test harness to confirm sizes line up.
- 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
- Use this API only for ACVP testing, never in production.
- Round-trip bytes through TestingOnlyPrivateKeySemiExpandedBytes to confirm sizes.
- Prefer NewPrivateKey*/GenerateKey* for real key handling.
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
- mldsa: invalid input length for bitUnpackSlow
- mldsa: invalid seed length
- mldsa: invalid public key length
- mldsa: invalid signature length
- mldsa: semi-expanded private key inconsistent with t0
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/76db0f2cbc5afdd2.
Report an issue: GitHub.