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

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions