xref: /aosp_15_r20/external/tink/go/signature/ecdsa_signer_key_manager_test.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2018 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package signature_test
18
19import (
20	"fmt"
21	"math/big"
22	"testing"
23
24	"google.golang.org/protobuf/proto"
25	"github.com/google/tink/go/core/registry"
26	"github.com/google/tink/go/signature/subtle"
27	"github.com/google/tink/go/subtle/random"
28	"github.com/google/tink/go/testutil"
29	commonpb "github.com/google/tink/go/proto/common_go_proto"
30	ecdsapb "github.com/google/tink/go/proto/ecdsa_go_proto"
31	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
32)
33
34type ecdsaParams struct {
35	hashType commonpb.HashType
36	curve    commonpb.EllipticCurveType
37}
38
39func TestECDSASignerGetPrimitiveBasic(t *testing.T) {
40	testParams := genValidECDSAParams()
41	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
42	if err != nil {
43		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
44	}
45	for i := 0; i < len(testParams); i++ {
46		serializedKey, _ := proto.Marshal(testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve))
47		_, err := km.Primitive(serializedKey)
48		if err != nil {
49			t.Errorf("unexpect error in test case %d: %s ", i, err)
50		}
51	}
52}
53
54func TestECDSASignGetPrimitiveWithInvalidInput(t *testing.T) {
55	// invalid params
56	testParams := genInvalidECDSAParams()
57	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
58	if err != nil {
59		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
60	}
61	for i := 0; i < len(testParams); i++ {
62		serializedKey, _ := proto.Marshal(testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve))
63		if _, err := km.Primitive(serializedKey); err == nil {
64			t.Errorf("expect an error in test case %d", i)
65		}
66	}
67	for _, tc := range genUnkownECDSAParams() {
68		k := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256)
69		k.GetPublicKey().GetParams().Curve = tc.curve
70		k.GetPublicKey().GetParams().HashType = tc.hashType
71		serializedKey, _ := proto.Marshal(k)
72		if _, err := km.Primitive(serializedKey); err == nil {
73			t.Errorf("expect an error in test case with params: (curve = %q, hash = %q)", tc.curve, tc.hashType)
74		}
75	}
76
77	// invalid version
78	key := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256,
79		commonpb.EllipticCurveType_NIST_P256)
80	key.Version = testutil.ECDSASignerKeyVersion + 1
81	serializedKey, _ := proto.Marshal(key)
82	if _, err := km.Primitive(serializedKey); err == nil {
83		t.Errorf("expect an error when version is invalid")
84	}
85	// nil input
86	if _, err := km.Primitive(nil); err == nil {
87		t.Errorf("expect an error when input is nil")
88	}
89	if _, err := km.Primitive([]byte{}); err == nil {
90		t.Errorf("expect an error when input is empty slice")
91	}
92}
93
94func TestECDSASignNewKeyBasic(t *testing.T) {
95	testParams := genValidECDSAParams()
96	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
97	if err != nil {
98		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
99	}
100	for i := 0; i < len(testParams); i++ {
101		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
102			ecdsapb.EcdsaSignatureEncoding_DER)
103		serializedFormat, _ := proto.Marshal(testutil.NewECDSAKeyFormat(params))
104		tmp, err := km.NewKey(serializedFormat)
105		if err != nil {
106			t.Errorf("unexpected error: %s", err)
107		}
108		key := tmp.(*ecdsapb.EcdsaPrivateKey)
109		if err := validateECDSAPrivateKey(key, params); err != nil {
110			t.Errorf("invalid private key in test case %d: %s", i, err)
111		}
112	}
113}
114
115func TestECDSASignNewKeyWithInvalidInput(t *testing.T) {
116	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
117	if err != nil {
118		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
119	}
120	// invalid hash and curve type
121	testParams := genInvalidECDSAParams()
122	for i := 0; i < len(testParams); i++ {
123		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
124			ecdsapb.EcdsaSignatureEncoding_DER)
125		serializedFormat, _ := proto.Marshal(testutil.NewECDSAKeyFormat(params))
126		if _, err := km.NewKey(serializedFormat); err == nil {
127			t.Errorf("expect an error in test case %d", i)
128		}
129	}
130	// invalid encoding
131	testParams = genValidECDSAParams()
132	for i := 0; i < len(testParams); i++ {
133		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
134			ecdsapb.EcdsaSignatureEncoding_UNKNOWN_ENCODING)
135		serializedFormat, _ := proto.Marshal(testutil.NewECDSAKeyFormat(params))
136		if _, err := km.NewKey(serializedFormat); err == nil {
137			t.Errorf("expect an error in test case %d", i)
138		}
139	}
140	// nil input
141	if _, err := km.NewKey(nil); err == nil {
142		t.Errorf("expect an error when input is nil")
143	}
144	if _, err := km.NewKey([]byte{}); err == nil {
145		t.Errorf("expect an error when input is empty slice")
146	}
147}
148
149func TestECDSASignNewKeyMultipleTimes(t *testing.T) {
150	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
151	if err != nil {
152		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
153	}
154	testParams := genValidECDSAParams()
155	nTest := 27
156	for i := 0; i < len(testParams); i++ {
157		keys := make(map[string]bool)
158		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
159			ecdsapb.EcdsaSignatureEncoding_DER)
160		format := testutil.NewECDSAKeyFormat(params)
161		serializedFormat, _ := proto.Marshal(format)
162		for j := 0; j < nTest; j++ {
163			key, _ := km.NewKey(serializedFormat)
164			serializedKey, _ := proto.Marshal(key)
165			keys[string(serializedKey)] = true
166
167			keyData, _ := km.NewKeyData(serializedFormat)
168			serializedKey = keyData.Value
169			keys[string(serializedKey)] = true
170		}
171		if len(keys) != nTest*2 {
172			t.Errorf("key is repeated with params: %s", params)
173		}
174	}
175}
176
177func TestECDSASignNewKeyDataBasic(t *testing.T) {
178	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
179	if err != nil {
180		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
181	}
182	testParams := genValidECDSAParams()
183	for i := 0; i < len(testParams); i++ {
184		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
185			ecdsapb.EcdsaSignatureEncoding_DER)
186		serializedFormat, _ := proto.Marshal(testutil.NewECDSAKeyFormat(params))
187
188		keyData, err := km.NewKeyData(serializedFormat)
189		if err != nil {
190			t.Errorf("unexpected error in test case  %d: %s", i, err)
191		}
192		if keyData.TypeUrl != testutil.ECDSASignerTypeURL {
193			t.Errorf("incorrect type url in test case  %d: expect %s, got %s",
194				i, testutil.ECDSASignerTypeURL, keyData.TypeUrl)
195		}
196		if keyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PRIVATE {
197			t.Errorf("incorrect key material type in test case  %d: expect %s, got %s",
198				i, tinkpb.KeyData_ASYMMETRIC_PRIVATE, keyData.KeyMaterialType)
199		}
200		key := new(ecdsapb.EcdsaPrivateKey)
201		if err := proto.Unmarshal(keyData.Value, key); err != nil {
202			t.Errorf("unexpect error in test case %d: %s", i, err)
203		}
204		if err := validateECDSAPrivateKey(key, params); err != nil {
205			t.Errorf("invalid private key in test case %d: %s", i, err)
206		}
207	}
208}
209
210func TestECDSASignNewKeyDataWithInvalidInput(t *testing.T) {
211	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
212	if err != nil {
213		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
214	}
215	testParams := genInvalidECDSAParams()
216	for i := 0; i < len(testParams); i++ {
217		params := testutil.NewECDSAParams(testParams[i].hashType, testParams[i].curve,
218			ecdsapb.EcdsaSignatureEncoding_DER)
219		format := testutil.NewECDSAKeyFormat(params)
220		serializedFormat, _ := proto.Marshal(format)
221
222		if _, err := km.NewKeyData(serializedFormat); err == nil {
223			t.Errorf("expect an error in test case  %d", i)
224		}
225	}
226	// nil input
227	if _, err := km.NewKeyData(nil); err == nil {
228		t.Errorf("expect an error when input is nil")
229	}
230}
231
232func TestPublicKeyDataBasic(t *testing.T) {
233	testParams := genValidECDSAParams()
234	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
235	if err != nil {
236		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
237	}
238	pkm, ok := km.(registry.PrivateKeyManager)
239	if !ok {
240		t.Errorf("cannot obtain private key manager")
241	}
242	for i := 0; i < len(testParams); i++ {
243		key := testutil.NewRandomECDSAPrivateKey(testParams[i].hashType, testParams[i].curve)
244		serializedKey, _ := proto.Marshal(key)
245
246		pubKeyData, err := pkm.PublicKeyData(serializedKey)
247		if err != nil {
248			t.Errorf("unexpect error in test case %d: %s ", i, err)
249		}
250		if pubKeyData.TypeUrl != testutil.ECDSAVerifierTypeURL {
251			t.Errorf("incorrect type url: %s", pubKeyData.TypeUrl)
252		}
253		if pubKeyData.KeyMaterialType != tinkpb.KeyData_ASYMMETRIC_PUBLIC {
254			t.Errorf("incorrect key material type: %d", pubKeyData.KeyMaterialType)
255		}
256		pubKey := new(ecdsapb.EcdsaPublicKey)
257		if err = proto.Unmarshal(pubKeyData.Value, pubKey); err != nil {
258			t.Errorf("invalid public key: %s", err)
259		}
260	}
261}
262
263func TestPublicKeyDataWithInvalidInput(t *testing.T) {
264	km, err := registry.GetKeyManager(testutil.ECDSASignerTypeURL)
265	if err != nil {
266		t.Errorf("cannot obtain ECDSASigner key manager: %s", err)
267	}
268	pkm, ok := km.(registry.PrivateKeyManager)
269	if !ok {
270		t.Errorf("cannot obtain private key manager")
271	}
272	// modified key
273	key := testutil.NewRandomECDSAPrivateKey(commonpb.HashType_SHA256,
274		commonpb.EllipticCurveType_NIST_P256)
275	serializedKey, _ := proto.Marshal(key)
276	serializedKey[0] = 0
277	if _, err := pkm.PublicKeyData(serializedKey); err == nil {
278		t.Errorf("expect an error when input is a modified serialized key")
279	}
280	// invalid with a single byte
281	if _, err := pkm.PublicKeyData([]byte{42}); err == nil {
282		t.Errorf("expect an error when input is an empty slice")
283	}
284}
285
286var errSmallKey = fmt.Errorf("private key doesn't have adequate size")
287
288func validateECDSAPrivateKey(key *ecdsapb.EcdsaPrivateKey, params *ecdsapb.EcdsaParams) error {
289	if key.Version != testutil.ECDSASignerKeyVersion {
290		return fmt.Errorf("incorrect private key's version: expect %d, got %d",
291			testutil.ECDSASignerKeyVersion, key.Version)
292	}
293	publicKey := key.PublicKey
294	if publicKey.Version != testutil.ECDSASignerKeyVersion {
295		return fmt.Errorf("incorrect public key's version: expect %d, got %d",
296			testutil.ECDSASignerKeyVersion, key.Version)
297	}
298	if params.HashType != publicKey.Params.HashType ||
299		params.Curve != publicKey.Params.Curve ||
300		params.Encoding != publicKey.Params.Encoding {
301		return fmt.Errorf("incorrect params: expect %s, got %s", params, publicKey.Params)
302	}
303	if len(publicKey.X) == 0 || len(publicKey.Y) == 0 {
304		return fmt.Errorf("public points are not initialized")
305	}
306	// check private key's size
307	d := new(big.Int).SetBytes(key.KeyValue)
308	keySize := len(d.Bytes())
309	switch params.Curve {
310	case commonpb.EllipticCurveType_NIST_P256:
311		if keySize < 256/8-8 || keySize > 256/8+1 {
312			return errSmallKey
313		}
314	case commonpb.EllipticCurveType_NIST_P384:
315		if keySize < 384/8-8 || keySize > 384/8+1 {
316			return errSmallKey
317		}
318	case commonpb.EllipticCurveType_NIST_P521:
319		if keySize < 521/8-8 || keySize > 521/8+1 {
320			return errSmallKey
321		}
322	}
323	// try to sign and verify with the key
324	hash, curve, encoding := testutil.GetECDSAParamNames(publicKey.Params)
325	signer, err := subtle.NewECDSASigner(hash, curve, encoding, key.KeyValue)
326	if err != nil {
327		return fmt.Errorf("unexpected error when creating ECDSASign: %s", err)
328	}
329	verifier, err := subtle.NewECDSAVerifier(hash, curve, encoding, publicKey.X, publicKey.Y)
330	if err != nil {
331		return fmt.Errorf("unexpected error when creating ECDSAVerify: %s", err)
332	}
333	data := random.GetRandomBytes(1281)
334	signature, err := signer.Sign(data)
335	if err != nil {
336		return fmt.Errorf("unexpected error when signing: %s", err)
337	}
338
339	if err := verifier.Verify(signature, data); err != nil {
340		return fmt.Errorf("unexpected error when verifying signature: %s", err)
341	}
342	return nil
343}
344
345func genValidECDSAParams() []ecdsaParams {
346	return []ecdsaParams{
347		ecdsaParams{
348			hashType: commonpb.HashType_SHA256,
349			curve:    commonpb.EllipticCurveType_NIST_P256,
350		},
351		ecdsaParams{
352			hashType: commonpb.HashType_SHA384,
353			curve:    commonpb.EllipticCurveType_NIST_P384,
354		},
355		ecdsaParams{
356			hashType: commonpb.HashType_SHA512,
357			curve:    commonpb.EllipticCurveType_NIST_P384,
358		},
359		ecdsaParams{
360			hashType: commonpb.HashType_SHA512,
361			curve:    commonpb.EllipticCurveType_NIST_P521,
362		},
363	}
364}
365
366func genUnkownECDSAParams() []ecdsaParams {
367	return []ecdsaParams{
368		ecdsaParams{
369			hashType: commonpb.HashType_UNKNOWN_HASH,
370			curve:    commonpb.EllipticCurveType_NIST_P256,
371		},
372		ecdsaParams{
373			hashType: commonpb.HashType_SHA256,
374			curve:    commonpb.EllipticCurveType_UNKNOWN_CURVE,
375		},
376	}
377}
378
379func genInvalidECDSAParams() []ecdsaParams {
380	return []ecdsaParams{
381		ecdsaParams{
382			hashType: commonpb.HashType_SHA1,
383			curve:    commonpb.EllipticCurveType_NIST_P256,
384		},
385		ecdsaParams{
386			hashType: commonpb.HashType_SHA1,
387			curve:    commonpb.EllipticCurveType_NIST_P384,
388		},
389		ecdsaParams{
390			hashType: commonpb.HashType_SHA1,
391			curve:    commonpb.EllipticCurveType_NIST_P521,
392		},
393		ecdsaParams{
394			hashType: commonpb.HashType_SHA256,
395			curve:    commonpb.EllipticCurveType_NIST_P384,
396		},
397		ecdsaParams{
398			hashType: commonpb.HashType_SHA256,
399			curve:    commonpb.EllipticCurveType_NIST_P521,
400		},
401		ecdsaParams{
402			hashType: commonpb.HashType_SHA512,
403			curve:    commonpb.EllipticCurveType_NIST_P256,
404		},
405	}
406}
407