golang/go · error

mldsa: invalid signature length

Error message

mldsa: invalid signature length

What it means

An ML-DSA signature is a fixed-size byte string: 2420 bytes for ML-DSA-44, 3309 for ML-DSA-65, 4627 for ML-DSA-87. Verify performs a length check up front (errInvalidSignatureLength) before any decoding; a blob of the wrong size is reported as malformed rather than as a forgery. This separates transport/encoding bugs from genuine cryptographic failures.

Source

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

			if constantTimeAbs(r0) >= bound {
				return true
			}
		}
	case 88:
		for i := range w {
			_, r0 := decompose88(w[i])
			if constantTimeAbs(r0) >= bound {
				return true
			}
		}
	default:
		panic("mldsa: internal error: unsupported γ2")
	}
	return false
}

var (
	errInvalidSignatureLength           = errors.New("mldsa: invalid signature length")
	errInvalidSignatureCoeffBounds      = errors.New("mldsa: invalid signature")
	errInvalidSignatureChallenge        = errors.New("mldsa: invalid signature")
	errInvalidSignatureHintLimits       = errors.New("mldsa: invalid signature encoding")
	errInvalidSignatureHintIndexOrder   = errors.New("mldsa: invalid signature encoding")
	errInvalidSignatureHintExtraIndices = errors.New("mldsa: invalid signature encoding")
)

func Verify(pub *PublicKey, msg, sig []byte, context string) error {
	fipsSelfTest()
	fips140.RecordApproved()
	μ, err := computeMessageHash(pub.tr[:], msg, context)
	if err != nil {
		return err
	}
	return verifyInternal(pub, &μ, sig)
}

func VerifyExternalMu(pub *PublicKey, μ []byte, sig []byte) error {

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Decode base64/hex before calling Verify and assert the decoded length equals the expected SignatureSize constant.
  2. Persist the parameter set next to the signature and verify against the matching variant's public key.
  3. Trim trailing whitespace/NULs after reading the signature from a text medium.
  4. Add a length assertion at the deserialization boundary so the error message names the transport bug, not the crypto API.

Example fix

// before
ok := mldsa.Verify(pub, msg, base64Sig, ctx) == nil  // still encoded

// after
sig, err := base64.StdEncoding.DecodeString(base64Sig)
if err != nil { return err }
err = mldsa.Verify(pub, msg, sig, ctx)
Defensive patterns

Strategy: validation

Validate before calling

if len(sig) != wantSize { // 2420/3309/4627
    return fmt.Errorf("signature must be %d bytes, got %d", wantSize, len(sig))
}

Type guard

func isMLDSA44Signature(sig []byte) bool { return len(sig) == 2420 }

Prevention

When it happens

Trigger: Calling mldsa.Verify(pub, msg, sig, context) where len(sig) does not equal the parameter set's SignatureSize.

Common situations: Signature transported base64/hex-encoded and not decoded; mixing ML-DSA-44 signatures with an ML-DSA-65 public key; truncation in a length-prefixed or URL-safe channel; trailing newline or NUL padding included in the slice.

Related errors


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