Source file src/crypto/dsa/dsa_wycheproof_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  package dsa_test
     5  
     6  import (
     7  	"crypto/dsa"
     8  	"crypto/internal/cryptotest/wycheproof"
     9  	"crypto/x509"
    10  	"math/big"
    11  	"testing"
    12  
    13  	"golang.org/x/crypto/cryptobyte"
    14  	"golang.org/x/crypto/cryptobyte/asn1"
    15  )
    16  
    17  func TestDSAWycheproof(t *testing.T) {
    18  	flagsShouldPass := map[string]bool{
    19  		// An encoded ASN.1 integer missing a leading zero is invalid,
    20  		// but accepted by some implementations.
    21  		"MissingZero": false,
    22  	}
    23  
    24  	for _, file := range []string{
    25  		"dsa_2048_224_sha224_test.json",
    26  		"dsa_2048_224_sha256_test.json",
    27  		"dsa_2048_256_sha256_test.json",
    28  		"dsa_3072_256_sha256_test.json",
    29  	} {
    30  		var testdata wycheproof.DsaVerifySchemaV1Json
    31  		wycheproof.LoadVectorFile(t, file, &testdata)
    32  
    33  		for _, tg := range testdata.TestGroups {
    34  			rawPub, err := x509.ParsePKIXPublicKey(wycheproof.MustDecodeHex(tg.PublicKeyDer))
    35  			if err != nil {
    36  				t.Fatalf("failed to parse DER encoded public key: %v", err)
    37  			}
    38  
    39  			pub := rawPub.(*dsa.PublicKey)
    40  			h := wycheproof.ParseHash(tg.Sha)
    41  
    42  			for _, tv := range tg.Tests {
    43  				t.Run(wycheproof.TestName(file, tv), func(t *testing.T) {
    44  					t.Parallel()
    45  
    46  					h := h.New()
    47  					h.Write(wycheproof.MustDecodeHex(tv.Msg))
    48  					hashed := h.Sum(nil)
    49  					// Truncate to the byte-length of the subgroup (Q)
    50  					hashed = hashed[:pub.Q.BitLen()/8]
    51  					got := verifyASN1(pub, hashed, wycheproof.MustDecodeHex(tv.Sig))
    52  					if want := wycheproof.ShouldPass(t, tv.Result, tv.Flags, flagsShouldPass); got != want {
    53  						t.Errorf("wanted success: %t", want)
    54  					}
    55  				})
    56  			}
    57  		}
    58  	}
    59  }
    60  
    61  func verifyASN1(pub *dsa.PublicKey, hash, sig []byte) bool {
    62  	var (
    63  		r, s  = &big.Int{}, &big.Int{}
    64  		inner cryptobyte.String
    65  	)
    66  	input := cryptobyte.String(sig)
    67  	if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
    68  		!input.Empty() ||
    69  		!inner.ReadASN1Integer(r) ||
    70  		!inner.ReadASN1Integer(s) ||
    71  		!inner.Empty() {
    72  		return false
    73  	}
    74  	return dsa.Verify(pub, hash, r, s)
    75  }
    76  

View as plain text