Skip to content

crypto/mldsa: Sign panics on zero-value PrivateKey #80339

Description

@SphereDonout

Go version

go1.26.0 darwin/arm64

What did you do?

I called the public ML-DSA signing API with an uninitialized zero-value mldsa.PrivateKey.
Minimal reproducer:

package main

import (
	"crypto/mldsa"
)

func main() {
	var sk mldsa.PrivateKey
	_, _ = sk.Sign(nil, []byte("message"), nil)
}

This is the same invalid-zero-key family as the public-key issue in crypto/mldsa, but on the private-key signing path.

What did you see happen?

The zero-value PrivateKey is not rejected up front. The public (*PrivateKey).Sign / SignDeterministic path forwards &sk.k into the internal signer, which derives ML-DSA parameters from zero-value internal state instead of returning an error.
In current source, that reaches signInternal, where p.γ2 is still zero for the zero-value key state, and the signer computes:

γ2 := (q - 1) / uint32(p.γ2)

That is a divide-by-zero panic rather than a clean error return.

What did you expect to see?

I expected the public signing API to reject an uninitialized mldsa.PrivateKey with an error, not panic.
For example, this should fail cleanly:

var sk mldsa.PrivateKey

if _, err := sk.Sign(nil, []byte("message"), nil); err == nil {
	panic("Sign accepted zero-value PrivateKey")
}

More generally, zero-value or otherwise invalid ML-DSA key state should be handled consistently across the public API surface. A caller should not be able to trigger an internal panic by passing an uninitialized mldsa.PrivateKey.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions