github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/packager/packager_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package packager_test 8 9 import ( 10 "encoding/base64" 11 "fmt" 12 "strings" 13 "testing" 14 15 "github.com/stretchr/testify/require" 16 17 cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto" 18 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 19 . "github.com/hyperledger/aries-framework-go/pkg/didcomm/packager" 20 "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer" 21 "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/authcrypt" 22 legacy "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer/legacy/authcrypt" 23 "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" 24 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 25 "github.com/hyperledger/aries-framework-go/pkg/doc/jose" 26 "github.com/hyperledger/aries-framework-go/pkg/doc/util/jwkkid" 27 "github.com/hyperledger/aries-framework-go/pkg/doc/util/kmsdidkey" 28 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 29 "github.com/hyperledger/aries-framework-go/pkg/kms" 30 "github.com/hyperledger/aries-framework-go/pkg/kms/localkms" 31 "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm" 32 mockdiddoc "github.com/hyperledger/aries-framework-go/pkg/mock/diddoc" 33 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 34 mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr" 35 "github.com/hyperledger/aries-framework-go/pkg/secretlock" 36 "github.com/hyperledger/aries-framework-go/pkg/secretlock/noop" 37 "github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint" 38 "github.com/hyperledger/aries-framework-go/spi/storage" 39 ) 40 41 const localKeyURI = "local-lock://test/key-uri/" 42 43 func TestNewPackagerMissingPrimaryPacker(t *testing.T) { 44 mockedProviders := &mockProvider{ 45 primaryPacker: nil, 46 packers: nil, 47 } 48 49 _, err := New(mockedProviders) 50 require.EqualError(t, err, "need primary packer to initialize packager") 51 } 52 53 func TestBaseKMSInPackager_UnpackMessage(t *testing.T) { 54 cryptoSvc, err := tinkcrypto.New() 55 require.NoError(t, err) 56 57 t.Run("test failed to create packer encMessage due to missing vdr in provider", func(t *testing.T) { 58 // create a custom KMS instance with this provider 59 customKMS, err := localkms.New(localKeyURI, newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 60 require.NoError(t, err) 61 require.NotEmpty(t, customKMS) 62 63 mockedProviders := &mockProvider{ 64 kms: customKMS, 65 primaryPacker: nil, 66 packers: nil, 67 crypto: cryptoSvc, 68 } 69 70 _, err = authcrypt.New(mockedProviders, jose.A128CBCHS256) 71 require.EqualError(t, err, "authcrypt: failed to create packer because vdr registry is empty") 72 }) 73 74 t.Run("test failed to unmarshal encMessage", func(t *testing.T) { 75 // create a custom KMS instance with this provider 76 customKMS, err := localkms.New(localKeyURI, 77 newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 78 require.NoError(t, err) 79 require.NotEmpty(t, customKMS) 80 81 require.NoError(t, err) 82 83 mockedProviders := &mockProvider{ 84 kms: customKMS, 85 primaryPacker: nil, 86 packers: nil, 87 crypto: cryptoSvc, 88 vdr: &mockvdr.MockVDRegistry{}, 89 } 90 91 testPacker, err := authcrypt.New(mockedProviders, jose.A128CBCHS256) 92 require.NoError(t, err) 93 94 mockedProviders.primaryPacker = testPacker 95 packager, err := New(mockedProviders) 96 require.NoError(t, err) 97 _, err = packager.UnpackMessage(nil) 98 require.Error(t, err) 99 require.Contains(t, err.Error(), "unexpected end of JSON input") 100 }) 101 102 t.Run("test bad encoding type", func(t *testing.T) { 103 customKMS, err := localkms.New(localKeyURI, 104 newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 105 require.NoError(t, err) 106 require.NotEmpty(t, customKMS) 107 108 mockedProviders := &mockProvider{ 109 storage: mockstorage.NewMockStoreProvider(), 110 kms: customKMS, 111 primaryPacker: nil, 112 packers: nil, 113 crypto: cryptoSvc, 114 vdr: &mockvdr.MockVDRegistry{}, 115 } 116 testPacker, err := authcrypt.New(mockedProviders, jose.A192CBCHS384) 117 require.NoError(t, err) 118 119 mockedProviders.primaryPacker = testPacker 120 packager, err := New(mockedProviders) 121 require.NoError(t, err) 122 123 msg := []byte(`{"protected":"` + base64.RawURLEncoding.EncodeToString([]byte(`{"typ":"badtype"}`)) + `"}`) 124 125 _, err = packager.UnpackMessage(msg) 126 require.Error(t, err) 127 require.Contains(t, err.Error(), "message Type not recognized") 128 129 msg = []byte(`{"protected":"` + "## NOT B64 ##" + `"}`) 130 131 _, err = packager.UnpackMessage(msg) 132 require.Error(t, err) 133 require.Contains(t, err.Error(), "illegal base64 data") 134 135 msg = []byte(`{"protected":"` + base64.RawURLEncoding.EncodeToString([]byte(`## NOT JSON ##`)) + `"}`) 136 137 _, err = packager.UnpackMessage(msg) 138 require.Error(t, err) 139 require.Contains(t, err.Error(), "invalid character") 140 }) 141 142 t.Run("test key not found", func(t *testing.T) { 143 storeMap := make(map[string]mockstorage.DBEntry) 144 customStore := &mockstorage.MockStore{ 145 Store: storeMap, 146 } 147 148 // create a customKMS with a custom storage provider using the above store to access the store map. 149 customKMS, err := localkms.New(localKeyURI, 150 newMockKMSProvider(mockstorage.NewCustomMockStoreProvider(customStore), t)) 151 require.NoError(t, err) 152 require.NotEmpty(t, customKMS) 153 154 mockedProviders := &mockProvider{ 155 kms: customKMS, 156 crypto: cryptoSvc, 157 primaryPacker: nil, 158 packers: nil, 159 vdr: &mockvdr.MockVDRegistry{}, 160 } 161 testPacker, err := authcrypt.New(mockedProviders, jose.A256CBCHS512) 162 require.NoError(t, err) 163 164 // use a real testPacker and a real KMS to validate pack/unpack 165 mockedProviders.primaryPacker = testPacker 166 packager, err := New(mockedProviders) 167 require.NoError(t, err) 168 169 // fromKey is stored in the KMS 170 _, fromKey, err := customKMS.CreateAndExportPubKeyBytes(kms.NISTP256ECDHKWType) 171 require.NoError(t, err) 172 173 fromDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(fromKey, kms.NISTP256ECDHKWType) 174 require.NoError(t, err) 175 176 // toVerKey is stored in the KMS as well 177 toKID, toKey, err := customKMS.CreateAndExportPubKeyBytes(kms.NISTP256ECDHKWType) 178 require.NoError(t, err) 179 180 toDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(toKey, kms.NISTP256ECDHKWType) 181 require.NoError(t, err) 182 183 // PackMessage should pass with both value from and to keys 184 packMsg, err := packager.PackMessage(&transport.Envelope{ 185 MediaTypeProfile: transport.MediaTypeV1EncryptedEnvelope, 186 Message: []byte("msg1"), 187 FromKey: []byte(fromDIDKey), 188 ToKeys: []string{toDIDKey}, 189 }) 190 require.NoError(t, err) 191 192 // mock KMS without ToKey then try UnpackMessage 193 delete(storeMap, toKID) // keys in storeMap are prefixed 194 195 // It should fail since Recipient keys are not found in the KMS 196 _, err = packager.UnpackMessage(packMsg) 197 require.Error(t, err) 198 require.EqualError(t, err, "unpack: authcrypt Unpack: no matching recipient in envelope") 199 }) 200 201 t.Run("test Pack/Unpack fails", func(t *testing.T) { 202 customKMS, err := localkms.New(localKeyURI, 203 newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 204 require.NoError(t, err) 205 require.NotEmpty(t, customKMS) 206 207 decryptValue := func(envelope []byte) (*transport.Envelope, error) { 208 return nil, fmt.Errorf("unpack error") 209 } 210 211 mockedProviders := &mockProvider{ 212 kms: customKMS, 213 primaryPacker: nil, 214 packers: nil, 215 crypto: cryptoSvc, 216 vdr: &mockvdr.MockVDRegistry{}, 217 } 218 219 // use a mocked packager with a mocked KMS to validate pack/unpack 220 e := func(cty string, payload []byte, senderPubKey []byte, recipientsKeys [][]byte) (bytes []byte, e error) { 221 p, e := authcrypt.New(mockedProviders, jose.A128CBCHS256) 222 require.NoError(t, e) 223 return p.Pack(cty, payload, senderPubKey, recipientsKeys) 224 } 225 226 mockPacker := &didcomm.MockAuthCrypt{ 227 DecryptValue: decryptValue, 228 EncryptValue: e, Type: transport.MediaTypeV2EncryptedEnvelope + "-authcrypt", 229 } 230 231 mockedProviders.primaryPacker = mockPacker 232 233 packager, err := New(mockedProviders) 234 require.NoError(t, err) 235 236 // use ECDH1PU type as we are using a sender key (ie: packer's FromKey is not empty aka authcrypt) 237 _, fromKey, err := customKMS.CreateAndExportPubKeyBytes(kms.NISTP384ECDHKWType) 238 require.NoError(t, err) 239 240 fromDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(fromKey, kms.NISTP384ECDHKWType) 241 require.NoError(t, err) 242 243 _, toKey, err := customKMS.CreateAndExportPubKeyBytes(kms.NISTP384ECDHKWType) 244 require.NoError(t, err) 245 246 toDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(toKey, kms.NISTP384ECDHKWType) 247 require.NoError(t, err) 248 249 // try pack with nil envelope - should fail 250 packMsg, err := packager.PackMessage(nil) 251 require.EqualError(t, err, "packMessage: envelope argument is nil") 252 require.Empty(t, packMsg) 253 254 // now try to pack with non empty envelope - should pass 255 packMsg, err = packager.PackMessage(&transport.Envelope{ 256 MediaTypeProfile: transport.MediaTypeV1EncryptedEnvelope, 257 Message: []byte("msg1"), 258 FromKey: []byte(fromDIDKey), 259 ToKeys: []string{toDIDKey}, 260 }) 261 require.NoError(t, err) 262 require.NotEmpty(t, packMsg) 263 264 // now try unpack - should fail since we mocked the packager's Unpack value to return "decrypt error" 265 // see 'decryptValue' above 266 _, err = packager.UnpackMessage(packMsg) 267 require.Error(t, err) 268 require.EqualError(t, err, "unpack: unpack error") 269 270 // now mock pack failure to test PackMessage with non empty envelope 271 e = func(cty string, payload []byte, senderPubKey []byte, recipientsKeys [][]byte) (bytes []byte, e error) { 272 return nil, fmt.Errorf("pack error") 273 } 274 mockPacker = &didcomm.MockAuthCrypt{EncryptValue: e} 275 mockedProviders.primaryPacker = mockPacker 276 packager, err = New(mockedProviders) 277 require.NoError(t, err) 278 packMsg, err = packager.PackMessage(&transport.Envelope{ 279 MediaTypeProfile: transport.MediaTypeV1EncryptedEnvelope, 280 Message: []byte("msg1"), 281 FromKey: []byte(fromDIDKey), 282 ToKeys: []string{toDIDKey}, 283 }) 284 require.Error(t, err) 285 require.Empty(t, packMsg) 286 require.EqualError(t, err, "packMessage: failed to pack: pack error") 287 }) 288 289 t.Run("test Pack/Unpack success", func(t *testing.T) { 290 customKMS, err := localkms.New(localKeyURI, newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 291 require.NoError(t, err) 292 require.NotEmpty(t, customKMS) 293 294 tests := []struct { 295 name string 296 keyType kms.KeyType 297 }{ 298 { 299 name: "Pack/Unpack success with P-256 ECDH KW keys", 300 keyType: kms.NISTP256ECDHKWType, 301 }, 302 { 303 name: "Pack/Unpack success with P-384 ECDH KW keys", 304 keyType: kms.NISTP384ECDHKWType, 305 }, 306 { 307 name: "Pack/Unpack success with P-521 ECDH KW keys", 308 keyType: kms.NISTP521ECDHKWType, 309 }, 310 { 311 name: "Pack/Unpack success with X25519 ECDH KW keys", 312 keyType: kms.X25519ECDHKWType, 313 }, 314 } 315 316 for _, tt := range tests { 317 tc := tt 318 t.Run(tc.name, func(t *testing.T) { 319 packUnPackSuccess(tc.keyType, customKMS, cryptoSvc, t) 320 }) 321 } 322 }) 323 324 t.Run("test success - dids not found", func(t *testing.T) { 325 customKMS, err := localkms.New(localKeyURI, 326 newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 327 require.NoError(t, err) 328 require.NotEmpty(t, customKMS) 329 330 require.NoError(t, err) 331 mockedProviders := &mockProvider{ 332 kms: customKMS, 333 primaryPacker: nil, 334 packers: nil, 335 } 336 337 // create a real testPacker (no mocking here) 338 testPacker := legacy.New(mockedProviders) 339 require.NoError(t, err) 340 mockedProviders.primaryPacker = testPacker 341 342 mockedProviders.packers = []packer.Packer{testPacker} 343 344 // now create a new packager with the above provider context 345 packager, err := New(mockedProviders) 346 require.NoError(t, err) 347 348 _, fromKey, err := customKMS.CreateAndExportPubKeyBytes(kms.ED25519Type) 349 require.NoError(t, err) 350 351 fromDIDKey, _ := fingerprint.CreateDIDKey(fromKey) 352 353 _, toKey, err := customKMS.CreateAndExportPubKeyBytes(kms.ED25519Type) 354 require.NoError(t, err) 355 356 toDIDKey, _ := fingerprint.CreateDIDKey(toKey) 357 358 // pack an non empty envelope - should pass 359 packMsg, err := packager.PackMessage(&transport.Envelope{ 360 // not passing CTY intentionally because packager.primaryPacker is legacyPacker (it ignores CTY). 361 Message: []byte("msg1"), 362 FromKey: []byte(fromDIDKey), 363 ToKeys: []string{toDIDKey}, 364 }) 365 require.NoError(t, err) 366 367 // unpack the packed message above - should pass and match the same payload (msg1) 368 unpackedMsg, err := packager.UnpackMessage(packMsg) 369 require.NoError(t, err) 370 require.Equal(t, unpackedMsg.Message, []byte("msg1")) 371 }) 372 } 373 374 func packUnPackSuccess(keyType kms.KeyType, customKMS kms.KeyManager, cryptoSvc cryptoapi.Crypto, t *testing.T) { 375 resolveDIDFunc, fromDIDKey, toDIDKey, fromDID, toDID := newDIDsAndDIDDocResolverFunc(customKMS, 376 keyType, t) 377 378 mockedProviders := &mockProvider{ 379 kms: customKMS, 380 primaryPacker: nil, 381 packers: nil, 382 crypto: cryptoSvc, 383 // vdr context for DID doc resolution: 384 vdr: &mockvdr.MockVDRegistry{ 385 ResolveFunc: resolveDIDFunc, 386 }, 387 } 388 389 // create a real testPacker (no mocking here) 390 testPacker, err := authcrypt.New(mockedProviders, jose.A256CBCHS512) 391 require.NoError(t, err) 392 393 mockedProviders.primaryPacker = testPacker 394 395 legacyPacker := legacy.New(mockedProviders) 396 mockedProviders.packers = []packer.Packer{testPacker, legacyPacker} 397 398 // now create a new packager with the above provider context 399 packager, err := New(mockedProviders) 400 require.NoError(t, err) 401 402 // legacy packer uses ED25519 keys only 403 _, fromKeyED25519, err := customKMS.CreateAndExportPubKeyBytes(kms.ED25519) 404 require.NoError(t, err) 405 406 fromDIDKeyED25519, _ := fingerprint.CreateDIDKey(fromKeyED25519) 407 408 _, toKeyEd25519, err := customKMS.CreateAndExportPubKeyBytes(kms.ED25519) 409 require.NoError(t, err) 410 411 toLegacyDIDKey, _ := fingerprint.CreateDIDKey(toKeyEd25519) 412 413 tests := []struct { 414 name string 415 mediaType string 416 isKeyAgreementKey bool 417 }{ 418 { 419 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeRFC0019EncryptedEnvelope), 420 mediaType: transport.MediaTypeRFC0019EncryptedEnvelope, 421 }, 422 { 423 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeV1PlaintextPayload), 424 mediaType: transport.MediaTypeV1PlaintextPayload, 425 }, 426 { 427 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeV1EncryptedEnvelope), 428 mediaType: transport.MediaTypeV1EncryptedEnvelope, 429 }, 430 { 431 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeV2EncryptedEnvelopeV1PlaintextPayload), 432 mediaType: transport.MediaTypeV2EncryptedEnvelopeV1PlaintextPayload, 433 }, 434 { 435 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeV2PlaintextPayload), 436 mediaType: transport.MediaTypeV2PlaintextPayload, 437 }, 438 { 439 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeV2EncryptedEnvelope), 440 mediaType: transport.MediaTypeV2EncryptedEnvelope, 441 }, 442 { 443 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeAIP2RFC0019Profile), 444 mediaType: transport.MediaTypeAIP2RFC0019Profile, 445 }, 446 { 447 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeProfileDIDCommAIP1), 448 mediaType: transport.MediaTypeProfileDIDCommAIP1, 449 }, 450 { 451 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeAIP2RFC0587Profile), 452 mediaType: transport.MediaTypeAIP2RFC0587Profile, 453 }, 454 { 455 name: fmt.Sprintf("success using mediaType %s", transport.MediaTypeDIDCommV2Profile), 456 mediaType: transport.MediaTypeDIDCommV2Profile, 457 }, 458 { 459 name: fmt.Sprintf("success using mediaType %s with KeyAgreement", 460 transport.MediaTypeAIP2RFC0587Profile), 461 mediaType: transport.MediaTypeAIP2RFC0587Profile, 462 isKeyAgreementKey: true, 463 }, 464 { 465 name: fmt.Sprintf("success using mediaType %s with KeyAgreement", transport.MediaTypeDIDCommV2Profile), 466 mediaType: transport.MediaTypeDIDCommV2Profile, 467 isKeyAgreementKey: true, 468 }, 469 } 470 471 for _, tt := range tests { 472 tc := tt 473 474 t.Run(tc.name, func(t *testing.T) { 475 var ( 476 fromKIDPack []byte 477 toKIDsPack []string 478 ) 479 480 switch tc.mediaType { 481 case transport.MediaTypeRFC0019EncryptedEnvelope, transport.MediaTypeAIP2RFC0019Profile, 482 transport.MediaTypeProfileDIDCommAIP1: 483 fromKIDPack = []byte(fromDIDKeyED25519) 484 toKIDsPack = []string{toLegacyDIDKey} 485 case transport.MediaTypeV1EncryptedEnvelope, transport.MediaTypeV1PlaintextPayload, 486 transport.MediaTypeV2EncryptedEnvelopeV1PlaintextPayload, transport.MediaTypeV2PlaintextPayload, 487 transport.MediaTypeV2EncryptedEnvelope, transport.MediaTypeAIP2RFC0587Profile, 488 transport.MediaTypeDIDCommV2Profile: 489 if tc.isKeyAgreementKey { 490 fromKIDPack = []byte(fromDID.KeyAgreement[0].VerificationMethod.ID) 491 toKIDsPack = []string{toDID.KeyAgreement[0].VerificationMethod.ID} 492 } else { 493 fromKIDPack = []byte(fromDIDKey) 494 toKIDsPack = []string{toDIDKey} 495 } 496 } 497 498 // pack an non empty envelope using packer selected by mediaType - should pass 499 packMsg, err := packager.PackMessage(&transport.Envelope{ 500 MediaTypeProfile: tc.mediaType, 501 Message: []byte("msg"), 502 FromKey: fromKIDPack, 503 ToKeys: toKIDsPack, 504 }) 505 require.NoError(t, err) 506 507 // unpack the packed message above - should pass and match the same payload (msg1) 508 unpackedMsg, err := packager.UnpackMessage(packMsg) 509 require.NoError(t, err) 510 require.Equal(t, unpackedMsg.Message, []byte("msg")) 511 512 switch tc.mediaType { 513 case transport.MediaTypeV1EncryptedEnvelope, transport.MediaTypeV1PlaintextPayload, 514 transport.MediaTypeV2EncryptedEnvelopeV1PlaintextPayload, transport.MediaTypeV2PlaintextPayload, 515 transport.MediaTypeV2EncryptedEnvelope, transport.MediaTypeAIP2RFC0587Profile, 516 transport.MediaTypeDIDCommV2Profile: 517 // try to unpack with packedMsg base64 encoded and wrapped with double quotes. 518 wrappedMsg := append([]byte("\""), []byte(base64.RawURLEncoding.EncodeToString(packMsg))...) 519 wrappedMsg = append(wrappedMsg, []byte("\"")...) 520 unpackedMsg, err = packager.UnpackMessage(wrappedMsg) 521 require.NoError(t, err) 522 require.Equal(t, unpackedMsg.Message, []byte("msg")) 523 } 524 }) 525 } 526 } 527 528 func TestPackagerLegacyInterop(t *testing.T) { 529 customKMS, err := localkms.New(localKeyURI, newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 530 require.NoError(t, err) 531 require.NotEmpty(t, customKMS) 532 533 cryptoSvc, err := tinkcrypto.New() 534 require.NoError(t, err) 535 536 resolveLegacyDIDFunc, legacyFromDID, legacyToDID := newLegacyDIDsAndDIDDocResolverFunc(t, customKMS) 537 538 mockedProviders := &mockProvider{ 539 kms: customKMS, 540 primaryPacker: nil, 541 packers: nil, 542 crypto: cryptoSvc, 543 // vdr context for DID doc resolution: 544 vdr: &mockvdr.MockVDRegistry{ 545 ResolveFunc: resolveLegacyDIDFunc, 546 }, 547 } 548 549 legacyPacker := legacy.New(mockedProviders) 550 mockedProviders.primaryPacker = legacyPacker 551 mockedProviders.packers = []packer.Packer{legacyPacker} 552 553 // now create a new packager with the above provider context 554 packager, err := New(mockedProviders) 555 require.NoError(t, err) 556 557 tests := []struct { 558 name string 559 mediaType string 560 isKeyAgreementKey bool 561 fromKIDPack []byte 562 toKIDsPack []string 563 }{ 564 { 565 name: fmt.Sprintf("success using mediaType %s with did key references", 566 transport.MediaTypeRFC0019EncryptedEnvelope), 567 mediaType: transport.MediaTypeRFC0019EncryptedEnvelope, 568 fromKIDPack: []byte(legacyFromDID.VerificationMethod[0].ID), 569 toKIDsPack: []string{legacyToDID.VerificationMethod[0].ID}, 570 }, 571 { 572 name: fmt.Sprintf("success using mediaType %s with raw keys", 573 transport.MediaTypeRFC0019EncryptedEnvelope), 574 mediaType: transport.MediaTypeRFC0019EncryptedEnvelope, 575 fromKIDPack: legacyFromDID.VerificationMethod[0].Value, 576 toKIDsPack: []string{string(legacyToDID.VerificationMethod[0].Value)}, 577 }, 578 } 579 580 for _, tt := range tests { 581 tc := tt 582 583 t.Run(tc.name, func(t *testing.T) { 584 // pack a non-empty envelope using packer selected by mediaType - should pass 585 packMsg, err := packager.PackMessage(&transport.Envelope{ 586 MediaTypeProfile: tc.mediaType, 587 Message: []byte("msg"), 588 FromKey: tc.fromKIDPack, 589 ToKeys: tc.toKIDsPack, 590 }) 591 require.NoError(t, err) 592 593 // unpack the packed message above - should pass and match the same payload (msg1) 594 unpackedMsg, err := packager.UnpackMessage(packMsg) 595 require.NoError(t, err) 596 require.Equal(t, unpackedMsg.Message, []byte("msg")) 597 }) 598 } 599 } 600 601 func TestPackager_PackMessage_DIDKey_Failures(t *testing.T) { 602 cryptoSvc, err := tinkcrypto.New() 603 require.NoError(t, err) 604 605 customKMS, err := localkms.New(localKeyURI, newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 606 require.NoError(t, err) 607 608 mockedProviders := &mockProvider{ 609 kms: customKMS, 610 primaryPacker: nil, 611 packers: nil, 612 crypto: cryptoSvc, 613 // vdr context for DID doc resolution: 614 vdr: &mockvdr.MockVDRegistry{}, 615 } 616 617 // create a real testPacker (no mocking here) 618 testPacker, err := authcrypt.New(mockedProviders, jose.A256CBCHS512) 619 require.NoError(t, err) 620 621 mockedProviders.primaryPacker = testPacker 622 623 legacyPacker := legacy.New(mockedProviders) 624 mockedProviders.packers = []packer.Packer{testPacker, legacyPacker} 625 626 // now create a new packager with the above provider context 627 packager, err := New(mockedProviders) 628 require.NoError(t, err) 629 630 tests := []struct { 631 name string 632 fromKey []byte 633 toKeys []string 634 errMsg string 635 }{ 636 { 637 name: "pack error with invalid recipient key as didKey", 638 toKeys: []string{"did:key:zInvalidKey"}, 639 errMsg: "packMessage: prepareSenderAndRecipientKeys: failed to parse public key bytes " + 640 "from did:key verKey for recipient 1: encryptionPubKeyFromDIDKey: extractRawKey: " + 641 "PubKeyFromFingerprint failure: unknown key encoding", 642 }, 643 { 644 name: "pack error with invalid sender key as didKey", 645 fromKey: []byte("did:key:zInvalidKey"), 646 toKeys: []string{"did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F"}, 647 errMsg: "packMessage: prepareSenderAndRecipientKeys: failed to extract pubKeyBytes from senderVerKey: " + 648 "encryptionPubKeyFromDIDKey: extractRawKey: PubKeyFromFingerprint " + 649 "failure: unknown key encoding", 650 }, 651 { 652 name: "pack error with invalid sender key not didKey nor keyAgreement", 653 fromKey: []byte("zInvalidKey"), 654 toKeys: []string{"did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F"}, 655 errMsg: "packMessage: failed to pack: authcrypt Pack: failed to get sender key from KMS: getKeySet: " + 656 "failed to read json keyset from reader: cannot read data for keysetID zInvalidKey: key not found. " + 657 "Underlying error: data not found", 658 }, 659 } 660 661 for _, tt := range tests { 662 tc := tt 663 t.Run(tc.name, func(t *testing.T) { 664 _, err = packager.PackMessage(&transport.Envelope{ 665 Message: []byte("msg1"), 666 FromKey: tc.fromKey, 667 ToKeys: tc.toKeys, 668 }) 669 require.EqualError(t, err, tc.errMsg) 670 }) 671 } 672 } 673 674 func TestPackager_PackMessage_KeyAgreementID_Failures(t *testing.T) { 675 cryptoSvc, err := tinkcrypto.New() 676 require.NoError(t, err) 677 678 customKMS, err := localkms.New(localKeyURI, newMockKMSProvider(mockstorage.NewMockStoreProvider(), t)) 679 require.NoError(t, err) 680 681 //nolint:dogsled 682 resolveDIDFunc, _, _, _, toDID := newDIDsAndDIDDocResolverFunc(customKMS, kms.X25519ECDHKWType, t) 683 684 mockedProviders := &mockProvider{ 685 kms: customKMS, 686 primaryPacker: nil, 687 packers: nil, 688 crypto: cryptoSvc, 689 // vdr context for DID doc resolution: 690 vdr: &mockvdr.MockVDRegistry{ 691 ResolveFunc: resolveDIDFunc, 692 }, 693 } 694 695 // create a real testPacker (no mocking here) 696 testPacker, err := authcrypt.New(mockedProviders, jose.XC20P) 697 require.NoError(t, err) 698 699 mockedProviders.primaryPacker = testPacker 700 701 legacyPacker := legacy.New(mockedProviders) 702 mockedProviders.packers = []packer.Packer{testPacker, legacyPacker} 703 704 // now create a new packager with the above provider context 705 packager, err := New(mockedProviders) 706 require.NoError(t, err) 707 708 tests := []struct { 709 name string 710 fromKey []byte 711 toKeys []string 712 errMsg string 713 }{ 714 { 715 name: "pack error with invalid recipient key as keyAgreementID", 716 toKeys: []string{toDID.ID + "#invalidKey"}, 717 errMsg: "packMessage: prepareSenderAndRecipientKeys: for recipient 1: resolveKeyAgreementFromDIDDoc: " + 718 "keyAgreement ID 'did:peer:bobdid#invalidKey' not found in DID 'did:peer:bobdid'", 719 }, 720 { 721 name: "pack error with invalid sender key as keyAgreementID", 722 fromKey: []byte(toDID.ID + "#invalidKey"), 723 toKeys: []string{toDID.ID + "#key-4"}, 724 errMsg: "packMessage: prepareSenderAndRecipientKeys: for sender: resolveKeyAgreementFromDIDDoc: " + 725 "keyAgreement ID 'did:peer:bobdid#invalidKey' not found in DID 'did:peer:bobdid'", 726 }, 727 { 728 name: "pack error with invalid sender key as keyAgreementID from a bad DID", 729 fromKey: []byte("did:peer:badDID#invalidKey"), 730 toKeys: []string{toDID.ID + "#key-4"}, 731 errMsg: "packMessage: prepareSenderAndRecipientKeys: for sender: resolveKeyAgreementFromDIDDoc: " + 732 "for recipient DID doc resolution did not found: did:peer:badDID", 733 }, 734 } 735 736 for _, tt := range tests { 737 tc := tt 738 t.Run(tc.name, func(t *testing.T) { 739 _, err = packager.PackMessage(&transport.Envelope{ 740 Message: []byte("msg1"), 741 FromKey: tc.fromKey, 742 ToKeys: tc.toKeys, 743 }) 744 require.EqualError(t, err, tc.errMsg) 745 }) 746 } 747 } 748 749 type resolverFunc func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) 750 751 //nolint:lll 752 func newDIDsAndDIDDocResolverFunc(customKMS kms.KeyManager, keyType kms.KeyType, t *testing.T) (resolverFunc, string, string, *did.Doc, *did.Doc) { 753 t.Helper() 754 755 _, fromKey, err := customKMS.CreateAndExportPubKeyBytes(keyType) 756 require.NoError(t, err) 757 758 fromDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(fromKey, keyType) 759 require.NoError(t, err) 760 761 fromJWK, err := jwkkid.BuildJWK(fromKey, keyType) 762 require.NoError(t, err) 763 764 vmKeyType := "JsonWebKey2020" 765 766 if keyType == kms.X25519ECDHKWType { 767 vmKeyType = "X25519KeyAgreementKey2019" 768 } 769 770 fromDID := mockdiddoc.GetMockDIDDocWithDIDCommV2Bloc(t, "alicedid") 771 fromKA, err := did.NewVerificationMethodFromJWK( 772 fromDID.KeyAgreement[0].VerificationMethod.ID, vmKeyType, fromDID.ID, fromJWK) 773 require.NoError(t, err) 774 775 fromDID.KeyAgreement = []did.Verification{ 776 { 777 VerificationMethod: *fromKA, 778 }, 779 } 780 781 _, toKey, err := customKMS.CreateAndExportPubKeyBytes(keyType) 782 require.NoError(t, err) 783 784 toDIDKey, err := kmsdidkey.BuildDIDKeyByKeyType(toKey, keyType) 785 require.NoError(t, err) 786 787 toJWK, err := jwkkid.BuildJWK(toKey, keyType) 788 require.NoError(t, err) 789 790 toDID := mockdiddoc.GetMockDIDDocWithDIDCommV2Bloc(t, "bobdid") 791 toKA, err := did.NewVerificationMethodFromJWK( 792 toDID.KeyAgreement[0].VerificationMethod.ID, vmKeyType, toDID.ID, toJWK) 793 require.NoError(t, err) 794 795 toDID.KeyAgreement = []did.Verification{ 796 { 797 VerificationMethod: *toKA, 798 }, 799 } 800 801 resolveDID := func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 802 switch didID { 803 case toDID.ID: 804 return &did.DocResolution{ 805 DIDDocument: toDID, 806 }, nil 807 case fromDID.ID: 808 return &did.DocResolution{ 809 DIDDocument: fromDID, 810 }, nil 811 default: 812 return nil, fmt.Errorf("did not found: %s", didID) 813 } 814 } 815 816 return resolveDID, fromDIDKey, toDIDKey, fromDID, toDID 817 } 818 819 func makeRawKey(t *testing.T, customKMS kms.KeyManager) []byte { 820 t.Helper() 821 822 var ( 823 key []byte 824 err error 825 ) 826 827 // for tests using raw keys, we need raw keys that won't be misinterpreted as did key references. 828 for key == nil || strings.Index(string(key), "#") > 0 { //nolint:gocritic // need to check with strings 829 _, key, err = customKMS.CreateAndExportPubKeyBytes(kms.ED25519Type) 830 require.NoError(t, err) 831 } 832 833 return key 834 } 835 836 func newLegacyDIDsAndDIDDocResolverFunc(t *testing.T, customKMS kms.KeyManager) (resolverFunc, *did.Doc, *did.Doc) { 837 t.Helper() 838 839 fromKey := makeRawKey(t, customKMS) 840 toKey := makeRawKey(t, customKMS) 841 842 fromDID := mockdiddoc.GetLegacyInteropMockDIDDoc(t, "AliceDIDInterop", fromKey) 843 toDID := mockdiddoc.GetLegacyInteropMockDIDDoc(t, "BobDIDInterop", toKey) 844 845 resolveDID := func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) { 846 switch didID { 847 case toDID.ID: 848 return &did.DocResolution{ 849 DIDDocument: toDID, 850 }, nil 851 case fromDID.ID: 852 return &did.DocResolution{ 853 DIDDocument: fromDID, 854 }, nil 855 default: 856 return nil, fmt.Errorf("did not found: %s", didID) 857 } 858 } 859 860 return resolveDID, fromDID, toDID 861 } 862 863 type kmsProvider struct { 864 kmsStore kms.Store 865 secretLockService secretlock.Service 866 } 867 868 func (k *kmsProvider) StorageProvider() kms.Store { 869 return k.kmsStore 870 } 871 872 func (k *kmsProvider) SecretLock() secretlock.Service { 873 return k.secretLockService 874 } 875 876 func newMockKMSProvider(storagePvdr *mockstorage.MockStoreProvider, t *testing.T) kms.Provider { 877 ariesProviderWrapper, err := kms.NewAriesProviderWrapper(storagePvdr) 878 require.NoError(t, err) 879 880 return &kmsProvider{kmsStore: ariesProviderWrapper, secretLockService: &noop.NoLock{}} 881 } 882 883 // mockProvider mocks provider for KMS. 884 type mockProvider struct { 885 storage *mockstorage.MockStoreProvider 886 kms kms.KeyManager 887 secretLock secretlock.Service 888 crypto cryptoapi.Crypto 889 packers []packer.Packer 890 primaryPacker packer.Packer 891 vdr vdrapi.Registry 892 } 893 894 func (m *mockProvider) Packers() []packer.Packer { 895 return m.packers 896 } 897 898 func (m *mockProvider) KMS() kms.KeyManager { 899 return m.kms 900 } 901 902 func (m *mockProvider) SecretLock() secretlock.Service { 903 return m.secretLock 904 } 905 906 func (m *mockProvider) StorageProvider() storage.Provider { 907 return m.storage 908 } 909 910 func (m *mockProvider) PrimaryPacker() packer.Packer { 911 return m.primaryPacker 912 } 913 914 // VDRegistry returns a vdr registry. 915 func (m *mockProvider) VDRegistry() vdrapi.Registry { 916 return m.vdr 917 } 918 919 func (m *mockProvider) Crypto() cryptoapi.Crypto { 920 return m.crypto 921 }