{"record":{"id":"8835af12b5bf653e","repo":"golang/go","slug":"mldsa-zero-public-key","errorCode":null,"errorMessage":"mldsa: zero public key","messagePattern":"mldsa: zero public key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/mldsa/mldsa_fips140v1.26.go","lineNumber":220,"sourceCode":"\tcase \"ML-DSA-44\":\n\t\treturn MLDSA44()\n\tcase \"ML-DSA-65\":\n\t\treturn MLDSA65()\n\tcase \"ML-DSA-87\":\n\t\treturn MLDSA87()\n\tdefault:\n\t\tpanic(\"mldsa: invalid parameters in public key\")\n\t}\n}\n\n// Verify reports whether signature is a valid signature of message by pk.\n// If opts is nil, it's equivalent to the zero value of Options.\nfunc Verify(pk *PublicKey, message []byte, signature []byte, opts *Options) error {\n\tif pk == nil {\n\t\treturn errors.New(\"mldsa: nil public key\")\n\t}\n\tif pk.p == (mldsa.PublicKey{}) {\n\t\treturn errors.New(\"mldsa: zero public key\")\n\t}\n\tif opts == nil {\n\t\topts = &Options{}\n\t}\n\treturn mldsa.Verify(&pk.p, message, signature, opts.Context)\n}\n","sourceCodeStart":202,"sourceCodeEnd":227,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/mldsa/mldsa_fips140v1.26.go#L202-L227","documentation":"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{}).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Build the public key through the documented constructor/decode API so pk.p is populated.","After loading, sanity-check: if pk == nil || pk.Bytes() is empty, abort.","Propagate decode errors rather than defaulting to an empty PublicKey."],"exampleFix":"// before\npk := &mldsa.PublicKey{} // inner p is zero value\nerr := mldsa.Verify(pk, msg, sig, nil) // \"mldsa: zero public key\"\n\n// after\npk, err := mldsa.NewPublicKeyFromBytes(raw)\nif err != nil { return err }\nerr = mldsa.Verify(pk, msg, sig, nil)","handlingStrategy":"validation","validationCode":"if pk == nil || len(pk.Bytes()) == 0 {\n    return errors.New(\"public key not initialized\")\n}\nreturn mldsa.Verify(pk, msg, sig, opts)","typeGuard":"func (pk *PublicKey) isInitialized() bool {\n    return pk != nil && len(pk.Bytes()) > 0\n}","tryCatchPattern":"if err := mldsa.Verify(pk, msg, sig, opts); err != nil {\n    if strings.Contains(err.Error(), \"zero public key\") {\n        pk, err = reloadPublicKey()\n        if err != nil { return err }\n        err = mldsa.Verify(pk, msg, sig, opts)\n    }\n    return err\n}","preventionTips":["Always construct PublicKey via the decode/constructor API.","Propagate decode errors instead of defaulting to an empty struct.","Add a byte-length assertion after loading public keys."],"tags":["cryptography","go","post-quantum","mldsa","key-management","verification"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}