github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/crypto_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package tinkcrypto 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "crypto/rand" 13 "math/big" 14 "testing" 15 16 tinkaead "github.com/google/tink/go/aead" 17 tinkaeadsubtle "github.com/google/tink/go/aead/subtle" 18 hybrid "github.com/google/tink/go/hybrid/subtle" 19 "github.com/google/tink/go/keyset" 20 "github.com/google/tink/go/mac" 21 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 22 "github.com/google/tink/go/signature" 23 "github.com/google/tink/go/subtle/random" 24 "github.com/stretchr/testify/require" 25 chacha "golang.org/x/crypto/chacha20poly1305" 26 27 cryptoapi "github.com/trustbloc/kms-go/spi/crypto" 28 29 "github.com/trustbloc/kms-go/crypto" 30 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead" 31 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle" 32 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs" 33 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/ecdh" 34 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio" 35 ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto" 36 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/secp256k1" 37 ) 38 39 const testMessage = "test message" 40 41 // Assert that Crypto implements the Crypto interface. 42 var _ cryptoapi.Crypto = (*Crypto)(nil) 43 44 func TestNew(t *testing.T) { 45 _, err := New() 46 require.NoError(t, err) 47 } 48 49 func TestCrypto_EncryptDecrypt(t *testing.T) { 50 tests := []struct { 51 name string 52 ivSize int 53 aeadTemplate *tinkpb.KeyTemplate 54 }{ 55 { 56 name: "test XChacha20Poly1305 encryption", 57 ivSize: chacha.NonceSizeX, 58 aeadTemplate: tinkaead.XChaCha20Poly1305KeyTemplate(), 59 }, 60 { 61 name: "test AES256GCM encryption", 62 ivSize: tinkaeadsubtle.AESGCMIVSize, 63 aeadTemplate: tinkaead.AES256GCMKeyTemplate(), 64 }, 65 { 66 name: "test AES128CBCHMACSHA256 encryption", 67 ivSize: subtle.AESCBCIVSize, 68 aeadTemplate: aead.AES128CBCHMACSHA256KeyTemplate(), 69 }, 70 { 71 name: "test AES192CBCHMACSHA384 encryption", 72 ivSize: subtle.AESCBCIVSize, 73 aeadTemplate: aead.AES192CBCHMACSHA384KeyTemplate(), 74 }, 75 { 76 name: "test AES256CBCHMACSHA384 encryption", 77 ivSize: subtle.AESCBCIVSize, 78 aeadTemplate: aead.AES256CBCHMACSHA384KeyTemplate(), 79 }, 80 { 81 name: "test AES256CBCHMACSHA512 encryption", 82 ivSize: subtle.AESCBCIVSize, 83 aeadTemplate: aead.AES256CBCHMACSHA512KeyTemplate(), 84 }, 85 } 86 87 t.Parallel() 88 89 for _, test := range tests { 90 tc := test 91 t.Run(tc.name, func(t *testing.T) { 92 kh, err := keyset.NewHandle(tc.aeadTemplate) 93 require.NoError(t, err) 94 95 c := Crypto{} 96 msg := []byte(testMessage) 97 aad := []byte("some additional data") 98 cipherText, nonce, err := c.Encrypt(msg, aad, kh) 99 require.NoError(t, err) 100 require.NotEmpty(t, nonce) 101 require.Equal(t, tc.ivSize, len(nonce)) 102 103 plainText, err := c.Decrypt(cipherText, aad, nonce, kh) 104 require.NoError(t, err) 105 require.Equal(t, msg, plainText) 106 107 // decrypt with bad nonce - should fail 108 plainText, err = c.Decrypt(cipherText, aad, []byte("bad nonce"), kh) 109 require.Error(t, err) 110 require.Empty(t, plainText) 111 112 // decrypt with bad cipher - should fail 113 plainText, err = c.Decrypt([]byte("bad cipher"), aad, nonce, kh) 114 require.Error(t, err) 115 require.Empty(t, plainText) 116 }) 117 } 118 119 t.Run("test bad/nil kh encryption", func(t *testing.T) { 120 kh, err := keyset.NewHandle(tinkaead.AES256GCMKeyTemplate()) 121 require.NoError(t, err) 122 123 c := Crypto{} 124 msg := []byte(testMessage) 125 aad := []byte("some additional data") 126 cipherText, nonce, err := c.Encrypt(msg, aad, kh) 127 require.NoError(t, err) 128 require.NotEmpty(t, nonce) 129 require.Equal(t, tinkaeadsubtle.AESGCMIVSize, len(nonce)) 130 131 // encrypt with nil key handle - should fail 132 _, _, err = c.Encrypt(msg, aad, nil) 133 require.Error(t, err) 134 require.Equal(t, errBadKeyHandleFormat, err) 135 136 plainText, err := c.Decrypt(cipherText, aad, nonce, kh) 137 require.NoError(t, err) 138 require.Equal(t, msg, plainText) 139 140 // decrypt with bad nonce - should fail 141 plainText, err = c.Decrypt(cipherText, aad, []byte("bad nonce"), kh) 142 require.Error(t, err) 143 require.Empty(t, plainText) 144 145 // decrypt with bad cipher - should fail 146 plainText, err = c.Decrypt([]byte("bad cipher"), aad, nonce, kh) 147 require.Error(t, err) 148 require.Empty(t, plainText) 149 150 // decrypt with nil key handle - should fail 151 _, err = c.Decrypt(cipherText, aad, nonce, nil) 152 require.Error(t, err) 153 require.Equal(t, errBadKeyHandleFormat, err) 154 }) 155 } 156 157 func TestCrypto_SignVerify(t *testing.T) { 158 t.Run("test with Ed25519 signature", func(t *testing.T) { 159 kh, err := keyset.NewHandle(signature.ED25519KeyTemplate()) 160 require.NoError(t, err) 161 162 badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil)) 163 require.NoError(t, err) 164 165 c := Crypto{} 166 msg := []byte(testMessage) 167 s, err := c.Sign(msg, kh) 168 require.NoError(t, err) 169 170 // sign with nil key handle - should fail 171 _, err = c.Sign(msg, nil) 172 require.Error(t, err) 173 require.Equal(t, errBadKeyHandleFormat, err) 174 175 // sign with bad key handle - should fail 176 _, err = c.Sign(msg, badKH) 177 require.Error(t, err) 178 179 // get corresponding public key handle to verify 180 pubKH, err := kh.Public() 181 require.NoError(t, err) 182 183 err = c.Verify(s, msg, pubKH) 184 require.NoError(t, err) 185 }) 186 187 t.Run("test with P-256 signature", func(t *testing.T) { 188 kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) 189 require.NoError(t, err) 190 191 badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil)) 192 require.NoError(t, err) 193 194 c := Crypto{} 195 msg := []byte(testMessage) 196 s, err := c.Sign(msg, kh) 197 require.NoError(t, err) 198 199 // get corresponding public key handle to verify 200 pubKH, err := kh.Public() 201 require.NoError(t, err) 202 203 err = c.Verify(s, msg, pubKH) 204 require.NoError(t, err) 205 206 // verify with nil key handle - should fail 207 err = c.Verify(s, msg, nil) 208 require.Error(t, err) 209 require.Equal(t, errBadKeyHandleFormat, err) 210 211 // verify with bad key handle - should fail 212 err = c.Verify(s, msg, badKH) 213 require.Error(t, err) 214 }) 215 216 t.Run("test with P-384 signature", func(t *testing.T) { 217 kh, err := keyset.NewHandle(signature.ECDSAP384KeyTemplate()) 218 require.NoError(t, err) 219 220 badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil)) 221 require.NoError(t, err) 222 223 c := Crypto{} 224 msg := []byte(testMessage) 225 s, err := c.Sign(msg, kh) 226 require.NoError(t, err) 227 228 // get corresponding public key handle to verify 229 pubKH, err := kh.Public() 230 require.NoError(t, err) 231 232 err = c.Verify(s, msg, pubKH) 233 require.NoError(t, err) 234 235 // verify with nil key handle - should fail 236 err = c.Verify(s, msg, nil) 237 require.Error(t, err) 238 require.Equal(t, errBadKeyHandleFormat, err) 239 240 // verify with bad key handle - should fail 241 err = c.Verify(s, msg, badKH) 242 require.Error(t, err) 243 }) 244 245 t.Run("test with secp256k1 signature", func(t *testing.T) { 246 derTemplate, err := secp256k1.DERKeyTemplate() 247 require.NoError(t, err) 248 249 kh, err := keyset.NewHandle(derTemplate) 250 require.NoError(t, err) 251 252 badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil)) 253 require.NoError(t, err) 254 255 c := Crypto{} 256 msg := []byte(testMessage) 257 s, err := c.Sign(msg, kh) 258 require.NoError(t, err) 259 260 // get corresponding public key handle to verify 261 pubKH, err := kh.Public() 262 require.NoError(t, err) 263 264 err = c.Verify(s, msg, pubKH) 265 require.NoError(t, err) 266 267 // verify with nil key handle - should fail 268 err = c.Verify(s, msg, nil) 269 require.Error(t, err) 270 require.Equal(t, errBadKeyHandleFormat, err) 271 272 // verify with bad key handle - should fail 273 err = c.Verify(s, msg, badKH) 274 require.Error(t, err) 275 }) 276 } 277 278 func TestCrypto_ComputeMAC(t *testing.T) { 279 t.Run("success", func(t *testing.T) { 280 kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) 281 require.NoError(t, err) 282 require.NotNil(t, kh) 283 284 c := Crypto{} 285 msg := []byte(testMessage) 286 macBytes, err := c.ComputeMAC(msg, kh) 287 require.NoError(t, err) 288 require.NotEmpty(t, macBytes) 289 }) 290 t.Run("success - message to compute MAC with nil data - should be treated as empty data", func(t *testing.T) { 291 kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) 292 require.NoError(t, err) 293 require.NotNil(t, kh) 294 295 c := Crypto{} 296 macBytes, err := c.ComputeMAC(nil, kh) 297 require.NoError(t, err) 298 require.NotEmpty(t, macBytes) 299 }) 300 t.Run("invalid key handle", func(t *testing.T) { 301 c := Crypto{} 302 macBytes, err := c.ComputeMAC(nil, nil) 303 require.Equal(t, errBadKeyHandleFormat, err) 304 require.Empty(t, macBytes) 305 }) 306 t.Run("fail - wrong key type", func(t *testing.T) { 307 kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) 308 require.NoError(t, err) 309 require.NotNil(t, kh) 310 311 c := Crypto{} 312 msg := []byte(testMessage) 313 macBytes, err := c.ComputeMAC(msg, kh) 314 require.EqualError(t, err, "mac_factory: not a MAC primitive") 315 require.Empty(t, macBytes) 316 }) 317 } 318 319 func TestCrypto_VerifyMAC(t *testing.T) { 320 t.Run("success", func(t *testing.T) { 321 kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) 322 require.NoError(t, err) 323 require.NotNil(t, kh) 324 325 c := Crypto{} 326 msg := []byte(testMessage) 327 macBytes, err := c.ComputeMAC(msg, kh) 328 require.NoError(t, err) 329 require.NotEmpty(t, macBytes) 330 331 err = c.VerifyMAC(macBytes, msg, kh) 332 require.NoError(t, err) 333 }) 334 t.Run("bad key handle format", func(t *testing.T) { 335 c := Crypto{} 336 err := c.VerifyMAC(nil, nil, nil) 337 require.Equal(t, errBadKeyHandleFormat, err) 338 }) 339 t.Run("fail - wrong key type", func(t *testing.T) { 340 kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate()) 341 require.NoError(t, err) 342 require.NotNil(t, kh) 343 344 c := Crypto{} 345 err = c.VerifyMAC(nil, nil, kh) 346 require.EqualError(t, err, "mac_factory: not a MAC primitive") 347 }) 348 } 349 350 func TestCrypto_ECDHES_Wrap_Unwrap_Key(t *testing.T) { 351 recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 352 require.NoError(t, err) 353 354 c, err := New() 355 require.NoError(t, err) 356 357 cek := random.GetRandomBytes(uint32(crypto.DefKeySize)) 358 apu := random.GetRandomBytes(uint32(10)) // or sender name 359 apv := random.GetRandomBytes(uint32(10)) // or recipient name 360 361 // test WrapKey with nil recipientKey 362 _, err = c.WrapKey(cek, apu, apv, nil) 363 require.EqualError(t, err, "wrapKey: recipient public key is required") 364 365 // now test WrapKey with good key 366 recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle) 367 require.NoError(t, err) 368 369 wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey) 370 require.NoError(t, err) 371 require.NotEmpty(t, wrappedKey.EncryptedCEK) 372 require.NotEmpty(t, wrappedKey.EPK) 373 require.EqualValues(t, wrappedKey.APU, apu) 374 require.EqualValues(t, wrappedKey.APV, apv) 375 require.Equal(t, wrappedKey.Alg, ECDHESA256KWAlg) 376 377 // test UnwrapKey with empty recWK and/or kh 378 _, err = c.UnwrapKey(nil, nil) 379 require.EqualError(t, err, "unwrapKey: RecipientWrappedKey is empty") 380 381 _, err = c.UnwrapKey(nil, recipientKeyHandle) 382 require.EqualError(t, err, "unwrapKey: RecipientWrappedKey is empty") 383 384 _, err = c.UnwrapKey(wrappedKey, nil) 385 require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: bad key handle format") 386 387 // test UnwrapKey with ECDHES key but different curve 388 ecdh384Key, err := keyset.NewHandle(ecdh.NISTP384ECDHKWKeyTemplate()) 389 require.NoError(t, err) 390 391 _, err = c.UnwrapKey(wrappedKey, ecdh384Key) 392 require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: error ECDH-ES kek derivation: deriveESKEKForUnwrap:"+ 393 " error: deriveESWithECKeyForUnwrap: recipient and ephemeral keys are not on the same curve") 394 395 // test UnwrapKey with wrappedKey using different algorithm 396 origAlg := wrappedKey.Alg 397 wrappedKey.Alg = "badAlg" 398 _, err = c.UnwrapKey(wrappedKey, recipientKeyHandle) 399 require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: unsupported JWE KW Alg 'badAlg'") 400 401 wrappedKey.Alg = origAlg 402 403 // finally test with valid wrappedKey and recipientKey 404 uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle) // UnwrapKey will extract private key from recipientKey 405 require.NoError(t, err) 406 require.EqualValues(t, cek, uCEK) 407 } 408 409 func TestCrypto_ECDHES_Wrap_Unwrap_ForAllKeyTypes(t *testing.T) { 410 tests := []struct { 411 tcName string 412 keyTempl *tinkpb.KeyTemplate 413 kwAlg string 414 keyType string 415 keyCurve string 416 useXC20P bool 417 senderKT *tinkpb.KeyTemplate 418 err string 419 }{ 420 { 421 tcName: "key wrap using ECDH-ES with NIST P-256 key and A256GCM kw", 422 keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(), 423 kwAlg: ECDHESA256KWAlg, 424 keyType: ecdhpb.KeyType_EC.String(), 425 keyCurve: elliptic.P256().Params().Name, 426 }, 427 { 428 tcName: "key wrap using ECDH-ES with NIST P-384 key and A256GCM kw", 429 keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(), 430 kwAlg: ECDHESA256KWAlg, 431 keyType: ecdhpb.KeyType_EC.String(), 432 keyCurve: elliptic.P384().Params().Name, 433 }, 434 { 435 tcName: "key wrap using ECDH-ES with NIST P-521 key and A256GCM kw", 436 keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(), 437 kwAlg: ECDHESA256KWAlg, 438 keyType: ecdhpb.KeyType_EC.String(), 439 keyCurve: elliptic.P521().Params().Name, 440 }, 441 { 442 tcName: "key wrap using ECDH-ES with X25519 key and A256GCM kw", 443 keyTempl: ecdh.X25519ECDHKWKeyTemplate(), 444 kwAlg: ECDHESA256KWAlg, 445 keyType: ecdhpb.KeyType_OKP.String(), 446 keyCurve: "X25519", 447 }, 448 { 449 tcName: "key wrap using ECDH-ES with NIST P-256 key and XC20P kw", 450 keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(), 451 kwAlg: ECDHESXC20PKWAlg, 452 keyType: ecdhpb.KeyType_EC.String(), 453 keyCurve: elliptic.P256().Params().Name, 454 useXC20P: true, 455 }, 456 { 457 tcName: "key wrap using ECDH-ES with NIST P-384 key and XC20P kw", 458 keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(), 459 kwAlg: ECDHESXC20PKWAlg, 460 keyType: ecdhpb.KeyType_EC.String(), 461 keyCurve: elliptic.P384().Params().Name, 462 useXC20P: true, 463 }, 464 { 465 tcName: "key wrap using ECDH-ES with NIST P-521 key and XC20P kw", 466 keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(), 467 kwAlg: ECDHESXC20PKWAlg, 468 keyType: ecdhpb.KeyType_EC.String(), 469 keyCurve: elliptic.P521().Params().Name, 470 useXC20P: true, 471 }, 472 { 473 tcName: "key wrap using ECDH-ES with X25519 key and XC20P kw", 474 keyTempl: ecdh.X25519ECDHKWKeyTemplate(), 475 kwAlg: ECDHESXC20PKWAlg, 476 keyType: ecdhpb.KeyType_OKP.String(), 477 keyCurve: "X25519", 478 useXC20P: true, 479 }, 480 { 481 tcName: "key wrap using ECDH-1PU with NIST P-256 key and A128GCM kw", 482 keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(), 483 kwAlg: ECDH1PUA128KWAlg, 484 keyType: ecdhpb.KeyType_EC.String(), 485 keyCurve: elliptic.P256().Params().Name, 486 senderKT: ecdh.NISTP256ECDHKWKeyTemplate(), 487 }, 488 { 489 tcName: "key wrap using ECDH-1PU with NIST P-384 key and A192GCM kw", 490 keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(), 491 kwAlg: ECDH1PUA192KWAlg, 492 keyType: ecdhpb.KeyType_EC.String(), 493 keyCurve: elliptic.P384().Params().Name, 494 senderKT: ecdh.NISTP384ECDHKWKeyTemplate(), 495 }, 496 { 497 tcName: "key wrap using ECDH-1PU with NIST P-521 key and A256GCM kw", 498 keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(), 499 kwAlg: ECDH1PUA256KWAlg, 500 keyType: ecdhpb.KeyType_EC.String(), 501 keyCurve: elliptic.P521().Params().Name, 502 senderKT: ecdh.NISTP521ECDHKWKeyTemplate(), 503 }, 504 { 505 tcName: "key wrap using ECDH-1PU with NIST P-384 key and A256GCM kw", 506 keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(), 507 kwAlg: ECDH1PUA256KWAlg, 508 keyType: ecdhpb.KeyType_EC.String(), 509 keyCurve: elliptic.P384().Params().Name, 510 senderKT: ecdh.NISTP384ECDHKWKeyTemplate(), 511 }, 512 { 513 tcName: "key wrap using ECDH-1PU with NIST P-521 key and A256GCM kw", 514 keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(), 515 kwAlg: ECDH1PUA256KWAlg, 516 keyType: ecdhpb.KeyType_EC.String(), 517 keyCurve: elliptic.P521().Params().Name, 518 senderKT: ecdh.NISTP521ECDHKWKeyTemplate(), 519 }, 520 { 521 tcName: "key wrap using ECDH-1PU with X25519 key and A256GCM kw", 522 keyTempl: ecdh.X25519ECDHKWKeyTemplate(), 523 kwAlg: ECDH1PUA256KWAlg, 524 keyType: ecdhpb.KeyType_OKP.String(), 525 keyCurve: "X25519", 526 senderKT: ecdh.X25519ECDHKWKeyTemplate(), 527 }, 528 { 529 tcName: "key wrap using ECDH-1PU with NIST P-256 key and XC20P kw", 530 keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(), 531 kwAlg: ECDH1PUXC20PKWAlg, 532 keyType: ecdhpb.KeyType_EC.String(), 533 keyCurve: elliptic.P256().Params().Name, 534 senderKT: ecdh.NISTP256ECDHKWKeyTemplate(), 535 useXC20P: true, 536 }, 537 { 538 tcName: "key wrap using ECDH-1PU with NIST P-384 key and XC20P kw", 539 keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(), 540 kwAlg: ECDH1PUXC20PKWAlg, 541 keyType: ecdhpb.KeyType_EC.String(), 542 keyCurve: elliptic.P384().Params().Name, 543 senderKT: ecdh.NISTP384ECDHKWKeyTemplate(), 544 useXC20P: true, 545 }, 546 { 547 tcName: "key wrap using ECDH-1PU with NIST P-521 key and XC20P kw", 548 keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(), 549 kwAlg: ECDH1PUXC20PKWAlg, 550 keyType: ecdhpb.KeyType_EC.String(), 551 keyCurve: elliptic.P521().Params().Name, 552 senderKT: ecdh.NISTP521ECDHKWKeyTemplate(), 553 useXC20P: true, 554 }, 555 { 556 tcName: "key wrap using ECDH-1PU with X25519 key and XC20P kw", 557 keyTempl: ecdh.X25519ECDHKWKeyTemplate(), 558 kwAlg: ECDH1PUXC20PKWAlg, 559 keyType: ecdhpb.KeyType_OKP.String(), 560 keyCurve: "X25519", 561 senderKT: ecdh.X25519ECDHKWKeyTemplate(), 562 useXC20P: true, 563 }, 564 } 565 566 c, err := New() 567 require.NoError(t, err) 568 569 apu := random.GetRandomBytes(uint32(10)) // or sender name 570 apv := random.GetRandomBytes(uint32(10)) // or recipient name 571 572 for _, tt := range tests { 573 tc := tt 574 t.Run("Test "+tc.tcName, func(t *testing.T) { 575 keySize := aesCEKSize1PU(tc.kwAlg) 576 577 cek := random.GetRandomBytes(uint32(keySize)) 578 recipientKeyHandle, err := keyset.NewHandle(tc.keyTempl) 579 require.NoError(t, err) 580 581 recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle) 582 require.NoError(t, err) 583 584 var senderKH *keyset.Handle 585 586 var wrapKeyOtps []cryptoapi.WrapKeyOpts 587 if tc.useXC20P { 588 // WithXC20OKW option used for WrapKey() only. UnwrapKey() does not check this option, it checks kwAlg. 589 wrapKeyOtps = append(wrapKeyOtps, cryptoapi.WithXC20PKW()) 590 } 591 592 if tc.senderKT != nil { 593 senderKH, err = keyset.NewHandle(tc.senderKT) 594 require.NoError(t, err) 595 596 wrapKeyOtps = append(wrapKeyOtps, cryptoapi.WithSender(senderKH)) 597 } 598 599 wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, wrapKeyOtps...) 600 require.NoError(t, err) 601 require.NotEmpty(t, wrappedKey.EncryptedCEK) 602 require.NotEmpty(t, wrappedKey.EPK) 603 require.EqualValues(t, wrappedKey.APU, apu) 604 require.EqualValues(t, wrappedKey.APV, apv) 605 require.Equal(t, tc.kwAlg, wrappedKey.Alg) 606 require.Equal(t, tc.keyCurve, wrappedKey.EPK.Curve) 607 require.Equal(t, tc.keyType, wrappedKey.EPK.Type) 608 609 if senderKH != nil { 610 var senderPubKey *cryptoapi.PublicKey 611 612 // mimic recipient side (by using sender public key for unwrapping instead of the private key) 613 senderPubKey, err = keyio.ExtractPrimaryPublicKey(senderKH) 614 require.NoError(t, err) 615 616 // reset wrapKeyOpts because UnwrapKey only uses WithSender() option. 617 wrapKeyOtps = []cryptoapi.WrapKeyOpts{cryptoapi.WithSender(senderPubKey)} 618 } 619 620 uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, wrapKeyOtps...) 621 require.NoError(t, err) 622 require.EqualValues(t, cek, uCEK) 623 }) 624 } 625 } 626 627 func TestCrypto_ECDH1PU_Wrap_Unwrap_Key(t *testing.T) { 628 recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 629 require.NoError(t, err) 630 631 recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle) 632 require.NoError(t, err) 633 634 senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 635 require.NoError(t, err) 636 637 c, err := New() 638 require.NoError(t, err) 639 640 cek := random.GetRandomBytes(uint32(crypto.DefKeySize * 2)) 641 apu := random.GetRandomBytes(uint32(10)) // or sender name 642 apv := random.GetRandomBytes(uint32(10)) // or recipient name 643 644 // test with bad senderKH value 645 _, err = c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender("badKey")) 646 require.EqualError(t, err, "wrapKey: deriveKEKAndWrap: error ECDH-1PU kek derivation: derive1PUKEK: EC key"+ 647 " derivation error derive1PUWithECKey: failed to retrieve sender key: ksToPrivateECDSAKey: bad key handle "+ 648 "format") 649 650 // now test WrapKey with good key 651 wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender(senderKH)) 652 require.NoError(t, err) 653 require.NotEmpty(t, wrappedKey.EncryptedCEK) 654 require.NotEmpty(t, wrappedKey.EPK) 655 require.EqualValues(t, wrappedKey.APU, apu) 656 require.EqualValues(t, wrappedKey.APV, apv) 657 require.Equal(t, wrappedKey.Alg, ECDH1PUA256KWAlg) 658 659 // test with valid wrappedKey, senderKH (public key) and recipientKey 660 senderPubKH, err := senderKH.Public() 661 require.NoError(t, err) 662 663 uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderPubKH)) 664 require.NoError(t, err) 665 require.EqualValues(t, cek, uCEK) 666 667 // extract sender public key and try Unwrap using extracted key 668 senderPubKey, err := keyio.ExtractPrimaryPublicKey(senderKH) 669 require.NoError(t, err) 670 671 crv, err := hybrid.GetCurve(senderPubKey.Curve) 672 require.NoError(t, err) 673 674 senderECPubKey := &ecdsa.PublicKey{ 675 Curve: crv, 676 X: new(big.Int).SetBytes(senderPubKey.X), 677 Y: new(big.Int).SetBytes(senderPubKey.Y), 678 } 679 680 uCEK, err = c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderECPubKey)) 681 require.NoError(t, err) 682 require.EqualValues(t, cek, uCEK) 683 } 684 685 func TestCrypto_ECDH1PU_Wrap_Unwrap_Key_Using_CryptoPubKey_as_SenderKey(t *testing.T) { 686 recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 687 require.NoError(t, err) 688 689 recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle) 690 require.NoError(t, err) 691 692 senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 693 require.NoError(t, err) 694 695 c, err := New() 696 require.NoError(t, err) 697 698 cek := random.GetRandomBytes(uint32(crypto.DefKeySize * 2)) 699 apu := random.GetRandomBytes(uint32(10)) // or sender name 700 apv := random.GetRandomBytes(uint32(10)) // or recipient name 701 702 // extract sender public key as crypto.Public key to be used in WithSender() 703 senderPubKey, err := keyio.ExtractPrimaryPublicKey(senderKH) 704 require.NoError(t, err) 705 706 // test WrapKey with extacted crypto.PublicKey above directly 707 // WrapKey() only accepts senderKH as keyset.Handle because it will use its private key. 708 wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender(senderKH)) 709 require.NoError(t, err) 710 require.NotEmpty(t, wrappedKey.EncryptedCEK) 711 require.NotEmpty(t, wrappedKey.EPK) 712 require.EqualValues(t, wrappedKey.APU, apu) 713 require.EqualValues(t, wrappedKey.APV, apv) 714 require.Equal(t, wrappedKey.Alg, ECDH1PUA256KWAlg) 715 716 // UnwrapKey require sender public key used here or keyset.Handle which was tested in the previous function above 717 uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderPubKey)) 718 require.NoError(t, err) 719 require.EqualValues(t, cek, uCEK) 720 721 crv, err := hybrid.GetCurve(senderPubKey.Curve) 722 require.NoError(t, err) 723 724 senderECPubKey := &ecdsa.PublicKey{ 725 Curve: crv, 726 X: new(big.Int).SetBytes(senderPubKey.X), 727 Y: new(big.Int).SetBytes(senderPubKey.Y), 728 } 729 730 uCEK, err = c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderECPubKey)) 731 require.NoError(t, err) 732 require.EqualValues(t, cek, uCEK) 733 } 734 735 func TestBBSCrypto_SignVerify_DeriveProofVerifyProof(t *testing.T) { 736 c := Crypto{} 737 msg := [][]byte{ 738 []byte(testMessage + "0"), []byte(testMessage + "1"), []byte(testMessage + "2"), 739 []byte(testMessage + "3"), []byte(testMessage + "4"), []byte(testMessage + "5"), 740 } 741 742 var ( 743 s []byte 744 pubKH *keyset.Handle 745 badKH *keyset.Handle 746 ) 747 748 t.Run("test with BBS+ signature", func(t *testing.T) { 749 kh, err := keyset.NewHandle(bbs.BLS12381G2KeyTemplate()) 750 require.NoError(t, err) 751 752 badKH, err = keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil)) 753 require.NoError(t, err) 754 755 s, err = c.SignMulti(msg, kh) 756 require.NoError(t, err) 757 758 // sign with nil key handle - should fail 759 _, err = c.SignMulti(msg, nil) 760 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 761 762 // sign with bad key type - should fail 763 _, err = c.SignMulti(msg, "bad key type") 764 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 765 766 // sign with empty messages - should fail 767 _, err = c.SignMulti([][]byte{}, kh) 768 require.EqualError(t, err, "BBS+ sign msg: messages are not defined") 769 770 // sign with bad key handle - should fail 771 _, err = c.SignMulti(msg, badKH) 772 require.Error(t, err) 773 774 // get corresponding public key handle to verify 775 pubKH, err = kh.Public() 776 require.NoError(t, err) 777 778 err = c.VerifyMulti(msg, s, nil) 779 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 780 781 err = c.VerifyMulti(msg, s, "bad key type") 782 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 783 784 err = c.VerifyMulti(msg, s, badKH) 785 require.Error(t, err) 786 787 err = c.VerifyMulti([][]byte{}, s, pubKH) 788 require.EqualError(t, err, "BBS+ verify msg: bbs_verifier_factory: invalid signature") 789 790 err = c.VerifyMulti(msg, s, pubKH) 791 require.NoError(t, err) 792 }) 793 794 require.NotEmpty(t, s) 795 796 t.Run("test with BBS+ proof", func(t *testing.T) { 797 revealedIndexes := []int{0, 2} 798 nonce := make([]byte, 32) 799 800 _, err := rand.Read(nonce) 801 require.NoError(t, err) 802 803 _, err = c.DeriveProof(msg, s, nonce, revealedIndexes, nil) 804 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 805 806 _, err = c.DeriveProof(msg, s, nonce, revealedIndexes, "bad key type") 807 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 808 809 _, err = c.DeriveProof(msg, s, nonce, revealedIndexes, badKH) 810 require.Error(t, err) 811 812 _, err = c.DeriveProof([][]byte{}, s, nonce, revealedIndexes, pubKH) 813 require.EqualError(t, err, "verify proof msg: bbs_verifier_factory: invalid signature proof") 814 815 proof, err := c.DeriveProof(msg, s, nonce, revealedIndexes, pubKH) 816 require.NoError(t, err) 817 818 err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, nil) 819 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 820 821 err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, "bad key type") 822 require.EqualError(t, err, errBadKeyHandleFormat.Error()) 823 824 err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, badKH) 825 require.Error(t, err) 826 827 err = c.VerifyProof([][]byte{msg[3], msg[4]}, proof, nonce, pubKH) 828 require.EqualError(t, err, "verify proof msg: bbs_verifier_factory: invalid signature proof") 829 830 err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, pubKH) 831 require.NoError(t, err) 832 }) 833 }