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  }