crypto/ecdsa: test hash size restrictions

Change-Id: I44a74a75d89abbf8f59fe6bfc21471e56a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/780000
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Filippo Valsorda 2026-05-19 20:37:41 +02:00 committed by Gopher Robot
parent 8329d31307
commit b12ed667d9

View file

@ -108,6 +108,81 @@ func TestSignAndVerifyASN1(t *testing.T) {
testAllCurves(t, testSignAndVerifyASN1)
}
func TestEmptyHashRejection(t *testing.T) {
testAllCurves(t, testEmptyHashRejection)
}
func testEmptyHashRejection(t *testing.T, c elliptic.Curve) {
priv, err := GenerateKey(c, rand.Reader)
if err != nil {
t.Fatal(err)
}
t.Run("SignASN1", func(t *testing.T) {
_, err := SignASN1(rand.Reader, priv, nil)
if err == nil {
t.Fatal("SignASN1 with nil hash should fail")
}
if !strings.Contains(err.Error(), "cannot be empty") {
t.Errorf("unexpected error: %v", err)
}
_, err = SignASN1(rand.Reader, priv, []byte{})
if err == nil {
t.Fatal("SignASN1 with empty hash should fail")
}
if !strings.Contains(err.Error(), "cannot be empty") {
t.Errorf("unexpected error: %v", err)
}
})
t.Run("Sign", func(t *testing.T) {
_, err := priv.Sign(rand.Reader, nil, nil)
if err == nil {
t.Fatal("Sign with nil hash should fail")
}
if !strings.Contains(err.Error(), "cannot be empty") {
t.Errorf("unexpected error: %v", err)
}
_, err = priv.Sign(rand.Reader, []byte{}, nil)
if err == nil {
t.Fatal("Sign with empty hash should fail")
}
if !strings.Contains(err.Error(), "cannot be empty") {
t.Errorf("unexpected error: %v", err)
}
})
t.Run("SignDeterministic", func(t *testing.T) {
if _, err := priv.Sign(nil, nil, nil); err == nil {
t.Error("deterministic Sign with nil hash should fail")
}
if _, err := priv.Sign(nil, []byte{}, nil); err == nil {
t.Error("deterministic Sign with empty hash should fail")
}
})
t.Run("VerifyASN1", func(t *testing.T) {
// Create a valid signature first
hash := []byte("test hash")
sig, err := SignASN1(rand.Reader, priv, hash)
if err != nil {
t.Fatal(err)
}
// Verify with nil hash should return false
if VerifyASN1(&priv.PublicKey, nil, sig) {
t.Error("VerifyASN1 with nil hash should return false")
}
// Verify with empty hash should return false
if VerifyASN1(&priv.PublicKey, []byte{}, sig) {
t.Error("VerifyASN1 with empty hash should return false")
}
})
}
func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) {
priv, _ := GenerateKey(c, rand.Reader)
@ -128,6 +203,40 @@ func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) {
}
}
func TestSignHashLength(t *testing.T) {
testAllCurves(t, testSignHashLength)
}
func testSignHashLength(t *testing.T, c elliptic.Curve) {
priv, err := GenerateKey(c, rand.Reader)
if err != nil {
t.Fatal(err)
}
digest := sha256.Sum256([]byte("message"))
// opts == nil is allowed and skips the length check.
if _, err := priv.Sign(rand.Reader, digest[:], nil); err != nil {
t.Errorf("Sign with nil opts: %v", err)
}
// opts != nil with matching hash length succeeds.
if _, err := priv.Sign(rand.Reader, digest[:], crypto.SHA256); err != nil {
t.Errorf("Sign with matching hash: %v", err)
}
// opts != nil with mismatched hash length fails.
if _, err := priv.Sign(rand.Reader, digest[:], crypto.SHA384); err == nil {
t.Error("Sign with mismatched hash length should fail")
}
if _, err := priv.Sign(rand.Reader, digest[:len(digest)-1], crypto.SHA256); err == nil {
t.Error("Sign with short digest should fail")
}
if _, err := priv.Sign(rand.Reader, nil, crypto.SHA256); err == nil {
t.Error("Sign with empty digest should fail")
}
}
func TestNonceSafety(t *testing.T) {
testAllCurves(t, testNonceSafety)
}