golang/go · error

mldsa: zero public key

Error message

mldsa: zero public key

What it means

Returned by Verify when pk is non-nil but the inner mldsa.PublicKey value pk.p is the zero value — i.e. the wrapper struct exists but was never populated with real key material. This catches a half-initialized PublicKey that would otherwise fail deep inside mldsa.Verify with a less actionable error. The check is pk.p == (mldsa.PublicKey{}).

Source

Thrown at src/crypto/mldsa/mldsa_fips140v1.26.go:220

	case "ML-DSA-44":
		return MLDSA44()
	case "ML-DSA-65":
		return MLDSA65()
	case "ML-DSA-87":
		return MLDSA87()
	default:
		panic("mldsa: invalid parameters in public key")
	}
}

// Verify reports whether signature is a valid signature of message by pk.
// If opts is nil, it's equivalent to the zero value of Options.
func Verify(pk *PublicKey, message []byte, signature []byte, opts *Options) error {
	if pk == nil {
		return errors.New("mldsa: nil public key")
	}
	if pk.p == (mldsa.PublicKey{}) {
		return errors.New("mldsa: zero public key")
	}
	if opts == nil {
		opts = &Options{}
	}
	return mldsa.Verify(&pk.p, message, signature, opts.Context)
}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Build the public key through the documented constructor/decode API so pk.p is populated.
  2. After loading, sanity-check: if pk == nil || pk.Bytes() is empty, abort.
  3. Propagate decode errors rather than defaulting to an empty PublicKey.

Example fix

// before
pk := &mldsa.PublicKey{} // inner p is zero value
err := mldsa.Verify(pk, msg, sig, nil) // "mldsa: zero public key"

// after
pk, err := mldsa.NewPublicKeyFromBytes(raw)
if err != nil { return err }
err = mldsa.Verify(pk, msg, sig, nil)
Defensive patterns

Strategy: validation

Validate before calling

if pk == nil || len(pk.Bytes()) == 0 {
    return errors.New("public key not initialized")
}
return mldsa.Verify(pk, msg, sig, opts)

Type guard

func (pk *PublicKey) isInitialized() bool {
    return pk != nil && len(pk.Bytes()) > 0
}

Try / catch

if err := mldsa.Verify(pk, msg, sig, opts); err != nil {
    if strings.Contains(err.Error(), "zero public key") {
        pk, err = reloadPublicKey()
        if err != nil { return err }
        err = mldsa.Verify(pk, msg, sig, opts)
    }
    return err
}

Prevention

When it happens

Trigger: Constructing &mldsa.PublicKey{} directly without running through NewPublicKey / Decode. A decode function that returned a non-nil pointer but left p zero on partial failure.

Common situations: Copying a PublicKey by value into a fresh struct and forgetting to populate the inner field. JSON/gob deserialization that allocates the wrapper but does not set the internal field. A lookup cache that stores an empty PublicKey sentinel.

Related errors


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