xref: /aosp_15_r20/external/tink/go/signature/subtle/ecdsa_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2020 Google LLC
2*e7b1675dSTing-Kang Chang//
3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang//
7*e7b1675dSTing-Kang Chang//      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang//
9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang// limitations under the License.
14*e7b1675dSTing-Kang Chang//
15*e7b1675dSTing-Kang Chang////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Changpackage subtle_test
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Changimport (
20*e7b1675dSTing-Kang Chang	"encoding/asn1"
21*e7b1675dSTing-Kang Chang	"encoding/hex"
22*e7b1675dSTing-Kang Chang	"math/big"
23*e7b1675dSTing-Kang Chang	"testing"
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/signature/subtle"
26*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/subtle/random"
27*e7b1675dSTing-Kang Chang)
28*e7b1675dSTing-Kang Chang
29*e7b1675dSTing-Kang Changtype paramsTestECDSA struct {
30*e7b1675dSTing-Kang Chang	hash     string
31*e7b1675dSTing-Kang Chang	curve    string
32*e7b1675dSTing-Kang Chang	encoding string
33*e7b1675dSTing-Kang Chang}
34*e7b1675dSTing-Kang Chang
35*e7b1675dSTing-Kang Changfunc TestECDSAEncodeDecodeDER(t *testing.T) {
36*e7b1675dSTing-Kang Chang	nTest := 1000
37*e7b1675dSTing-Kang Chang	for i := 0; i < nTest; i++ {
38*e7b1675dSTing-Kang Chang		sig := newECDSARandomSignature()
39*e7b1675dSTing-Kang Chang		encoding := "DER"
40*e7b1675dSTing-Kang Chang		encoded, err := sig.EncodeECDSASignature(encoding, "P-256")
41*e7b1675dSTing-Kang Chang		if err != nil {
42*e7b1675dSTing-Kang Chang			t.Errorf("unexpected error during encoding: %s", err)
43*e7b1675dSTing-Kang Chang		}
44*e7b1675dSTing-Kang Chang		// first byte is 0x30
45*e7b1675dSTing-Kang Chang		if encoded[0] != byte(0x30) {
46*e7b1675dSTing-Kang Chang			t.Errorf("first byte is incorrect, expected 48, got %v", encoded[0])
47*e7b1675dSTing-Kang Chang		}
48*e7b1675dSTing-Kang Chang		// tag is 2
49*e7b1675dSTing-Kang Chang		if encoded[2] != byte(2) || encoded[4+encoded[3]] != byte(2) {
50*e7b1675dSTing-Kang Chang			t.Errorf("expect tag to be 2 (integer), got %d and %d", encoded[2], encoded[4+encoded[3]])
51*e7b1675dSTing-Kang Chang		}
52*e7b1675dSTing-Kang Chang		// length
53*e7b1675dSTing-Kang Chang		if len(encoded) != int(encoded[1])+2 {
54*e7b1675dSTing-Kang Chang			t.Errorf("incorrect length, expected %d, got %d", len(encoded), encoded[1]+2)
55*e7b1675dSTing-Kang Chang		}
56*e7b1675dSTing-Kang Chang		decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding)
57*e7b1675dSTing-Kang Chang		if err != nil {
58*e7b1675dSTing-Kang Chang			t.Errorf("unexpected error during decoding: %s", err)
59*e7b1675dSTing-Kang Chang		}
60*e7b1675dSTing-Kang Chang		if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 {
61*e7b1675dSTing-Kang Chang			t.Errorf("decoded signature doesn't match original value")
62*e7b1675dSTing-Kang Chang		}
63*e7b1675dSTing-Kang Chang	}
64*e7b1675dSTing-Kang Chang}
65*e7b1675dSTing-Kang Chang
66*e7b1675dSTing-Kang Changfunc TestECDSAEncodeDecodeIEEEP1363(t *testing.T) {
67*e7b1675dSTing-Kang Chang	nTest := 1000
68*e7b1675dSTing-Kang Chang	for i := 0; i < nTest; i++ {
69*e7b1675dSTing-Kang Chang		sig := newECDSARandomSignature()
70*e7b1675dSTing-Kang Chang		encoding := "IEEE_P1363"
71*e7b1675dSTing-Kang Chang		encoded, err := sig.EncodeECDSASignature(encoding, "P-256")
72*e7b1675dSTing-Kang Chang		if err != nil {
73*e7b1675dSTing-Kang Chang			t.Errorf("unexpected error during encoding: %s", err)
74*e7b1675dSTing-Kang Chang		}
75*e7b1675dSTing-Kang Chang		if len(encoded) != 64 {
76*e7b1675dSTing-Kang Chang			t.Errorf("incorrect length, expected %d, got %d", 64, len(encoded))
77*e7b1675dSTing-Kang Chang		}
78*e7b1675dSTing-Kang Chang		if len(sig.R.Bytes()) < 32 {
79*e7b1675dSTing-Kang Chang			expectedZeros := 32 - len(sig.R.Bytes())
80*e7b1675dSTing-Kang Chang			for i := 0; i < expectedZeros; i++ {
81*e7b1675dSTing-Kang Chang				if encoded[i] != 0 {
82*e7b1675dSTing-Kang Chang					t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded))
83*e7b1675dSTing-Kang Chang				}
84*e7b1675dSTing-Kang Chang			}
85*e7b1675dSTing-Kang Chang		}
86*e7b1675dSTing-Kang Chang		if len(sig.S.Bytes()) < 32 {
87*e7b1675dSTing-Kang Chang			expectedZeros := 32 - len(sig.S.Bytes())
88*e7b1675dSTing-Kang Chang			for i := 32; i < (32 + expectedZeros); i++ {
89*e7b1675dSTing-Kang Chang				if encoded[i] != 0 {
90*e7b1675dSTing-Kang Chang					t.Errorf("expect byte %d to be 0, got %d. encoded data = %s", i, encoded[i], hex.Dump(encoded))
91*e7b1675dSTing-Kang Chang				}
92*e7b1675dSTing-Kang Chang			}
93*e7b1675dSTing-Kang Chang		}
94*e7b1675dSTing-Kang Chang		decodedSig, err := subtle.DecodeECDSASignature(encoded, encoding)
95*e7b1675dSTing-Kang Chang		if err != nil {
96*e7b1675dSTing-Kang Chang			t.Errorf("unexpected error during decoding: %s", err)
97*e7b1675dSTing-Kang Chang		}
98*e7b1675dSTing-Kang Chang		if decodedSig.R.Cmp(sig.R) != 0 || decodedSig.S.Cmp(sig.S) != 0 {
99*e7b1675dSTing-Kang Chang			t.Errorf("decoded signature doesn't match original value")
100*e7b1675dSTing-Kang Chang		}
101*e7b1675dSTing-Kang Chang	}
102*e7b1675dSTing-Kang Chang}
103*e7b1675dSTing-Kang Chang
104*e7b1675dSTing-Kang Changfunc TestECDSAEncodeWithInvalidInput(t *testing.T) {
105*e7b1675dSTing-Kang Chang	sig := newECDSARandomSignature()
106*e7b1675dSTing-Kang Chang	_, err := sig.EncodeECDSASignature("UNKNOWN_ENCODING", "P-256")
107*e7b1675dSTing-Kang Chang	if err == nil {
108*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when encoding is invalid")
109*e7b1675dSTing-Kang Chang	}
110*e7b1675dSTing-Kang Chang}
111*e7b1675dSTing-Kang Chang
112*e7b1675dSTing-Kang Changfunc TestECDSADecodeWithInvalidInput(t *testing.T) {
113*e7b1675dSTing-Kang Chang	var sig *subtle.ECDSASignature
114*e7b1675dSTing-Kang Chang	var encoded []byte
115*e7b1675dSTing-Kang Chang	encoding := "DER"
116*e7b1675dSTing-Kang Chang
117*e7b1675dSTing-Kang Chang	// modified first byte
118*e7b1675dSTing-Kang Chang	sig = newECDSARandomSignature()
119*e7b1675dSTing-Kang Chang	encoded, _ = sig.EncodeECDSASignature(encoding, "P-256")
120*e7b1675dSTing-Kang Chang	encoded[0] = 0x31
121*e7b1675dSTing-Kang Chang	if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil {
122*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when first byte is not 0x30")
123*e7b1675dSTing-Kang Chang	}
124*e7b1675dSTing-Kang Chang	// modified tag
125*e7b1675dSTing-Kang Chang	sig = newECDSARandomSignature()
126*e7b1675dSTing-Kang Chang	encoded, _ = sig.EncodeECDSASignature(encoding, "P-256")
127*e7b1675dSTing-Kang Chang	encoded[2] = encoded[2] + 1
128*e7b1675dSTing-Kang Chang	if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil {
129*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when tag is modified")
130*e7b1675dSTing-Kang Chang	}
131*e7b1675dSTing-Kang Chang	// modified length
132*e7b1675dSTing-Kang Chang	sig = newECDSARandomSignature()
133*e7b1675dSTing-Kang Chang	encoded, _ = sig.EncodeECDSASignature(encoding, "P-256")
134*e7b1675dSTing-Kang Chang	encoded[1] = encoded[1] + 1
135*e7b1675dSTing-Kang Chang	if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil {
136*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when length is modified")
137*e7b1675dSTing-Kang Chang	}
138*e7b1675dSTing-Kang Chang	// append unused 0s
139*e7b1675dSTing-Kang Chang	sig = newECDSARandomSignature()
140*e7b1675dSTing-Kang Chang	encoded, _ = sig.EncodeECDSASignature(encoding, "P-256")
141*e7b1675dSTing-Kang Chang	tmp := make([]byte, len(encoded)+4)
142*e7b1675dSTing-Kang Chang	copy(tmp, encoded)
143*e7b1675dSTing-Kang Chang	if _, err := subtle.DecodeECDSASignature(tmp, encoding); err == nil {
144*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when unused 0s are appended to signature")
145*e7b1675dSTing-Kang Chang	}
146*e7b1675dSTing-Kang Chang	// a struct with three numbers
147*e7b1675dSTing-Kang Chang	randomStruct := struct{ X, Y, Z *big.Int }{
148*e7b1675dSTing-Kang Chang		X: new(big.Int).SetBytes(random.GetRandomBytes(32)),
149*e7b1675dSTing-Kang Chang		Y: new(big.Int).SetBytes(random.GetRandomBytes(32)),
150*e7b1675dSTing-Kang Chang		Z: new(big.Int).SetBytes(random.GetRandomBytes(32)),
151*e7b1675dSTing-Kang Chang	}
152*e7b1675dSTing-Kang Chang	encoded, _ = asn1.Marshal(randomStruct)
153*e7b1675dSTing-Kang Chang	if _, err := subtle.DecodeECDSASignature(encoded, encoding); err == nil {
154*e7b1675dSTing-Kang Chang		t.Errorf("expect an error when input is not an ECDSASignature")
155*e7b1675dSTing-Kang Chang	}
156*e7b1675dSTing-Kang Chang}
157*e7b1675dSTing-Kang Chang
158*e7b1675dSTing-Kang Changfunc TestECDSAValidateParams(t *testing.T) {
159*e7b1675dSTing-Kang Chang	params := genECDSAValidParams()
160*e7b1675dSTing-Kang Chang	for i := 0; i < len(params); i++ {
161*e7b1675dSTing-Kang Chang		if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err != nil {
162*e7b1675dSTing-Kang Chang			t.Errorf("unexpected error for valid params: %s, i = %d", err, i)
163*e7b1675dSTing-Kang Chang		}
164*e7b1675dSTing-Kang Chang	}
165*e7b1675dSTing-Kang Chang	params = genECDSAInvalidParams()
166*e7b1675dSTing-Kang Chang	for i := 0; i < len(params); i++ {
167*e7b1675dSTing-Kang Chang		if err := subtle.ValidateECDSAParams(params[i].hash, params[i].curve, params[i].encoding); err == nil {
168*e7b1675dSTing-Kang Chang			t.Errorf("expect an error when params are invalid, i = %d", i)
169*e7b1675dSTing-Kang Chang		}
170*e7b1675dSTing-Kang Chang	}
171*e7b1675dSTing-Kang Chang}
172*e7b1675dSTing-Kang Chang
173*e7b1675dSTing-Kang Changfunc genECDSAInvalidParams() []paramsTestECDSA {
174*e7b1675dSTing-Kang Chang	encodings := []string{"DER", "IEEE_P1363"}
175*e7b1675dSTing-Kang Chang	testCases := []paramsTestECDSA{
176*e7b1675dSTing-Kang Chang		// invalid encoding
177*e7b1675dSTing-Kang Chang		{hash: "SHA256", curve: "NIST_P256", encoding: "UNKNOWN_ENCODING"},
178*e7b1675dSTing-Kang Chang		// invalid hash
179*e7b1675dSTing-Kang Chang		{hash: "SHA1", curve: "NIST_P256", encoding: "IEEE_P1363"},
180*e7b1675dSTing-Kang Chang		// invalid curve
181*e7b1675dSTing-Kang Chang		{hash: "SHA1", curve: "UNKNOWN_CURVE", encoding: "IEEE_P1363"},
182*e7b1675dSTing-Kang Chang	}
183*e7b1675dSTing-Kang Chang	for _, encoding := range encodings {
184*e7b1675dSTing-Kang Chang		testCases = append(testCases,
185*e7b1675dSTing-Kang Chang			// invalid curve
186*e7b1675dSTing-Kang Chang			paramsTestECDSA{hash: "SHA256", curve: "UNKNOWN_CURVE", encoding: encoding},
187*e7b1675dSTing-Kang Chang			// invalid hash: P256 and SHA-512
188*e7b1675dSTing-Kang Chang			paramsTestECDSA{hash: "SHA512", curve: "NIST_P256", encoding: encoding},
189*e7b1675dSTing-Kang Chang			// invalid hash: P521 and SHA-256
190*e7b1675dSTing-Kang Chang			paramsTestECDSA{hash: "SHA256", curve: "NIST_P521", encoding: encoding},
191*e7b1675dSTing-Kang Chang			// invalid hash: P384 and SHA-256
192*e7b1675dSTing-Kang Chang			paramsTestECDSA{hash: "SHA256", curve: "NIST_P384", encoding: encoding},
193*e7b1675dSTing-Kang Chang		)
194*e7b1675dSTing-Kang Chang	}
195*e7b1675dSTing-Kang Chang	return testCases
196*e7b1675dSTing-Kang Chang}
197*e7b1675dSTing-Kang Chang
198*e7b1675dSTing-Kang Changfunc genECDSAValidParams() []paramsTestECDSA {
199*e7b1675dSTing-Kang Chang	return []paramsTestECDSA{
200*e7b1675dSTing-Kang Chang		{hash: "SHA256", curve: "NIST_P256", encoding: "DER"},
201*e7b1675dSTing-Kang Chang		{hash: "SHA256", curve: "NIST_P256", encoding: "IEEE_P1363"},
202*e7b1675dSTing-Kang Chang		{hash: "SHA384", curve: "NIST_P384", encoding: "DER"},
203*e7b1675dSTing-Kang Chang		{hash: "SHA384", curve: "NIST_P384", encoding: "IEEE_P1363"},
204*e7b1675dSTing-Kang Chang		{hash: "SHA512", curve: "NIST_P384", encoding: "DER"},
205*e7b1675dSTing-Kang Chang		{hash: "SHA512", curve: "NIST_P384", encoding: "IEEE_P1363"},
206*e7b1675dSTing-Kang Chang		{hash: "SHA512", curve: "NIST_P521", encoding: "DER"},
207*e7b1675dSTing-Kang Chang		{hash: "SHA512", curve: "NIST_P521", encoding: "IEEE_P1363"},
208*e7b1675dSTing-Kang Chang	}
209*e7b1675dSTing-Kang Chang}
210*e7b1675dSTing-Kang Chang
211*e7b1675dSTing-Kang Changfunc newECDSARandomSignature() *subtle.ECDSASignature {
212*e7b1675dSTing-Kang Chang	r := new(big.Int).SetBytes(random.GetRandomBytes(32))
213*e7b1675dSTing-Kang Chang	s := new(big.Int).SetBytes(random.GetRandomBytes(32))
214*e7b1675dSTing-Kang Chang	return subtle.NewECDSASignature(r, s)
215*e7b1675dSTing-Kang Chang}
216