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