| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| package dsa_test |
| |
| import ( |
| "crypto/dsa" |
| "crypto/internal/cryptotest/wycheproof" |
| "crypto/x509" |
| "math/big" |
| "testing" |
| |
| "golang.org/x/crypto/cryptobyte" |
| "golang.org/x/crypto/cryptobyte/asn1" |
| ) |
| |
| func TestDSAWycheproof(t *testing.T) { |
| flagsShouldPass := map[string]bool{ |
| // An encoded ASN.1 integer missing a leading zero is invalid, |
| // but accepted by some implementations. |
| "MissingZero": false, |
| } |
| |
| for _, file := range []string{ |
| "dsa_2048_224_sha224_test.json", |
| "dsa_2048_224_sha256_test.json", |
| "dsa_2048_256_sha256_test.json", |
| "dsa_3072_256_sha256_test.json", |
| } { |
| var testdata wycheproof.DsaVerifySchemaV1Json |
| wycheproof.LoadVectorFile(t, file, &testdata) |
| |
| for _, tg := range testdata.TestGroups { |
| rawPub, err := x509.ParsePKIXPublicKey(wycheproof.MustDecodeHex(tg.PublicKeyDer)) |
| if err != nil { |
| t.Fatalf("failed to parse DER encoded public key: %v", err) |
| } |
| |
| pub := rawPub.(*dsa.PublicKey) |
| h := wycheproof.ParseHash(tg.Sha) |
| |
| for _, tv := range tg.Tests { |
| t.Run(wycheproof.TestName(file, tv), func(t *testing.T) { |
| t.Parallel() |
| |
| h := h.New() |
| h.Write(wycheproof.MustDecodeHex(tv.Msg)) |
| hashed := h.Sum(nil) |
| // Truncate to the byte-length of the subgroup (Q) |
| hashed = hashed[:pub.Q.BitLen()/8] |
| got := verifyASN1(pub, hashed, wycheproof.MustDecodeHex(tv.Sig)) |
| if want := wycheproof.ShouldPass(t, tv.Result, tv.Flags, flagsShouldPass); got != want { |
| t.Errorf("wanted success: %t", want) |
| } |
| }) |
| } |
| } |
| } |
| } |
| |
| func verifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool { |
| var ( |
| r, s = &big.Int{}, &big.Int{} |
| inner cryptobyte.String |
| ) |
| input := cryptobyte.String(sig) |
| if !input.ReadASN1(&inner, asn1.SEQUENCE) || |
| !input.Empty() || |
| !inner.ReadASN1Integer(r) || |
| !inner.ReadASN1Integer(s) || |
| !inner.Empty() { |
| return false |
| } |
| return dsa.Verify(pub, hash, r, s) |
| } |