github.com/hyperledger/aries-framework-go@v0.3.2/pkg/wallet/wallet_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package wallet
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/ed25519"
    12  	"crypto/elliptic"
    13  	"crypto/rand"
    14  	"crypto/sha256"
    15  	_ "embed"
    16  	"encoding/base64"
    17  	"encoding/json"
    18  	"errors"
    19  	"fmt"
    20  	"net/http"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/btcsuite/btcutil/base58"
    26  	"github.com/google/uuid"
    27  	"github.com/stretchr/testify/require"
    28  
    29  	"github.com/hyperledger/aries-framework-go/component/storage/edv"
    30  	"github.com/hyperledger/aries-framework-go/internal/testdata"
    31  	"github.com/hyperledger/aries-framework-go/pkg/crypto/primitive/bbs12381g2pub"
    32  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto"
    33  	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
    34  	"github.com/hyperledger/aries-framework-go/pkg/doc/jwt"
    35  	"github.com/hyperledger/aries-framework-go/pkg/doc/presexch"
    36  	"github.com/hyperledger/aries-framework-go/pkg/doc/util"
    37  	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
    38  	vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
    39  	"github.com/hyperledger/aries-framework-go/pkg/internal/ldtestutil"
    40  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    41  	"github.com/hyperledger/aries-framework-go/pkg/kms/webkms"
    42  	cryptomock "github.com/hyperledger/aries-framework-go/pkg/mock/crypto"
    43  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    44  	mockprovider "github.com/hyperledger/aries-framework-go/pkg/mock/provider"
    45  	"github.com/hyperledger/aries-framework-go/pkg/mock/secretlock"
    46  	mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    47  	mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr"
    48  	"github.com/hyperledger/aries-framework-go/pkg/secretlock/local/masterlock/pbkdf2"
    49  	"github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint"
    50  	"github.com/hyperledger/aries-framework-go/pkg/vdr/key"
    51  	"github.com/hyperledger/aries-framework-go/spi/storage"
    52  )
    53  
    54  // nolint: lll
    55  const (
    56  	sampleUserID            = "sample-user01"
    57  	sampleFakeTkn           = "fake-auth-tkn"
    58  	toBeImplementedErr      = "to be implemented"
    59  	sampleWalletErr         = "sample wallet err"
    60  	sampleCreatedDate       = "2020-12-25"
    61  	sampleChallenge         = "sample-challenge"
    62  	sampleDomain            = "sample-domain"
    63  	sampleInvalidDIDID      = "did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHdI"
    64  	sampleInvalidDIDContent = `{
    65      	"@context": ["https://w3id.org/did/v1"],
    66      	"id": "did:example:sampleInvalidDIDContent"
    67  		}`
    68  	sampleVerificationMethod = "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5#z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5"
    69  	didKey                   = "did:key:z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5"
    70  	pkBase58                 = "2MP5gWCnf67jvW3E4Lz8PpVrDWAXMYY1sDxjnkEnKhkkbKD7yP2mkVeyVpu5nAtr3TeDgMNjBPirk2XcQacs3dvZ"
    71  	kid                      = "z6MknC1wwS6DEYwtGbZZo2QvjQjkh2qSBjb4GYmbye8dv4S5"
    72  	didKeyBBS                = "did:key:zUC72c7u4BYVmfYinDceXkNAwzPEyuEE23kUmJDjLy8495KH3pjLwFhae1Fww9qxxRdLnS2VNNwni6W3KbYZKsicDtiNNEp76fYWR6HCD8jAz6ihwmLRjcHH6kB294Xfg1SL1qQ"
    73  	pkBBSBase58              = "6gsgGpdx7p1nYoKJ4b5fKt1xEomWdnemg9nJFX6mqNCh"
    74  	keyIDBBS                 = "zUC72c7u4BYVmfYinDceXkNAwzPEyuEE23kUmJDjLy8495KH3pjLwFhae1Fww9qxxRdLnS2VNNwni6W3KbYZKsicDtiNNEp76fYWR6HCD8jAz6ihwmLRjcHH6kB294Xfg1SL1qQ"
    75  	sampleEDVServerURL       = "sample-edv-url"
    76  	sampleEDVVaultID         = "sample-edv-vault-id"
    77  	sampleEDVEncryptionKID   = "sample-edv-encryption-kid"
    78  	sampleEDVMacKID          = "sample-edv-mac-kid"
    79  )
    80  
    81  func TestCreate(t *testing.T) {
    82  	t.Run("test create new wallet using local kms passphrase", func(t *testing.T) {
    83  		mockctx := newMockProvider(t)
    84  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
    85  		require.NoError(t, err)
    86  		require.NoError(t, ProfileExists(sampleUserID, mockctx))
    87  
    88  		wallet, err := New(sampleUserID, mockctx)
    89  		require.NoError(t, err)
    90  		require.NotEmpty(t, wallet)
    91  	})
    92  
    93  	t.Run("test create new wallet using local kms secret lock service", func(t *testing.T) {
    94  		mockctx := newMockProvider(t)
    95  		err := CreateProfile(sampleUserID, mockctx, WithSecretLockService(&secretlock.MockSecretLock{}))
    96  		require.NoError(t, err)
    97  
    98  		wallet, err := New(sampleUserID, mockctx)
    99  		require.NoError(t, err)
   100  		require.NotEmpty(t, wallet)
   101  	})
   102  
   103  	t.Run("test create new wallet using remote kms key server URL", func(t *testing.T) {
   104  		mockctx := newMockProvider(t)
   105  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   106  		require.NoError(t, err)
   107  
   108  		wallet, err := New(sampleUserID, mockctx)
   109  		require.NoError(t, err)
   110  		require.NotEmpty(t, wallet)
   111  	})
   112  
   113  	t.Run("test create new wallet using remote kms key server URL & EDV", func(t *testing.T) {
   114  		mockctx := newMockProvider(t)
   115  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL),
   116  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, sampleEDVEncryptionKID, sampleEDVMacKID))
   117  		require.NoError(t, err)
   118  
   119  		wallet, err := New(sampleUserID, mockctx)
   120  		require.NoError(t, err)
   121  		require.NotEmpty(t, wallet)
   122  		require.NotEmpty(t, wallet.profile.EDVConf)
   123  		require.Equal(t, wallet.profile.EDVConf.ServerURL, sampleEDVServerURL)
   124  		require.Equal(t, wallet.profile.EDVConf.VaultID, sampleEDVVaultID)
   125  		require.Equal(t, wallet.profile.EDVConf.EncryptionKeyID, sampleEDVEncryptionKID)
   126  		require.Equal(t, wallet.profile.EDVConf.MACKeyID, sampleEDVMacKID)
   127  	})
   128  
   129  	t.Run("test create new wallet failure", func(t *testing.T) {
   130  		mockctx := newMockProvider(t)
   131  		err := CreateProfile(sampleUserID, mockctx)
   132  		require.Error(t, err)
   133  		require.Contains(t, err.Error(), "invalid create profile options")
   134  
   135  		require.True(t, errors.Is(ProfileExists(sampleUserID, mockctx), ErrProfileNotFound))
   136  
   137  		wallet, err := New(sampleUserID, mockctx)
   138  		require.Error(t, err)
   139  		require.Empty(t, wallet)
   140  	})
   141  
   142  	t.Run("test create new wallet failure - create store error", func(t *testing.T) {
   143  		mockctx := newMockProvider(t)
   144  		mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{
   145  			ErrOpenStoreHandle: fmt.Errorf(sampleWalletErr),
   146  		}
   147  
   148  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   149  		require.Error(t, err)
   150  		require.Contains(t, err.Error(), sampleWalletErr)
   151  
   152  		err = ProfileExists(sampleUserID, mockctx)
   153  		require.Error(t, err)
   154  		require.Contains(t, err.Error(), sampleWalletErr)
   155  
   156  		wallet, err := New(sampleUserID, mockctx)
   157  		require.Error(t, err)
   158  		require.Empty(t, wallet)
   159  	})
   160  
   161  	t.Run("test create new wallet failure - save profile error", func(t *testing.T) {
   162  		mockctx := newMockProvider(t)
   163  		mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{
   164  			Store: &mockstorage.MockStore{
   165  				ErrPut: fmt.Errorf(sampleWalletErr),
   166  			},
   167  		}
   168  
   169  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   170  		require.Error(t, err)
   171  		require.Contains(t, err.Error(), sampleWalletErr)
   172  
   173  		wallet, err := New(sampleUserID, mockctx)
   174  		require.Error(t, err)
   175  		require.Empty(t, wallet)
   176  	})
   177  }
   178  
   179  func TestUpdate(t *testing.T) {
   180  	t.Run("test update wallet using local kms passphrase", func(t *testing.T) {
   181  		mockctx := newMockProvider(t)
   182  		createSampleProfile(t, mockctx)
   183  
   184  		err := UpdateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   185  		require.NoError(t, err)
   186  
   187  		wallet, err := New(sampleUserID, mockctx)
   188  		require.NoError(t, err)
   189  		require.NotEmpty(t, wallet)
   190  		require.NotEmpty(t, wallet.profile.MasterLockCipher)
   191  	})
   192  
   193  	t.Run("test update wallet using local kms secret lock service", func(t *testing.T) {
   194  		mockctx := newMockProvider(t)
   195  		createSampleProfile(t, mockctx)
   196  
   197  		err := UpdateProfile(sampleUserID, mockctx, WithSecretLockService(&secretlock.MockSecretLock{}))
   198  		require.NoError(t, err)
   199  
   200  		wallet, err := New(sampleUserID, mockctx)
   201  		require.NoError(t, err)
   202  		require.NotEmpty(t, wallet)
   203  	})
   204  
   205  	t.Run("test update wallet using remote kms key server URL", func(t *testing.T) {
   206  		mockctx := newMockProvider(t)
   207  		createSampleProfile(t, mockctx)
   208  
   209  		err := UpdateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   210  		require.NoError(t, err)
   211  
   212  		wallet, err := New(sampleUserID, mockctx)
   213  		require.NoError(t, err)
   214  		require.NotEmpty(t, wallet)
   215  		require.Empty(t, wallet.profile.MasterLockCipher)
   216  		require.NotEmpty(t, wallet.profile.KeyServerURL)
   217  	})
   218  
   219  	t.Run("test update wallet profile edv settings", func(t *testing.T) {
   220  		mockctx := newMockProvider(t)
   221  		createSampleProfile(t, mockctx)
   222  
   223  		err := UpdateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL),
   224  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, sampleEDVEncryptionKID, sampleEDVMacKID))
   225  		require.NoError(t, err)
   226  
   227  		wallet, err := New(sampleUserID, mockctx)
   228  		require.NoError(t, err)
   229  		require.NotEmpty(t, wallet)
   230  		require.NotEmpty(t, wallet.profile.EDVConf)
   231  		require.Equal(t, wallet.profile.EDVConf.ServerURL, sampleEDVServerURL)
   232  		require.Equal(t, wallet.profile.EDVConf.VaultID, sampleEDVVaultID)
   233  		require.Equal(t, wallet.profile.EDVConf.EncryptionKeyID, sampleEDVEncryptionKID)
   234  		require.Equal(t, wallet.profile.EDVConf.MACKeyID, sampleEDVMacKID)
   235  	})
   236  
   237  	t.Run("test update wallet failure", func(t *testing.T) {
   238  		mockctx := newMockProvider(t)
   239  		createSampleProfile(t, mockctx)
   240  
   241  		err := UpdateProfile(sampleUserID, mockctx)
   242  		require.Error(t, err)
   243  		require.Contains(t, err.Error(), "invalid create profile options")
   244  
   245  		wallet, err := New(sampleUserID, mockctx)
   246  		require.NoError(t, err)
   247  		require.NotEmpty(t, wallet)
   248  		require.NotEmpty(t, wallet.profile.MasterLockCipher)
   249  	})
   250  
   251  	t.Run("test update wallet failure - profile doesn't exists", func(t *testing.T) {
   252  		mockctx := newMockProvider(t)
   253  		err := UpdateProfile(sampleUserID, mockctx)
   254  		require.Error(t, err)
   255  		require.Contains(t, err.Error(), "profile does not exist")
   256  
   257  		wallet, err := New(sampleUserID, mockctx)
   258  		require.Error(t, err)
   259  		require.Empty(t, wallet)
   260  	})
   261  
   262  	t.Run("test update wallet failure - create store error", func(t *testing.T) {
   263  		mockctx := newMockProvider(t)
   264  		mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{
   265  			ErrOpenStoreHandle: fmt.Errorf(sampleWalletErr),
   266  		}
   267  
   268  		err := UpdateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   269  		require.Error(t, err)
   270  		require.Contains(t, err.Error(), sampleWalletErr)
   271  
   272  		wallet, err := New(sampleUserID, mockctx)
   273  		require.Error(t, err)
   274  		require.Empty(t, wallet)
   275  	})
   276  
   277  	t.Run("test update wallet failure - save profile error", func(t *testing.T) {
   278  		mockctx := newMockProvider(t)
   279  		createSampleProfile(t, mockctx)
   280  
   281  		mockctx.StorageProviderValue.(*mockstorage.MockStoreProvider).Store.ErrPut = fmt.Errorf(sampleWalletErr)
   282  
   283  		err := UpdateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   284  		require.Error(t, err)
   285  		require.Contains(t, err.Error(), sampleWalletErr)
   286  
   287  		wallet, err := New(sampleUserID, mockctx)
   288  		require.NoError(t, err)
   289  		require.NotEmpty(t, wallet)
   290  		require.Empty(t, wallet.profile.KeyServerURL)
   291  		require.NotEmpty(t, wallet.profile.MasterLockCipher)
   292  	})
   293  
   294  	t.Run("test update wallet failure - save edv settings error", func(t *testing.T) {
   295  		mockctx := newMockProvider(t)
   296  		createSampleProfile(t, mockctx)
   297  
   298  		err := UpdateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL),
   299  			WithEDVStorage(sampleEDVServerURL, "", sampleEDVEncryptionKID, sampleEDVMacKID))
   300  		require.Error(t, err)
   301  		require.Contains(t, err.Error(), "failed to update EDV configuration")
   302  	})
   303  }
   304  
   305  func TestCreateDataVaultKeyPairs(t *testing.T) {
   306  	t.Run("successfully create EDV key pair", func(t *testing.T) {
   307  		mockctx := newMockProvider(t)
   308  
   309  		// create a wallet profile
   310  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase),
   311  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, "", ""))
   312  		require.NoError(t, err)
   313  
   314  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   315  		require.NoError(t, err)
   316  
   317  		wallet, err := New(sampleUserID, mockctx)
   318  		require.NoError(t, err)
   319  		require.NotEmpty(t, wallet)
   320  		require.NotEmpty(t, wallet.profile.EDVConf.EncryptionKeyID)
   321  		require.NotEmpty(t, wallet.profile.EDVConf.MACKeyID)
   322  
   323  		// call again to replace existing settings
   324  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   325  		require.NoError(t, err)
   326  
   327  		wallet2, err := New(sampleUserID, mockctx)
   328  		require.NoError(t, err)
   329  		require.NotEmpty(t, wallet2)
   330  		require.NotEmpty(t, wallet2.profile.EDVConf.EncryptionKeyID)
   331  		require.NotEmpty(t, wallet2.profile.EDVConf.MACKeyID)
   332  
   333  		require.NotEqual(t, wallet.profile.EDVConf.EncryptionKeyID, wallet2.profile.EDVConf.EncryptionKeyID)
   334  		require.NotEqual(t, wallet.profile.EDVConf.MACKeyID, wallet2.profile.EDVConf.MACKeyID)
   335  	})
   336  
   337  	t.Run("successfully create key pair failures", func(t *testing.T) {
   338  		mockctx := newMockProvider(t)
   339  
   340  		// test create a wallet profile without EDV settings
   341  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   342  		require.NoError(t, err)
   343  
   344  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   345  		require.Error(t, err)
   346  		require.Contains(t, err.Error(), "invalid operation")
   347  
   348  		// test store errors
   349  		mockctx = newMockProvider(t)
   350  		mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{
   351  			ErrOpenStoreHandle: errors.New(sampleWalletErr),
   352  		}
   353  
   354  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   355  		require.Error(t, err)
   356  		require.Contains(t, err.Error(), "failed to get store")
   357  
   358  		// invalid user profile
   359  		mockctx = newMockProvider(t)
   360  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   361  		require.Error(t, err)
   362  		require.Contains(t, err.Error(), "failed to get wallet user profile")
   363  
   364  		// invalid auth
   365  		mockctx = newMockProvider(t)
   366  
   367  		err = CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase),
   368  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, "", ""))
   369  		require.NoError(t, err)
   370  
   371  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase("invalid"))
   372  		require.Error(t, err)
   373  		require.Contains(t, err.Error(), "message authentication failed")
   374  
   375  		// test create key pair error
   376  		mockctx = newMockProvider(t)
   377  
   378  		err = CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase),
   379  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, "", ""))
   380  		require.NoError(t, err)
   381  
   382  		mockStPvdr, ok := mockctx.StorageProviderValue.(*mockstorage.MockStoreProvider)
   383  		require.True(t, ok)
   384  		mockStPvdr.Store.ErrPut = errors.New(sampleWalletErr)
   385  
   386  		err = CreateDataVaultKeyPairs(sampleUserID, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   387  		require.Error(t, err)
   388  		require.Contains(t, err.Error(), "failed to create key pairs")
   389  	})
   390  
   391  	t.Run("fail to create new KMS Aries provider wrapper", func(t *testing.T) {
   392  		testProfile := profile{EDVConf: &edvConf{}}
   393  
   394  		testProfileBytes, err := json.Marshal(testProfile)
   395  		require.NoError(t, err)
   396  
   397  		mockContext := &mockprovider.Provider{
   398  			StorageProviderValue: &mockstorage.MockStoreProvider{
   399  				FailNamespace: kms.AriesWrapperStoreName,
   400  				Store: &mockstorage.MockStore{
   401  					Store: map[string]mockstorage.DBEntry{
   402  						"vcwallet_usr_sample-user01": {Value: testProfileBytes},
   403  					},
   404  				},
   405  			},
   406  		}
   407  
   408  		err = CreateDataVaultKeyPairs(sampleUserID, mockContext)
   409  		require.EqualError(t, err, "failed to open store for name space kmsdb")
   410  	})
   411  
   412  	t.Run("test update profile errors", func(t *testing.T) {
   413  		kmgr := &mockkms.KeyManager{CreateKeyFn: func(kt kms.KeyType) (s string, i interface{}, e error) {
   414  			if kt == kms.HMACSHA256Tag256Type {
   415  				return "", nil, errors.New(sampleWalletErr)
   416  			}
   417  			return "", nil, nil
   418  		}}
   419  
   420  		err := updateProfile(kmgr, &profile{EDVConf: &edvConf{}})
   421  		require.Error(t, err)
   422  		require.Contains(t, err.Error(), "failed to create EDV MAC key pair")
   423  
   424  		kmgr = &mockkms.KeyManager{CreateKeyFn: func(kt kms.KeyType) (s string, i interface{}, e error) {
   425  			if kt == kms.NISTP256ECDHKWType {
   426  				return "", nil, errors.New(sampleWalletErr)
   427  			}
   428  			return "", nil, nil
   429  		}}
   430  
   431  		err = updateProfile(kmgr, &profile{EDVConf: &edvConf{}})
   432  		require.Error(t, err)
   433  		require.Contains(t, err.Error(), "failed to create EDV encryption key pair")
   434  	})
   435  }
   436  
   437  func TestNew(t *testing.T) {
   438  	t.Run("test get wallet by user", func(t *testing.T) {
   439  		mockctx := newMockProvider(t)
   440  		// create a wallet
   441  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   442  		require.NoError(t, err)
   443  
   444  		wallet, err := New(sampleUserID, mockctx)
   445  		require.NoError(t, err)
   446  		require.NotEmpty(t, wallet)
   447  	})
   448  
   449  	t.Run("test get wallet by invalid userID", func(t *testing.T) {
   450  		mockctx := newMockProvider(t)
   451  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   452  		require.NoError(t, err)
   453  
   454  		wallet, err := New(sampleUserID+"invalid", mockctx)
   455  		require.Empty(t, wallet)
   456  		require.Error(t, err)
   457  		require.Contains(t, err.Error(), "profile does not exist")
   458  	})
   459  
   460  	t.Run("test get wallet failure - save profile error", func(t *testing.T) {
   461  		mockctx := newMockProvider(t)
   462  		mockctx.StorageProviderValue = &mockstorage.MockStoreProvider{
   463  			ErrOpenStoreHandle: fmt.Errorf(sampleWalletErr),
   464  		}
   465  
   466  		wallet, err := New(sampleUserID, mockctx)
   467  		require.Error(t, err)
   468  		require.Empty(t, wallet)
   469  		require.Contains(t, err.Error(), sampleWalletErr)
   470  	})
   471  }
   472  
   473  func TestWallet_OpenClose(t *testing.T) {
   474  	t.Run("test open & close wallet using local kms passphrase", func(t *testing.T) {
   475  		mockctx := newMockProvider(t)
   476  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   477  		require.NoError(t, err)
   478  
   479  		wallet, err := New(sampleUserID, mockctx)
   480  		require.NoError(t, err)
   481  		require.NotEmpty(t, wallet)
   482  
   483  		// get token
   484  		token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase), WithUnlockExpiry(500*time.Millisecond))
   485  		require.NoError(t, err)
   486  		require.NotEmpty(t, token)
   487  
   488  		// try again
   489  		token, err = wallet.Open(WithUnlockByPassphrase(samplePassPhrase))
   490  		require.Empty(t, token)
   491  		require.Error(t, err)
   492  		require.Equal(t, err, ErrAlreadyUnlocked)
   493  
   494  		// close wallet
   495  		require.True(t, wallet.Close())
   496  		require.False(t, wallet.Close())
   497  
   498  		// try to open with wrong passphrase
   499  		token, err = wallet.Open(WithUnlockByPassphrase(samplePassPhrase + "wrong"))
   500  		require.Empty(t, token)
   501  		require.Error(t, err)
   502  		require.Contains(t, err.Error(), "message authentication failed")
   503  	})
   504  
   505  	t.Run("test open & close wallet using secret lock service", func(t *testing.T) {
   506  		mockctx := newMockProvider(t)
   507  		masterLock, err := pbkdf2.NewMasterLock(samplePassPhrase, sha256.New, 0, nil)
   508  		require.NoError(t, err)
   509  
   510  		err = CreateProfile(sampleUserID, mockctx, WithSecretLockService(masterLock))
   511  		require.NoError(t, err)
   512  
   513  		wallet, err := New(sampleUserID, mockctx)
   514  		require.NoError(t, err)
   515  		require.NotEmpty(t, wallet)
   516  
   517  		// get token
   518  		token, err := wallet.Open(WithUnlockBySecretLockService(masterLock))
   519  		require.NoError(t, err)
   520  		require.NotEmpty(t, token)
   521  
   522  		// try again
   523  		token, err = wallet.Open(WithUnlockBySecretLockService(masterLock))
   524  		require.Empty(t, token)
   525  		require.Error(t, err)
   526  		require.Equal(t, err, ErrAlreadyUnlocked)
   527  
   528  		// close wallet
   529  		require.True(t, wallet.Close())
   530  		require.False(t, wallet.Close())
   531  
   532  		// try to open with wrong secret lock service
   533  		badLock, err := pbkdf2.NewMasterLock(samplePassPhrase+"wrong", sha256.New, 0, nil)
   534  		require.NoError(t, err)
   535  
   536  		token, err = wallet.Open(WithUnlockBySecretLockService(badLock))
   537  		require.Empty(t, token)
   538  		require.Error(t, err)
   539  		require.Contains(t, err.Error(), "message authentication failed")
   540  	})
   541  
   542  	t.Run("test open & close wallet using remote kms URL & auth token option", func(t *testing.T) {
   543  		mockctx := newMockProvider(t)
   544  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   545  		require.NoError(t, err)
   546  
   547  		wallet, err := New(sampleUserID, mockctx)
   548  		require.NoError(t, err)
   549  		require.NotEmpty(t, wallet)
   550  
   551  		// get token
   552  		token, err := wallet.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   553  		require.NoError(t, err)
   554  		require.NotEmpty(t, token)
   555  
   556  		// try again
   557  		token, err = wallet.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   558  		require.Empty(t, token)
   559  		require.Error(t, err)
   560  		require.Equal(t, err, ErrAlreadyUnlocked)
   561  
   562  		// close wallet
   563  		require.True(t, wallet.Close())
   564  		require.False(t, wallet.Close())
   565  	})
   566  
   567  	t.Run("test open & close wallet using remote kms URL & auth header option", func(t *testing.T) {
   568  		mockctx := newMockProvider(t)
   569  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   570  		require.NoError(t, err)
   571  
   572  		wallet, err := New(sampleUserID, mockctx)
   573  		require.NoError(t, err)
   574  		require.NotEmpty(t, wallet)
   575  
   576  		// get token
   577  		token, err := wallet.Open(WithUnlockWebKMSOptions(
   578  			webkms.WithHeaders(func(req *http.Request) (*http.Header, error) {
   579  				req.Header.Set("authorization", fmt.Sprintf("Bearer %s", sampleRemoteKMSAuth))
   580  
   581  				return &req.Header, nil
   582  			}),
   583  		))
   584  		require.NoError(t, err)
   585  		require.NotEmpty(t, token)
   586  
   587  		// try again
   588  		token, err = wallet.Open(WithUnlockWebKMSOptions(
   589  			webkms.WithHeaders(func(req *http.Request) (*http.Header, error) {
   590  				req.Header.Set("authorization", fmt.Sprintf("Bearer %s", sampleRemoteKMSAuth))
   591  
   592  				return &req.Header, nil
   593  			}),
   594  		))
   595  		require.Empty(t, token)
   596  		require.Error(t, err)
   597  		require.Equal(t, err, ErrAlreadyUnlocked)
   598  
   599  		// close wallet
   600  		require.True(t, wallet.Close())
   601  		require.False(t, wallet.Close())
   602  	})
   603  
   604  	t.Run("test open & close wallet using EDV options", func(t *testing.T) {
   605  		mockctx := newMockProvider(t)
   606  		user := uuid.New().String()
   607  
   608  		// create profile
   609  		err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase),
   610  			WithEDVStorage(sampleEDVServerURL, sampleEDVVaultID, sampleEDVEncryptionKID, sampleEDVMacKID))
   611  		require.NoError(t, err)
   612  
   613  		// create key pairs
   614  		err = CreateDataVaultKeyPairs(user, mockctx, WithUnlockByPassphrase(samplePassPhrase))
   615  		require.NoError(t, err)
   616  
   617  		wallet, err := New(user, mockctx)
   618  		require.NoError(t, err)
   619  		require.NotEmpty(t, wallet)
   620  
   621  		token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase), WithUnlockEDVOptions(
   622  			edv.WithFullDocumentsReturnedFromQueries(), edv.WithBatchEndpointExtension(),
   623  		))
   624  		require.NoError(t, err)
   625  		require.NotEmpty(t, token)
   626  
   627  		// try again
   628  		token, err = wallet.Open(WithUnlockByPassphrase(samplePassPhrase))
   629  		require.Empty(t, token)
   630  		require.Error(t, err)
   631  		require.Equal(t, err, ErrAlreadyUnlocked)
   632  
   633  		// close wallet
   634  		require.True(t, wallet.Close())
   635  		require.False(t, wallet.Close())
   636  	})
   637  
   638  	t.Run("test opened wallet between multliple instances", func(t *testing.T) {
   639  		mockctx := newMockProvider(t)
   640  		err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
   641  		require.NoError(t, err)
   642  
   643  		wallet1, err := New(sampleUserID, mockctx)
   644  		require.NoError(t, err)
   645  		require.NotEmpty(t, wallet1)
   646  
   647  		// get token
   648  		token, err := wallet1.Open(WithUnlockByPassphrase(samplePassPhrase), WithUnlockExpiry(500*time.Millisecond))
   649  		require.NoError(t, err)
   650  		require.NotEmpty(t, token)
   651  
   652  		// create new instance for same profile
   653  		wallet2, err := New(sampleUserID, mockctx)
   654  		require.NoError(t, err)
   655  		require.NotEmpty(t, wallet2)
   656  
   657  		// no need to unlock again since token is shared
   658  		require.NoError(t, wallet2.Add(token, Metadata, []byte(sampleContentValid)))
   659  
   660  		// close first instance
   661  		wallet1.Close()
   662  		require.Error(t, wallet2.Add(token, Metadata, []byte(sampleContentNoID)))
   663  	})
   664  
   665  	t.Run("test open wallet failure when store open fails", func(t *testing.T) {
   666  		mockctx := newMockProvider(t)
   667  		err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   668  		require.NoError(t, err)
   669  
   670  		wallet, err := New(sampleUserID, mockctx)
   671  		require.NoError(t, err)
   672  		require.NotEmpty(t, wallet)
   673  
   674  		// corrupt content store
   675  		wallet.contents = newContentStore(&mockstorage.MockStoreProvider{
   676  			ErrOpenStoreHandle: fmt.Errorf(sampleWalletErr),
   677  		}, createTestDocumentLoader(t), wallet.profile)
   678  
   679  		// get token
   680  		token, err := wallet.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   681  		require.Error(t, err)
   682  		require.Contains(t, err.Error(), "failed to open store : sample wallet err")
   683  		require.Empty(t, token)
   684  
   685  		// close wallet
   686  		require.False(t, wallet.Close())
   687  	})
   688  }
   689  
   690  func TestWallet_Export(t *testing.T) {
   691  	mockctx := newMockProvider(t)
   692  	err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   693  	require.NoError(t, err)
   694  
   695  	walletInstance, err := New(sampleUserID, mockctx)
   696  	require.NotEmpty(t, walletInstance)
   697  	require.NoError(t, err)
   698  
   699  	result, err := walletInstance.Export("")
   700  	require.Empty(t, result)
   701  	require.Error(t, err)
   702  	require.EqualError(t, err, toBeImplementedErr)
   703  }
   704  
   705  func TestWallet_Import(t *testing.T) {
   706  	mockctx := newMockProvider(t)
   707  	err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   708  	require.NoError(t, err)
   709  
   710  	walletInstance, err := New(sampleUserID, mockctx)
   711  	require.NotEmpty(t, walletInstance)
   712  	require.NoError(t, err)
   713  
   714  	err = walletInstance.Import("", nil)
   715  	require.Error(t, err)
   716  	require.EqualError(t, err, toBeImplementedErr)
   717  }
   718  
   719  func TestWallet_Add(t *testing.T) {
   720  	mockctx := newMockProvider(t)
   721  	err := CreateProfile(sampleUserID, mockctx, WithKeyServerURL(sampleKeyServerURL))
   722  	require.NoError(t, err)
   723  
   724  	walletInstance, err := New(sampleUserID, mockctx)
   725  	require.NotEmpty(t, walletInstance)
   726  	require.NoError(t, err)
   727  
   728  	// wallet locked
   729  	require.True(t, errors.Is(walletInstance.Add(sampleFakeTkn, Metadata, []byte(sampleContentValid)), ErrWalletLocked))
   730  
   731  	// unlock wallet
   732  	tkn, err := walletInstance.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   733  	require.NoError(t, err)
   734  
   735  	// add data model to wallet
   736  	err = walletInstance.Add(tkn, Metadata, []byte(sampleContentValid))
   737  	require.NoError(t, err)
   738  }
   739  
   740  func TestWallet_Get(t *testing.T) {
   741  	mockctx := newMockProvider(t)
   742  	user := uuid.New().String()
   743  
   744  	err := CreateProfile(user, mockctx, WithKeyServerURL(sampleKeyServerURL))
   745  	require.NoError(t, err)
   746  
   747  	walletInstance, err := New(user, mockctx)
   748  	require.NotEmpty(t, walletInstance)
   749  	require.NoError(t, err)
   750  
   751  	tkn, err := walletInstance.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   752  	require.NoError(t, err)
   753  
   754  	err = walletInstance.Add(tkn, Metadata, []byte(sampleContentValid))
   755  	require.NoError(t, err)
   756  
   757  	content, err := walletInstance.Get(tkn, Metadata, "did:example:123456789abcdefghi")
   758  	require.NoError(t, err)
   759  	require.NotEmpty(t, content)
   760  	require.Equal(t, sampleContentValid, string(content))
   761  }
   762  
   763  func TestWallet_GetAll(t *testing.T) {
   764  	const vcContent = `{
   765        "@context": [
   766          "https://www.w3.org/2018/credentials/v1",
   767          "https://www.w3.org/2018/credentials/examples/v1"
   768        ],
   769        "id": "%s",
   770        "issuer": {
   771          "id": "did:example:76e12ec712ebc6f1c221ebfeb1f"
   772        },
   773        "type": [
   774          "VerifiableCredential",
   775          "UniversityDegreeCredential"
   776        ]
   777      }`
   778  
   779  	const orgCollection = `{
   780                      "@context": ["https://w3id.org/wallet/v1"],
   781                      "id": "did:example:acme123456789abcdefghi",
   782                      "type": "Organization",
   783                      "name": "Acme Corp.",
   784                      "image": "https://via.placeholder.com/150",
   785                      "description" : "A software company.",
   786                      "tags": ["professional", "organization"],
   787                      "correlation": ["4058a72a-9523-11ea-bb37-0242ac130002"]
   788                  }`
   789  
   790  	const collectionID = "did:example:acme123456789abcdefghi"
   791  
   792  	user := uuid.New().String()
   793  
   794  	mockctx := newMockProvider(t)
   795  	err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
   796  	require.NoError(t, err)
   797  
   798  	walletInstance, err := New(user, mockctx)
   799  	require.NotEmpty(t, walletInstance)
   800  	require.NoError(t, err)
   801  
   802  	tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
   803  	require.NoError(t, err)
   804  
   805  	const count = 5
   806  
   807  	var taggedKeys, untaggedKeys [count]string
   808  
   809  	// save test data without collection
   810  	for i := 0; i < count; i++ {
   811  		k := uuid.New().String()
   812  
   813  		require.NoError(t, walletInstance.Add(tkn, Credential, []byte(fmt.Sprintf(vcContent, k))))
   814  
   815  		untaggedKeys[i] = k
   816  	}
   817  
   818  	// save a collection
   819  	require.NoError(t, walletInstance.Add(tkn, Collection, []byte(orgCollection)))
   820  
   821  	// save contents by collection
   822  	for i := 0; i < count; i++ {
   823  		k := uuid.New().String()
   824  
   825  		require.NoError(t, walletInstance.Add(tkn, Credential, []byte(fmt.Sprintf(vcContent, k)),
   826  			AddByCollection(collectionID)))
   827  
   828  		taggedKeys[i] = k
   829  	}
   830  
   831  	// get all by content
   832  	vcs, err := walletInstance.GetAll(tkn, Credential)
   833  	require.NoError(t, err)
   834  	require.Len(t, vcs, count*2)
   835  
   836  	// get all by content & collection
   837  	vcs, err = walletInstance.GetAll(tkn, Credential, FilterByCollection(collectionID))
   838  	require.NoError(t, err)
   839  	require.Len(t, vcs, count)
   840  
   841  	// delete one item under collection
   842  	require.NoError(t, walletInstance.Remove(tkn, Credential, taggedKeys[0]))
   843  	// get all by content & collection
   844  	vcs, err = walletInstance.GetAll(tkn, Credential, FilterByCollection(collectionID))
   845  	require.NoError(t, err)
   846  	require.Len(t, vcs, count-1)
   847  
   848  	// delete one item which is not under collection
   849  	require.NoError(t, walletInstance.Remove(tkn, Credential, untaggedKeys[0]))
   850  	// get all by content
   851  	vcs, err = walletInstance.GetAll(tkn, Credential)
   852  	require.NoError(t, err)
   853  	require.Len(t, vcs, count*2-2)
   854  }
   855  
   856  func TestWallet_Remove(t *testing.T) {
   857  	mockctx := newMockProvider(t)
   858  	user := uuid.New().String()
   859  
   860  	err := CreateProfile(user, mockctx, WithKeyServerURL(sampleKeyServerURL))
   861  	require.NoError(t, err)
   862  
   863  	walletInstance, err := New(user, mockctx)
   864  	require.NotEmpty(t, walletInstance)
   865  	require.NoError(t, err)
   866  
   867  	tkn, err := walletInstance.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   868  	require.NoError(t, err)
   869  
   870  	err = walletInstance.Add(tkn, Metadata, []byte(sampleContentValid))
   871  	require.NoError(t, err)
   872  
   873  	content, err := walletInstance.Get(tkn, Metadata, "did:example:123456789abcdefghi")
   874  	require.NoError(t, err)
   875  	require.NotEmpty(t, content)
   876  
   877  	err = walletInstance.Remove(tkn, Metadata, "did:example:123456789abcdefghi")
   878  	require.NoError(t, err)
   879  
   880  	content, err = walletInstance.Get(tkn, Metadata, "did:example:123456789abcdefghi")
   881  	require.Empty(t, content)
   882  	require.Error(t, err)
   883  	require.True(t, errors.Is(err, storage.ErrDataNotFound))
   884  }
   885  
   886  func TestWallet_Query(t *testing.T) {
   887  	mockctx := newMockProvider(t)
   888  	user := uuid.New().String()
   889  
   890  	mockctx.VDRegistryValue = &mockvdr.MockVDRegistry{
   891  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
   892  			if strings.HasPrefix(didID, "did:key:") {
   893  				k := key.New()
   894  
   895  				d, e := k.Read(didID)
   896  				if e != nil {
   897  					return nil, e
   898  				}
   899  
   900  				return d, nil
   901  			}
   902  
   903  			return nil, fmt.Errorf("did not found")
   904  		},
   905  	}
   906  
   907  	err := CreateProfile(user, mockctx, WithKeyServerURL(sampleKeyServerURL))
   908  	require.NoError(t, err)
   909  
   910  	vc1, err := (&verifiable.Credential{
   911  		Context: []string{verifiable.ContextURI},
   912  		Types:   []string{verifiable.VCType},
   913  		ID:      "http://example.edu/credentials/9999",
   914  		CustomFields: map[string]interface{}{
   915  			"first_name": "Jesse",
   916  		},
   917  		Issued: &util.TimeWrapper{
   918  			Time: time.Now(),
   919  		},
   920  		Issuer: verifiable.Issuer{
   921  			ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
   922  		},
   923  		Subject: uuid.New().String(),
   924  	}).MarshalJSON()
   925  	require.NoError(t, err)
   926  
   927  	sampleVC := fmt.Sprintf(sampleVCFmt, verifiable.ContextURI)
   928  	vcForQuery := []byte(strings.ReplaceAll(sampleVC,
   929  		"http://example.edu/credentials/1872", "http://example.edu/credentials/1879"))
   930  	vcForDerive := []byte(sampleBBSVC)
   931  
   932  	walletInstance, err := New(user, mockctx)
   933  	require.NotEmpty(t, walletInstance)
   934  	require.NoError(t, err)
   935  
   936  	tkn, err := walletInstance.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
   937  	require.NoError(t, err)
   938  
   939  	require.NoError(t, walletInstance.Add(tkn, Credential, vc1))
   940  	require.NoError(t, walletInstance.Add(tkn, Credential, vcForQuery))
   941  	require.NoError(t, walletInstance.Add(tkn, Credential, vcForDerive))
   942  
   943  	pd := &presexch.PresentationDefinition{
   944  		ID: uuid.New().String(),
   945  		InputDescriptors: []*presexch.InputDescriptor{{
   946  			ID: uuid.New().String(),
   947  			Schema: []*presexch.Schema{{
   948  				URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
   949  			}},
   950  			Constraints: &presexch.Constraints{
   951  				Fields: []*presexch.Field{{
   952  					Path: []string{"$.first_name"},
   953  				}},
   954  			},
   955  		}},
   956  	}
   957  
   958  	// presentation exchange
   959  	pdJSON, err := json.Marshal(pd)
   960  	require.NoError(t, err)
   961  	require.NotEmpty(t, pdJSON)
   962  
   963  	// query by example
   964  	queryByExample := []byte(fmt.Sprintf(sampleQueryByExFmt, verifiable.ContextURI))
   965  	// query by frame
   966  	queryByFrame := []byte(sampleQueryByFrame)
   967  
   968  	t.Run("test wallet queries", func(t *testing.T) {
   969  		tests := []struct {
   970  			name        string
   971  			params      []*QueryParams
   972  			resultCount int
   973  			vcCount     map[int]int
   974  			error       string
   975  		}{
   976  			{
   977  				name: "query by presentation exchange - success",
   978  				params: []*QueryParams{
   979  					{Type: "PresentationExchange", Query: []json.RawMessage{pdJSON}},
   980  				},
   981  				resultCount: 1,
   982  				vcCount:     map[int]int{0: 1},
   983  			},
   984  			{
   985  				name: "query by example - success",
   986  				params: []*QueryParams{
   987  					{Type: "QueryByExample", Query: []json.RawMessage{queryByExample}},
   988  				},
   989  				resultCount: 1,
   990  				vcCount:     map[int]int{0: 1},
   991  			},
   992  			{
   993  				name: "query by frame - success",
   994  				params: []*QueryParams{
   995  					{Type: "QueryByFrame", Query: []json.RawMessage{queryByFrame}},
   996  				},
   997  				resultCount: 1,
   998  				vcCount:     map[int]int{0: 1},
   999  			},
  1000  			{
  1001  				name: "DIDAuth - success",
  1002  				params: []*QueryParams{
  1003  					{Type: "DIDAuth"},
  1004  				},
  1005  				resultCount: 1,
  1006  				vcCount:     map[int]int{0: 0},
  1007  			},
  1008  			{
  1009  				name: "multiple queries - success",
  1010  				params: []*QueryParams{
  1011  					{Type: "PresentationExchange", Query: []json.RawMessage{pdJSON}},
  1012  					{Type: "QueryByExample", Query: []json.RawMessage{queryByExample}},
  1013  					{Type: "QueryByFrame", Query: []json.RawMessage{queryByFrame}},
  1014  				},
  1015  				resultCount: 2,
  1016  				vcCount:     map[int]int{0: 1, 1: 2},
  1017  			},
  1018  			{
  1019  				name: "invalid query type",
  1020  				params: []*QueryParams{
  1021  					{Type: "invalid"},
  1022  				},
  1023  				error: "unsupported query type",
  1024  			},
  1025  			{
  1026  				name:   "empty query type",
  1027  				params: []*QueryParams{},
  1028  				error:  "no result found",
  1029  			},
  1030  		}
  1031  
  1032  		t.Parallel()
  1033  
  1034  		for _, test := range tests {
  1035  			tc := test
  1036  			t.Run(tc.name, func(t *testing.T) {
  1037  				results, err := walletInstance.Query(tkn, tc.params...)
  1038  
  1039  				if tc.error != "" {
  1040  					require.Empty(t, results)
  1041  					require.Error(t, err)
  1042  					require.Contains(t, err.Error(), tc.error)
  1043  
  1044  					return
  1045  				}
  1046  
  1047  				require.NoError(t, err)
  1048  				require.Len(t, results, tc.resultCount)
  1049  
  1050  				for i, result := range results {
  1051  					require.Len(t, result.Credentials(), tc.vcCount[i])
  1052  				}
  1053  			})
  1054  		}
  1055  	})
  1056  
  1057  	t.Run("test get all error", func(t *testing.T) {
  1058  		user := uuid.New().String()
  1059  		mockctxInvalid := newMockProvider(t)
  1060  
  1061  		sp := getMockStorageProvider()
  1062  
  1063  		sp.MockStoreProvider.Store.ErrQuery = errors.New(sampleContenttErr)
  1064  		mockctxInvalid.StorageProviderValue = sp
  1065  
  1066  		err := CreateProfile(user, mockctxInvalid, WithKeyServerURL(sampleKeyServerURL))
  1067  		require.NoError(t, err)
  1068  
  1069  		walletInstanceInvalid, err := New(user, mockctxInvalid)
  1070  		require.NoError(t, err)
  1071  		require.NotEmpty(t, walletInstanceInvalid)
  1072  
  1073  		result, err := walletInstanceInvalid.Query(sampleFakeTkn, &QueryParams{Type: "QueryByFrame"})
  1074  		require.True(t, errors.Is(err, ErrWalletLocked))
  1075  		require.Empty(t, result)
  1076  
  1077  		tk, err := walletInstanceInvalid.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
  1078  		require.NoError(t, err)
  1079  
  1080  		result, err = walletInstanceInvalid.Query(tk, &QueryParams{Type: "QueryByFrame"})
  1081  		require.Error(t, err)
  1082  		require.Contains(t, err.Error(), "failed to query credentials")
  1083  		require.Contains(t, err.Error(), sampleContenttErr)
  1084  		require.Empty(t, result)
  1085  	})
  1086  }
  1087  
  1088  func TestWallet_Query_TwoInputDescriptorsWithTwoCredentialsWithOverlap(t *testing.T) {
  1089  	mockctx := newMockProvider(t)
  1090  	user := uuid.New().String()
  1091  
  1092  	err := CreateProfile(user, mockctx, WithKeyServerURL(sampleKeyServerURL))
  1093  	require.NoError(t, err)
  1094  
  1095  	walletInstance, err := New(user, mockctx)
  1096  	require.NotEmpty(t, walletInstance)
  1097  	require.NoError(t, err)
  1098  
  1099  	tkn, err := walletInstance.Open(WithUnlockByAuthorizationToken(sampleRemoteKMSAuth))
  1100  	require.NoError(t, err)
  1101  
  1102  	require.NoError(t, walletInstance.Add(tkn, Credential, []byte(testJSONLD)))
  1103  	require.NoError(t, walletInstance.Add(tkn, Credential, []byte(testSDJWT)))
  1104  
  1105  	var pd presexch.PresentationDefinition
  1106  
  1107  	err = json.Unmarshal([]byte(testPD), &pd)
  1108  	require.NoError(t, err)
  1109  
  1110  	vps, err := walletInstance.Query(tkn, &QueryParams{
  1111  		Type:  "PresentationExchange",
  1112  		Query: []json.RawMessage{[]byte(testPD)},
  1113  	})
  1114  
  1115  	require.NoError(t, err)
  1116  
  1117  	for _, vp := range vps {
  1118  		vpBytes, err := json.Marshal(vp)
  1119  		require.NoError(t, err)
  1120  
  1121  		require.False(t, strings.Contains(string(vpBytes), "[2]"))
  1122  	}
  1123  }
  1124  
  1125  func TestWallet_Issue(t *testing.T) {
  1126  	user := uuid.New().String()
  1127  	customVDR := &mockvdr.MockVDRegistry{
  1128  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
  1129  			if didID == sampleInvalidDIDID {
  1130  				d, e := did.ParseDocument(testdata.SampleInvalidDID)
  1131  				require.NoError(t, e)
  1132  
  1133  				return &did.DocResolution{DIDDocument: d}, nil
  1134  			} else if strings.HasPrefix(didID, "did:key:") {
  1135  				k := key.New()
  1136  
  1137  				d, e := k.Read(didID)
  1138  				if e != nil {
  1139  					return nil, e
  1140  				}
  1141  
  1142  				return d, nil
  1143  			}
  1144  
  1145  			return nil, fmt.Errorf("did not found")
  1146  		},
  1147  	}
  1148  
  1149  	mockctx := newMockProvider(t)
  1150  	mockctx.VDRegistryValue = customVDR
  1151  	mockctx.CryptoValue = &cryptomock.Crypto{}
  1152  
  1153  	err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  1154  	require.NoError(t, err)
  1155  
  1156  	t.Run("Test VC wallet issue using controller - success", func(t *testing.T) {
  1157  		walletInstance, err := New(user, mockctx)
  1158  		require.NotEmpty(t, walletInstance)
  1159  		require.NoError(t, err)
  1160  
  1161  		// unlock wallet
  1162  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1163  		require.NoError(t, err)
  1164  		require.NotEmpty(t, authToken)
  1165  
  1166  		defer walletInstance.Close()
  1167  
  1168  		// import keys manually
  1169  		session, err := sessionManager().getSession(authToken)
  1170  		require.NotEmpty(t, session)
  1171  		require.NoError(t, err)
  1172  
  1173  		kmgr := session.KeyManager
  1174  		require.NotEmpty(t, kmgr)
  1175  
  1176  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1177  		// nolint: errcheck, gosec
  1178  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1179  
  1180  		// sign with just controller
  1181  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1182  			Controller: didKey,
  1183  		})
  1184  		require.NoError(t, err)
  1185  		require.NotEmpty(t, result)
  1186  		require.Len(t, result.Proofs, 1)
  1187  	})
  1188  
  1189  	t.Run("Test VC wallet issue JSONWebSignature2020 using controller - success", func(t *testing.T) {
  1190  		walletInstance, err := New(user, mockctx)
  1191  		require.NotEmpty(t, walletInstance)
  1192  		require.NoError(t, err)
  1193  
  1194  		// unlock wallet
  1195  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1196  		require.NoError(t, err)
  1197  		require.NotEmpty(t, authToken)
  1198  
  1199  		defer walletInstance.Close()
  1200  
  1201  		// import keys manually
  1202  		session, err := sessionManager().getSession(authToken)
  1203  		require.NotEmpty(t, session)
  1204  		require.NoError(t, err)
  1205  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1206  		// nolint: errcheck, gosec
  1207  		session.KeyManager.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1208  
  1209  		// sign with just controller
  1210  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1211  			Controller: didKey,
  1212  			ProofType:  JSONWebSignature2020,
  1213  		})
  1214  		require.NoError(t, err)
  1215  		require.NotEmpty(t, result)
  1216  		require.Len(t, result.Proofs, 1)
  1217  	})
  1218  
  1219  	t.Run("Test VC wallet issue JWT VC using controller - success", func(t *testing.T) {
  1220  		walletInstance, err := New(user, mockctx)
  1221  		require.NotEmpty(t, walletInstance)
  1222  		require.NoError(t, err)
  1223  
  1224  		walletInstance.walletCrypto = &cryptomock.Crypto{
  1225  			SignValue: []byte("abcdefg"),
  1226  		}
  1227  
  1228  		// unlock wallet
  1229  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1230  		require.NoError(t, err)
  1231  		require.NotEmpty(t, authToken)
  1232  
  1233  		defer walletInstance.Close()
  1234  
  1235  		// import keys manually
  1236  		session, err := sessionManager().getSession(authToken)
  1237  		require.NotEmpty(t, session)
  1238  		require.NoError(t, err)
  1239  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1240  		// nolint: errcheck, gosec
  1241  		session.KeyManager.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1242  
  1243  		// sign with just controller
  1244  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1245  			Controller:  didKey,
  1246  			ProofFormat: ExternalJWTProofFormat,
  1247  			ProofType:   JSONWebSignature2020,
  1248  		})
  1249  		require.NoError(t, err)
  1250  		require.NotEmpty(t, result)
  1251  
  1252  		require.NotEqual(t, "", result.JWT)
  1253  
  1254  		vcExpected, err := verifiable.ParseCredential(testdata.SampleUDCVC, verifiable.WithDisabledProofCheck(),
  1255  			verifiable.WithJSONLDDocumentLoader(walletInstance.jsonldDocumentLoader))
  1256  		require.NoError(t, err)
  1257  
  1258  		vcActual, err := verifiable.ParseCredential([]byte(result.JWT), verifiable.WithDisabledProofCheck(),
  1259  			verifiable.WithJSONLDDocumentLoader(walletInstance.jsonldDocumentLoader))
  1260  		require.NoError(t, err)
  1261  
  1262  		require.Equal(t, result.JWT, vcActual.JWT)
  1263  		vcActual.JWT = ""
  1264  
  1265  		require.Equal(t, vcExpected, vcActual)
  1266  	})
  1267  
  1268  	t.Run("Test VC wallet issue JWT VC - fail to generate claims", func(t *testing.T) {
  1269  		walletInstance, err := New(user, mockctx)
  1270  		require.NotEmpty(t, walletInstance)
  1271  		require.NoError(t, err)
  1272  
  1273  		walletInstance.walletCrypto = &cryptomock.Crypto{
  1274  			SignValue: []byte("abcdefg"),
  1275  		}
  1276  
  1277  		// unlock wallet
  1278  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1279  		require.NoError(t, err)
  1280  		require.NotEmpty(t, authToken)
  1281  
  1282  		defer walletInstance.Close()
  1283  
  1284  		// import keys manually
  1285  		session, err := sessionManager().getSession(authToken)
  1286  		require.NotEmpty(t, session)
  1287  		require.NoError(t, err)
  1288  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1289  		// nolint: errcheck, gosec
  1290  		session.KeyManager.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1291  
  1292  		minimalVC := &verifiable.Credential{
  1293  			Context: []string{verifiable.ContextURI},
  1294  			ID:      "https://foo.bar",
  1295  			Issued:  util.NewTime(time.Now()),
  1296  			Types:   []string{verifiable.VCType},
  1297  			Subject: []verifiable.Subject{
  1298  				{
  1299  					ID: "foo", // with multiple subjects, VC can't be converted to JWT claims.
  1300  				},
  1301  				{
  1302  					ID: "bar",
  1303  				},
  1304  			},
  1305  			Issuer: verifiable.Issuer{
  1306  				ID: "https://bar.baz",
  1307  			},
  1308  		}
  1309  
  1310  		vcBytes, err := minimalVC.MarshalJSON()
  1311  		require.NoError(t, err)
  1312  
  1313  		// sign with just controller
  1314  		_, err = walletInstance.Issue(authToken, vcBytes, &ProofOptions{
  1315  			Controller:  didKey,
  1316  			ProofFormat: ExternalJWTProofFormat,
  1317  			ProofType:   JSONWebSignature2020,
  1318  		})
  1319  		require.Error(t, err)
  1320  		require.Contains(t, err.Error(), "failed to generate JWT claims for VC")
  1321  	})
  1322  
  1323  	t.Run("Test VC wallet issue JWT VC - fail to create JWT", func(t *testing.T) {
  1324  		walletInstance, err := New(user, mockctx)
  1325  		require.NotEmpty(t, walletInstance)
  1326  		require.NoError(t, err)
  1327  
  1328  		expectErr := errors.New("expected error")
  1329  
  1330  		walletInstance.walletCrypto = &cryptomock.Crypto{
  1331  			SignErr: expectErr,
  1332  		}
  1333  
  1334  		// unlock wallet
  1335  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1336  		require.NoError(t, err)
  1337  		require.NotEmpty(t, authToken)
  1338  
  1339  		defer walletInstance.Close()
  1340  
  1341  		// import keys manually
  1342  		session, err := sessionManager().getSession(authToken)
  1343  		require.NotEmpty(t, session)
  1344  		require.NoError(t, err)
  1345  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1346  		// nolint: errcheck, gosec
  1347  		session.KeyManager.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1348  
  1349  		_, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1350  			Controller:  didKey,
  1351  			ProofFormat: ExternalJWTProofFormat,
  1352  			ProofType:   JSONWebSignature2020,
  1353  		})
  1354  		require.Error(t, err)
  1355  		require.ErrorIs(t, err, expectErr)
  1356  		require.Contains(t, err.Error(), "failed to generate JWT VC")
  1357  	})
  1358  
  1359  	t.Run("Test VC wallet issue using verification method - success", func(t *testing.T) {
  1360  		walletInstance, err := New(user, mockctx)
  1361  		require.NotEmpty(t, walletInstance)
  1362  		require.NoError(t, err)
  1363  
  1364  		// unlock wallet
  1365  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1366  		require.NoError(t, err)
  1367  		require.NotEmpty(t, authToken)
  1368  
  1369  		defer walletInstance.Close()
  1370  
  1371  		// import keys manually
  1372  		session, err := sessionManager().getSession(authToken)
  1373  		require.NotEmpty(t, session)
  1374  		require.NoError(t, err)
  1375  
  1376  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1377  		// nolint: errcheck, gosec
  1378  		session.KeyManager.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1379  
  1380  		// issue
  1381  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1382  			Controller:         didKey,
  1383  			VerificationMethod: sampleVerificationMethod,
  1384  		})
  1385  		require.NoError(t, err)
  1386  		require.NotEmpty(t, result)
  1387  		require.Len(t, result.Proofs, 1)
  1388  	})
  1389  
  1390  	t.Run("Test VC wallet issue using all options - success", func(t *testing.T) {
  1391  		walletInstance, err := New(user, mockctx)
  1392  		require.NotEmpty(t, walletInstance)
  1393  		require.NoError(t, err)
  1394  
  1395  		// unlock wallet
  1396  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1397  		require.NoError(t, err)
  1398  		require.NotEmpty(t, authToken)
  1399  
  1400  		defer walletInstance.Close()
  1401  
  1402  		// import keys manually
  1403  		session, err := sessionManager().getSession(authToken)
  1404  		require.NotEmpty(t, session)
  1405  		require.NoError(t, err)
  1406  
  1407  		kmgr := session.KeyManager
  1408  		require.NotEmpty(t, kmgr)
  1409  
  1410  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1411  		// nolint: errcheck, gosec
  1412  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1413  
  1414  		// issue credential
  1415  		proofRepr := verifiable.SignatureJWS
  1416  		vm := sampleVerificationMethod
  1417  		created, err := time.Parse("2006-01-02", sampleCreatedDate)
  1418  		require.NoError(t, err)
  1419  
  1420  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1421  			Controller:          didKey,
  1422  			VerificationMethod:  vm,
  1423  			ProofType:           JSONWebSignature2020,
  1424  			Challenge:           sampleChallenge,
  1425  			Domain:              sampleDomain,
  1426  			Created:             &created,
  1427  			ProofRepresentation: &proofRepr,
  1428  		})
  1429  		require.NoError(t, err)
  1430  		require.NotEmpty(t, result)
  1431  		require.Len(t, result.Proofs, 1)
  1432  
  1433  		require.Equal(t, result.Proofs[0]["challenge"], sampleChallenge)
  1434  		require.Equal(t, result.Proofs[0]["created"], "2020-12-25T00:00:00Z")
  1435  		require.Equal(t, result.Proofs[0]["domain"], sampleDomain)
  1436  		require.NotEmpty(t, result.Proofs[0]["jws"])
  1437  		require.Equal(t, result.Proofs[0]["proofPurpose"], "assertionMethod")
  1438  		require.Equal(t, result.Proofs[0]["type"], JSONWebSignature2020)
  1439  		require.Equal(t, result.Proofs[0]["verificationMethod"], vm)
  1440  	})
  1441  
  1442  	t.Run("Test VC wallet issue using BBS - success", func(t *testing.T) {
  1443  		walletInstance, err := New(user, mockctx)
  1444  		require.NotEmpty(t, walletInstance)
  1445  		require.NoError(t, err)
  1446  
  1447  		// unlock wallet
  1448  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1449  		require.NoError(t, err)
  1450  		require.NotEmpty(t, authToken)
  1451  
  1452  		defer walletInstance.Close()
  1453  
  1454  		// import keys manually
  1455  		session, err := sessionManager().getSession(authToken)
  1456  		require.NotEmpty(t, session)
  1457  		require.NoError(t, err)
  1458  
  1459  		kmgr := session.KeyManager
  1460  		require.NotEmpty(t, kmgr)
  1461  
  1462  		privKeyBBS, err := bbs12381g2pub.UnmarshalPrivateKey(base58.Decode(pkBBSBase58))
  1463  		require.NoError(t, err)
  1464  		// nolint: errcheck, gosec
  1465  		kmgr.ImportPrivateKey(privKeyBBS, kms.BLS12381G2Type, kms.WithKeyID(keyIDBBS))
  1466  
  1467  		// sign with just controller
  1468  		proofRepr := verifiable.SignatureProofValue
  1469  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1470  			Controller:          didKeyBBS,
  1471  			ProofType:           BbsBlsSignature2020,
  1472  			ProofRepresentation: &proofRepr,
  1473  		})
  1474  		require.NoError(t, err)
  1475  		require.NotEmpty(t, result)
  1476  		require.Len(t, result.Proofs, 1)
  1477  	})
  1478  
  1479  	t.Run("Test VC wallet issue using stored DID - success", func(t *testing.T) {
  1480  		mockctx1 := newMockProvider(t)
  1481  		mockctx1.VDRegistryValue = &mockvdr.MockVDRegistry{}
  1482  		mockctx1.CryptoValue = &cryptomock.Crypto{}
  1483  
  1484  		err := CreateProfile(user, mockctx1, WithPassphrase(samplePassPhrase))
  1485  		require.NoError(t, err)
  1486  
  1487  		walletInstance, err := New(user, mockctx1)
  1488  		require.NotEmpty(t, walletInstance)
  1489  		require.NoError(t, err)
  1490  
  1491  		// unlock wallet
  1492  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1493  		require.NoError(t, err)
  1494  		require.NotEmpty(t, authToken)
  1495  
  1496  		defer walletInstance.Close()
  1497  
  1498  		// import keys manually
  1499  		session, err := sessionManager().getSession(authToken)
  1500  		require.NotEmpty(t, session)
  1501  		require.NoError(t, err)
  1502  
  1503  		kmgr := session.KeyManager
  1504  		require.NotEmpty(t, kmgr)
  1505  
  1506  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1507  		// nolint: errcheck, gosec
  1508  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1509  
  1510  		// save DID Resolution response
  1511  		err = walletInstance.Add(authToken, DIDResolutionResponse, testdata.SampleDocResolutionResponse)
  1512  		require.NoError(t, err)
  1513  
  1514  		// sign with just controller
  1515  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1516  			Controller: didKey,
  1517  		})
  1518  		require.NoError(t, err)
  1519  		require.NotEmpty(t, result)
  1520  		require.Len(t, result.Proofs, 1)
  1521  	})
  1522  
  1523  	t.Run("Test VC wallet issue failure - invalid VC", func(t *testing.T) {
  1524  		walletInstance, err := New(user, mockctx)
  1525  		require.NotEmpty(t, walletInstance)
  1526  		require.NoError(t, err)
  1527  
  1528  		result, err := walletInstance.Issue(sampleFakeTkn, []byte("--"), &ProofOptions{})
  1529  		require.Empty(t, result)
  1530  		require.Error(t, err)
  1531  		require.Contains(t, err.Error(), "failed to parse credential")
  1532  	})
  1533  
  1534  	t.Run("Test VC wallet issue failure - proof option validation", func(t *testing.T) {
  1535  		walletInstance, err := New(user, mockctx)
  1536  		require.NotEmpty(t, walletInstance)
  1537  		require.NoError(t, err)
  1538  
  1539  		// unlock wallet
  1540  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1541  		require.NoError(t, err)
  1542  		require.NotEmpty(t, authToken)
  1543  
  1544  		defer walletInstance.Close()
  1545  
  1546  		// no controller
  1547  		result, err := walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{})
  1548  		require.Empty(t, result)
  1549  		require.Error(t, err)
  1550  		require.Contains(t, err.Error(), "invalid proof option, 'controller' is required")
  1551  
  1552  		// DID not found
  1553  		result, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1554  			Controller: "did:example:1234",
  1555  		})
  1556  		require.Empty(t, result)
  1557  		require.Error(t, err)
  1558  		require.Contains(t, err.Error(), "failed to prepare proof: did not found")
  1559  
  1560  		// no assertion method
  1561  		result, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1562  			Controller: sampleInvalidDIDID,
  1563  		})
  1564  		require.Empty(t, result)
  1565  		require.Error(t, err)
  1566  		require.Contains(t, err.Error(), "unable to find 'assertionMethod' for given verification method")
  1567  	})
  1568  
  1569  	t.Run("Test VC wallet issue failure - add proof errors", func(t *testing.T) {
  1570  		walletInstance, err := New(user, mockctx)
  1571  		require.NotEmpty(t, walletInstance)
  1572  		require.NoError(t, err)
  1573  
  1574  		// wallet locked
  1575  		result, err := walletInstance.Issue(sampleFakeTkn, testdata.SampleUDCVC, &ProofOptions{
  1576  			Controller: didKey,
  1577  		})
  1578  		require.Empty(t, result)
  1579  		require.Error(t, err)
  1580  		require.Contains(t, err.Error(), "wallet locked")
  1581  
  1582  		// get token
  1583  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1584  		require.NoError(t, err)
  1585  		require.NotEmpty(t, authToken)
  1586  
  1587  		defer walletInstance.Close()
  1588  
  1589  		// key not found
  1590  		result, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1591  			Controller: "did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd",
  1592  		})
  1593  		require.Empty(t, result)
  1594  		require.Contains(t, err.Error(), "cannot read data for keysetID")
  1595  
  1596  		// import keys manually
  1597  		session, err := sessionManager().getSession(authToken)
  1598  		require.NotEmpty(t, session)
  1599  		require.NoError(t, err)
  1600  
  1601  		kmgr := session.KeyManager
  1602  		require.NotEmpty(t, kmgr)
  1603  
  1604  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1605  		// nolint: errcheck, gosec
  1606  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1607  
  1608  		// invalid signature type
  1609  		result, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1610  			Controller: didKey,
  1611  			ProofType:  "invalid",
  1612  		})
  1613  		require.Empty(t, result)
  1614  		require.Contains(t, err.Error(), " unsupported signature type 'invalid'")
  1615  
  1616  		// wrong key type
  1617  		result, err = walletInstance.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  1618  			Controller: didKey,
  1619  			ProofType:  BbsBlsSignature2020,
  1620  		})
  1621  		require.Empty(t, result)
  1622  		require.Contains(t, err.Error(), "failed to add linked data proof")
  1623  	})
  1624  }
  1625  
  1626  func TestWallet_Prove(t *testing.T) {
  1627  	user := uuid.New().String()
  1628  	customVDR := &mockvdr.MockVDRegistry{
  1629  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
  1630  			if didID == sampleInvalidDIDID {
  1631  				d, e := did.ParseDocument(testdata.SampleInvalidDID)
  1632  				require.NoError(t, e)
  1633  
  1634  				return &did.DocResolution{DIDDocument: d}, nil
  1635  			} else if strings.HasPrefix(didID, "did:key:") {
  1636  				k := key.New()
  1637  
  1638  				d, e := k.Read(didID)
  1639  				if e != nil {
  1640  					return nil, e
  1641  				}
  1642  
  1643  				return d, nil
  1644  			}
  1645  
  1646  			return nil, fmt.Errorf("did not found")
  1647  		},
  1648  	}
  1649  
  1650  	mockctx := newMockProvider(t)
  1651  	mockctx.VDRegistryValue = customVDR
  1652  	mockctx.CryptoValue = &cryptomock.Crypto{
  1653  		SignValue: []byte("abcdefg"),
  1654  	}
  1655  
  1656  	// create profile
  1657  	err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  1658  	require.NoError(t, err)
  1659  
  1660  	// prepare VCs for tests
  1661  	vcs := make(map[string]*verifiable.Credential, 2)
  1662  	walletForIssue, err := New(user, mockctx)
  1663  	require.NotEmpty(t, walletForIssue)
  1664  	require.NoError(t, err)
  1665  
  1666  	issuerToken, err := walletForIssue.Open(WithUnlockByPassphrase(samplePassPhrase))
  1667  	require.NoError(t, err)
  1668  	require.NotEmpty(t, issuerToken)
  1669  
  1670  	// import ED25519 & BLS12381G2Type keys manually
  1671  	session, err := sessionManager().getSession(issuerToken)
  1672  	require.NotEmpty(t, session)
  1673  	require.NoError(t, err)
  1674  
  1675  	kmgr := session.KeyManager
  1676  	require.NotEmpty(t, kmgr)
  1677  
  1678  	edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1679  	// nolint: errcheck, gosec
  1680  	kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1681  
  1682  	privKeyBBS, err := bbs12381g2pub.UnmarshalPrivateKey(base58.Decode(pkBBSBase58))
  1683  	require.NoError(t, err)
  1684  	// nolint: errcheck, gosec
  1685  	kmgr.ImportPrivateKey(privKeyBBS, kms.BLS12381G2Type, kms.WithKeyID(keyIDBBS))
  1686  
  1687  	// issue a credential with Ed25519Signature2018
  1688  	result, err := walletForIssue.Issue(issuerToken, testdata.SampleUDCVC, &ProofOptions{
  1689  		Controller: didKey,
  1690  	})
  1691  	require.NoError(t, err)
  1692  	require.NotEmpty(t, result)
  1693  	require.Len(t, result.Proofs, 1)
  1694  	vcs["edvc"] = result
  1695  
  1696  	// issue a credential with BbsBlsSignature2020
  1697  	proofRepr := verifiable.SignatureProofValue
  1698  	result, err = walletForIssue.Issue(issuerToken, testdata.SampleUDCVC, &ProofOptions{
  1699  		Controller:          didKeyBBS,
  1700  		ProofType:           BbsBlsSignature2020,
  1701  		ProofRepresentation: &proofRepr,
  1702  	})
  1703  	require.NoError(t, err)
  1704  	require.NotEmpty(t, result)
  1705  	require.Len(t, result.Proofs, 1)
  1706  	vcs["bbsvc"] = result
  1707  
  1708  	templateCred, err := verifiable.ParseCredential(testdata.SampleUDCVC, verifiable.WithDisabledProofCheck(),
  1709  		verifiable.WithJSONLDDocumentLoader(walletForIssue.jsonldDocumentLoader))
  1710  	require.NoError(t, err)
  1711  
  1712  	templateCred.Issuer.ID = didKey
  1713  
  1714  	templateData, err := templateCred.MarshalJSON()
  1715  	require.NoError(t, err)
  1716  
  1717  	// issue a JWT credential
  1718  	result, err = walletForIssue.Issue(issuerToken, templateData, &ProofOptions{
  1719  		Controller:         didKey,
  1720  		VerificationMethod: sampleVerificationMethod,
  1721  		ProofFormat:        ExternalJWTProofFormat,
  1722  	})
  1723  	require.NoError(t, err)
  1724  	require.NotEmpty(t, result)
  1725  	require.NotEqual(t, "", result.JWT)
  1726  	require.True(t, jwt.IsJWS(result.JWT))
  1727  
  1728  	vcs["jwtvc"] = result
  1729  
  1730  	walletForIssue.Close()
  1731  
  1732  	t.Run("Test prove using stored & raw credential - success", func(t *testing.T) {
  1733  		walletInstance, err := New(user, mockctx)
  1734  		require.NotEmpty(t, walletInstance)
  1735  		require.NoError(t, err)
  1736  
  1737  		// unlock wallet
  1738  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1739  		require.NoError(t, err)
  1740  		require.NotEmpty(t, authToken)
  1741  
  1742  		defer walletInstance.Close()
  1743  
  1744  		// save one VC in store
  1745  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"])
  1746  		defer cleanup()
  1747  
  1748  		// import keys manually for signing presentation
  1749  		session, err := sessionManager().getSession(authToken)
  1750  		require.NotEmpty(t, session)
  1751  		require.NoError(t, err)
  1752  
  1753  		kmgr := session.KeyManager
  1754  		require.NotEmpty(t, kmgr)
  1755  
  1756  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1757  		// nolint: errcheck, gosec
  1758  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1759  
  1760  		edVCBytes, err := json.Marshal(vcs["edvc"])
  1761  		require.NoError(t, err)
  1762  
  1763  		bbsVCBytes, err := json.Marshal(vcs["bbsvc"])
  1764  		require.NoError(t, err)
  1765  
  1766  		jwtVCBytes, err := json.Marshal(vcs["jwtvc"])
  1767  		require.NoError(t, err)
  1768  
  1769  		// sign with just controller (one stored & one raw bytes)
  1770  		result, err := walletInstance.Prove(authToken,
  1771  			&ProofOptions{Controller: didKey},
  1772  			WithStoredCredentialsToProve(vcs["edvc"].ID),
  1773  			WithRawCredentialsToProve(bbsVCBytes, jwtVCBytes),
  1774  			WithCredentialsToProve(vcs["edvc"]),
  1775  		)
  1776  		require.NoError(t, err)
  1777  		require.NotEmpty(t, result)
  1778  		require.Len(t, result.Proofs, 1)
  1779  		require.Len(t, result.Credentials(), 4)
  1780  		require.Equal(t, result.Holder, didKey)
  1781  
  1782  		// sign with just controller with all raw credentials
  1783  		result, err = walletInstance.Prove(authToken,
  1784  			&ProofOptions{Controller: didKey},
  1785  			WithRawCredentialsToProve(edVCBytes, bbsVCBytes, jwtVCBytes),
  1786  		)
  1787  		require.NoError(t, err)
  1788  		require.NotEmpty(t, result)
  1789  		require.Len(t, result.Proofs, 1)
  1790  		require.Equal(t, result.Holder, didKey)
  1791  	})
  1792  
  1793  	t.Run("Test prove using presentation - success", func(t *testing.T) {
  1794  		walletInstance, err := New(user, mockctx)
  1795  		require.NotEmpty(t, walletInstance)
  1796  		require.NoError(t, err)
  1797  
  1798  		// unlock wallet
  1799  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1800  		require.NoError(t, err)
  1801  		require.NotEmpty(t, authToken)
  1802  
  1803  		defer walletInstance.Close()
  1804  
  1805  		// save one VC in store
  1806  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"])
  1807  		defer cleanup()
  1808  
  1809  		// import keys manually for signing presentation
  1810  		session, err := sessionManager().getSession(authToken)
  1811  		require.NotEmpty(t, session)
  1812  		require.NoError(t, err)
  1813  
  1814  		kmgr := session.KeyManager
  1815  		require.NotEmpty(t, kmgr)
  1816  
  1817  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1818  		// nolint: errcheck, gosec
  1819  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1820  
  1821  		bbsVCBytes, err := json.Marshal(vcs["bbsvc"])
  1822  		require.NoError(t, err)
  1823  
  1824  		pres, err := verifiable.NewPresentation(verifiable.WithCredentials(vcs["edvc"]))
  1825  		require.NoError(t, err)
  1826  		require.NotEmpty(t, pres)
  1827  
  1828  		// sign with just controller
  1829  		result, err := walletInstance.Prove(authToken,
  1830  			&ProofOptions{Controller: didKey},
  1831  			WithPresentationToProve(pres),
  1832  		)
  1833  		require.NoError(t, err)
  1834  		require.NotEmpty(t, result)
  1835  		require.Len(t, result.Proofs, 1)
  1836  		require.Len(t, result.Credentials(), 1)
  1837  		require.Equal(t, result.Holder, didKey)
  1838  
  1839  		// sign with just controller (sign with presentation & credentials)
  1840  		pres, err = verifiable.NewPresentation(verifiable.WithCredentials(vcs["edvc"]))
  1841  		require.NoError(t, err)
  1842  		require.NotEmpty(t, pres)
  1843  
  1844  		result, err = walletInstance.Prove(authToken,
  1845  			&ProofOptions{Controller: didKey},
  1846  			WithPresentationToProve(pres),
  1847  			WithStoredCredentialsToProve(vcs["edvc"].ID),
  1848  			WithRawCredentialsToProve(bbsVCBytes),
  1849  		)
  1850  
  1851  		require.NoError(t, err)
  1852  		require.NotEmpty(t, result)
  1853  		require.Len(t, result.Proofs, 1)
  1854  		require.Len(t, result.Credentials(), 3)
  1855  		require.Equal(t, result.Holder, didKey)
  1856  	})
  1857  
  1858  	t.Run("Test prove using raw presentation - success", func(t *testing.T) {
  1859  		walletInstance, err := New(user, mockctx)
  1860  		require.NotEmpty(t, walletInstance)
  1861  		require.NoError(t, err)
  1862  
  1863  		// unlock wallet
  1864  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1865  		require.NoError(t, err)
  1866  		require.NotEmpty(t, authToken)
  1867  
  1868  		defer walletInstance.Close()
  1869  
  1870  		// save one VC in store
  1871  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"])
  1872  		defer cleanup()
  1873  
  1874  		// import keys manually for signing presentation
  1875  		session, err := sessionManager().getSession(authToken)
  1876  		require.NotEmpty(t, session)
  1877  		require.NoError(t, err)
  1878  
  1879  		kmgr := session.KeyManager
  1880  		require.NotEmpty(t, kmgr)
  1881  
  1882  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1883  		// nolint: errcheck, gosec
  1884  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1885  
  1886  		bbsVCBytes, err := json.Marshal(vcs["bbsvc"])
  1887  		require.NoError(t, err)
  1888  
  1889  		pres, err := verifiable.NewPresentation(verifiable.WithCredentials(vcs["edvc"]))
  1890  		require.NoError(t, err)
  1891  		require.NotEmpty(t, pres)
  1892  
  1893  		// sign with just controller
  1894  		result, err := walletInstance.Prove(authToken,
  1895  			&ProofOptions{Controller: didKey},
  1896  			WithPresentationToProve(pres),
  1897  		)
  1898  		require.NoError(t, err)
  1899  		require.NotEmpty(t, result)
  1900  		require.Len(t, result.Proofs, 1)
  1901  		require.Len(t, result.Credentials(), 1)
  1902  		require.Equal(t, result.Holder, didKey)
  1903  
  1904  		// sign with just controller (sign with presentation & credentials)
  1905  		pres, err = verifiable.NewPresentation(verifiable.WithCredentials(vcs["edvc"]))
  1906  		require.NoError(t, err)
  1907  		require.NotEmpty(t, pres)
  1908  
  1909  		rawPres, err := pres.MarshalJSON()
  1910  		require.NoError(t, err)
  1911  
  1912  		result, err = walletInstance.Prove(authToken,
  1913  			&ProofOptions{Controller: didKey},
  1914  			WithRawPresentationToProve(rawPres),
  1915  			WithStoredCredentialsToProve(vcs["edvc"].ID),
  1916  			WithRawCredentialsToProve(bbsVCBytes),
  1917  		)
  1918  
  1919  		require.NoError(t, err)
  1920  		require.NotEmpty(t, result)
  1921  		require.Len(t, result.Proofs, 1)
  1922  		require.Len(t, result.Credentials(), 3)
  1923  		require.Equal(t, result.Holder, didKey)
  1924  	})
  1925  
  1926  	t.Run("Test prove using various proof options - success", func(t *testing.T) {
  1927  		walletInstance, err := New(user, mockctx)
  1928  		require.NotEmpty(t, walletInstance)
  1929  		require.NoError(t, err)
  1930  
  1931  		// unlock wallet
  1932  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1933  		require.NoError(t, err)
  1934  		require.NotEmpty(t, authToken)
  1935  
  1936  		defer walletInstance.Close()
  1937  
  1938  		// save all VCs in store
  1939  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"], vcs["bbsvc"])
  1940  		defer cleanup()
  1941  
  1942  		// import keys manually for signing presentation
  1943  		session, err := sessionManager().getSession(authToken)
  1944  		require.NotEmpty(t, session)
  1945  		require.NoError(t, err)
  1946  
  1947  		kmgr := session.KeyManager
  1948  		require.NotEmpty(t, kmgr)
  1949  
  1950  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  1951  		// nolint: errcheck, gosec
  1952  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  1953  
  1954  		// prepare opts
  1955  		proofRepr := verifiable.SignatureJWS
  1956  		vm := sampleVerificationMethod
  1957  		created, err := time.Parse("2006-01-02", sampleCreatedDate)
  1958  		require.NoError(t, err)
  1959  
  1960  		// sign with just controller (one stored & one raw)
  1961  		result, err := walletInstance.Prove(authToken, &ProofOptions{
  1962  			Controller:          didKey,
  1963  			VerificationMethod:  vm,
  1964  			ProofType:           JSONWebSignature2020,
  1965  			Challenge:           sampleChallenge,
  1966  			Domain:              sampleDomain,
  1967  			Created:             &created,
  1968  			ProofRepresentation: &proofRepr,
  1969  		}, WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  1970  		require.NoError(t, err)
  1971  		require.NotEmpty(t, result)
  1972  		require.Len(t, result.Proofs, 1)
  1973  
  1974  		require.Equal(t, result.Proofs[0]["challenge"], sampleChallenge)
  1975  		require.Equal(t, result.Proofs[0]["created"], "2020-12-25T00:00:00Z")
  1976  		require.Equal(t, result.Proofs[0]["domain"], sampleDomain)
  1977  		require.NotEmpty(t, result.Proofs[0]["jws"])
  1978  		require.Equal(t, result.Proofs[0]["proofPurpose"], "authentication")
  1979  		require.Equal(t, result.Proofs[0]["type"], JSONWebSignature2020)
  1980  		require.Equal(t, result.Proofs[0]["verificationMethod"], vm)
  1981  	})
  1982  
  1983  	t.Run("Test prove using JWT - success", func(t *testing.T) {
  1984  		walletInstance, err := New(user, mockctx)
  1985  		require.NotEmpty(t, walletInstance)
  1986  		require.NoError(t, err)
  1987  
  1988  		// unlock wallet
  1989  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  1990  		require.NoError(t, err)
  1991  		require.NotEmpty(t, authToken)
  1992  
  1993  		defer walletInstance.Close()
  1994  
  1995  		// save one VC in store
  1996  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["jwtvc"])
  1997  		defer cleanup()
  1998  
  1999  		// import keys manually for signing presentation
  2000  		session, err := sessionManager().getSession(authToken)
  2001  		require.NotEmpty(t, session)
  2002  		require.NoError(t, err)
  2003  
  2004  		kmgr := session.KeyManager
  2005  		require.NotEmpty(t, kmgr)
  2006  
  2007  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2008  		// nolint: errcheck, gosec
  2009  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2010  
  2011  		// sign with just controller (one stored & one raw bytes)
  2012  		result, err := walletInstance.Prove(authToken,
  2013  			&ProofOptions{
  2014  				Controller:  didKey,
  2015  				ProofFormat: ExternalJWTProofFormat,
  2016  			},
  2017  			WithStoredCredentialsToProve(vcs["jwtvc"].ID),
  2018  		)
  2019  		require.NoError(t, err)
  2020  		require.NotEmpty(t, result)
  2021  		require.Len(t, result.Proofs, 0)
  2022  		require.Len(t, result.Credentials(), 1)
  2023  		require.Equal(t, result.Holder, didKey)
  2024  		require.NotEmpty(t, result.JWT)
  2025  	})
  2026  
  2027  	t.Run("Test prove without credentials (DIDAuth) - success", func(t *testing.T) {
  2028  		walletInstance, err := New(user, mockctx)
  2029  		require.NotEmpty(t, walletInstance)
  2030  		require.NoError(t, err)
  2031  
  2032  		// unlock wallet
  2033  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2034  		require.NoError(t, err)
  2035  		require.NotEmpty(t, authToken)
  2036  
  2037  		defer walletInstance.Close()
  2038  
  2039  		// import keys manually for signing presentation
  2040  		session, err := sessionManager().getSession(authToken)
  2041  		require.NotEmpty(t, session)
  2042  		require.NoError(t, err)
  2043  
  2044  		kmgr := session.KeyManager
  2045  		require.NotEmpty(t, kmgr)
  2046  
  2047  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2048  		// nolint: errcheck, gosec
  2049  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2050  
  2051  		// prepare opts
  2052  		proofRepr := verifiable.SignatureJWS
  2053  		vm := sampleVerificationMethod
  2054  		created, err := time.Parse("2006-01-02", sampleCreatedDate)
  2055  		require.NoError(t, err)
  2056  
  2057  		result, err := walletInstance.Prove(authToken, &ProofOptions{
  2058  			Controller:          didKey,
  2059  			VerificationMethod:  vm,
  2060  			ProofType:           JSONWebSignature2020,
  2061  			Challenge:           sampleChallenge,
  2062  			Domain:              sampleDomain,
  2063  			Created:             &created,
  2064  			ProofRepresentation: &proofRepr,
  2065  		})
  2066  		require.NoError(t, err)
  2067  		require.NotEmpty(t, result)
  2068  		require.Empty(t, result.Credentials())
  2069  
  2070  		require.Len(t, result.Proofs, 1)
  2071  		require.Equal(t, result.Proofs[0]["challenge"], sampleChallenge)
  2072  		require.Equal(t, result.Proofs[0]["created"], "2020-12-25T00:00:00Z")
  2073  		require.Equal(t, result.Proofs[0]["domain"], sampleDomain)
  2074  		require.NotEmpty(t, result.Proofs[0]["jws"])
  2075  		require.Equal(t, result.Proofs[0]["proofPurpose"], "authentication")
  2076  		require.Equal(t, result.Proofs[0]["type"], JSONWebSignature2020)
  2077  		require.Equal(t, result.Proofs[0]["verificationMethod"], vm)
  2078  	})
  2079  
  2080  	t.Run("Test prove failure - invalid credentials/presentation", func(t *testing.T) {
  2081  		walletInstance, err := New(user, mockctx)
  2082  		require.NotEmpty(t, walletInstance)
  2083  		require.NoError(t, err)
  2084  
  2085  		// unlock wallet
  2086  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2087  		require.NoError(t, err)
  2088  		require.NotEmpty(t, authToken)
  2089  
  2090  		defer walletInstance.Close()
  2091  
  2092  		result, err := walletInstance.Prove(authToken, &ProofOptions{}, WithRawCredentialsToProve([]byte("123")))
  2093  		require.Empty(t, result)
  2094  		require.Error(t, err)
  2095  		require.Contains(t, err.Error(), "failed to resolve credentials from request")
  2096  
  2097  		result, err = walletInstance.Prove(authToken, &ProofOptions{},
  2098  			WithStoredCredentialsToProve("non-existing-credential"))
  2099  		require.Empty(t, result)
  2100  		require.Error(t, err)
  2101  		require.Contains(t, err.Error(), "data not found")
  2102  
  2103  		// save invalid VC in store
  2104  		require.NoError(t, walletInstance.Add(authToken, Credential, []byte(sampleInvalidDIDContent)))
  2105  		result, err = walletInstance.Prove(authToken, &ProofOptions{},
  2106  			WithStoredCredentialsToProve("did:example:sampleInvalidDIDContent"))
  2107  		require.Empty(t, result)
  2108  		require.Error(t, err)
  2109  		require.Contains(t, err.Error(), "build new credential")
  2110  
  2111  		result, err = walletInstance.Prove(authToken, &ProofOptions{},
  2112  			WithRawPresentationToProve([]byte(sampleInvalidDIDContent)))
  2113  		require.Contains(t, err.Error(), "verifiable presentation is not valid")
  2114  		require.Empty(t, result)
  2115  	})
  2116  
  2117  	t.Run("Test prove failures - proof option validation", func(t *testing.T) {
  2118  		walletInstance, err := New(user, mockctx)
  2119  		require.NotEmpty(t, walletInstance)
  2120  		require.NoError(t, err)
  2121  
  2122  		// unlock wallet
  2123  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2124  		require.NoError(t, err)
  2125  		require.NotEmpty(t, authToken)
  2126  
  2127  		defer walletInstance.Close()
  2128  
  2129  		// save all VCs in store
  2130  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"], vcs["bbsvc"])
  2131  		defer cleanup()
  2132  
  2133  		// no controller
  2134  		result, err := walletInstance.Prove(authToken, &ProofOptions{},
  2135  			WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2136  		require.Empty(t, result)
  2137  		require.Error(t, err)
  2138  		require.Contains(t, err.Error(), "invalid proof option, 'controller' is required")
  2139  
  2140  		// DID not found
  2141  		result, err = walletInstance.Prove(authToken, &ProofOptions{Controller: "did:example:1234"},
  2142  			WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2143  		require.Empty(t, result)
  2144  		require.Error(t, err)
  2145  		require.Contains(t, err.Error(), "failed to prepare proof: did not found")
  2146  
  2147  		// no assertion method
  2148  		result, err = walletInstance.Prove(authToken, &ProofOptions{Controller: sampleInvalidDIDID},
  2149  			WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2150  		require.Empty(t, result)
  2151  		require.Error(t, err)
  2152  		require.Contains(t, err.Error(), "unable to find 'authentication' for given verification method")
  2153  	})
  2154  
  2155  	t.Run("Test prove using JWT - fail to generate JWT claims from invalid presentation", func(t *testing.T) {
  2156  		walletInstance, err := New(user, mockctx)
  2157  		require.NotEmpty(t, walletInstance)
  2158  		require.NoError(t, err)
  2159  
  2160  		// unlock wallet
  2161  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2162  		require.NoError(t, err)
  2163  		require.NotEmpty(t, authToken)
  2164  
  2165  		defer walletInstance.Close()
  2166  
  2167  		// sign with invalid Presentation
  2168  		_, err = walletInstance.Prove(authToken,
  2169  			&ProofOptions{
  2170  				Controller:  didKey,
  2171  				ProofFormat: ExternalJWTProofFormat,
  2172  			},
  2173  			WithPresentationToProve(&verifiable.Presentation{
  2174  				Proofs: []verifiable.Proof{
  2175  					{
  2176  						"invalid": new(chan<- int), // can't marshal a channel
  2177  					},
  2178  				},
  2179  			}),
  2180  		)
  2181  		require.Error(t, err)
  2182  		require.Contains(t, err.Error(), "failed to generate JWT claims for VP")
  2183  	})
  2184  
  2185  	t.Run("Test prove using JWT - fail to sign VP", func(t *testing.T) {
  2186  		walletInstance, err := New(user, mockctx)
  2187  		require.NotEmpty(t, walletInstance)
  2188  		require.NoError(t, err)
  2189  
  2190  		// unlock wallet
  2191  		_, err = walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2192  		require.NoError(t, err)
  2193  		require.NotEmpty(t, issuerToken)
  2194  
  2195  		defer walletInstance.Close()
  2196  
  2197  		_, err = walletInstance.Prove("invalid auth token",
  2198  			&ProofOptions{
  2199  				Controller:  didKey,
  2200  				ProofFormat: ExternalJWTProofFormat,
  2201  			},
  2202  		)
  2203  		require.Error(t, err)
  2204  		require.Contains(t, err.Error(), "failed to generate JWT VP")
  2205  	})
  2206  
  2207  	t.Run("Test VC wallet prove failure - add LD proof errors", func(t *testing.T) {
  2208  		walletInstance, err := New(user, mockctx)
  2209  		require.NotEmpty(t, walletInstance)
  2210  		require.NoError(t, err)
  2211  
  2212  		// wallet locked
  2213  		result, err := walletInstance.Prove(sampleFakeTkn, &ProofOptions{Controller: didKey},
  2214  			WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2215  		require.Empty(t, result)
  2216  		require.Error(t, err)
  2217  		require.Contains(t, err.Error(), "wallet locked")
  2218  
  2219  		// get token
  2220  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2221  		require.NoError(t, err)
  2222  		require.NotEmpty(t, authToken)
  2223  
  2224  		defer walletInstance.Close()
  2225  
  2226  		cleanup := addCredentialsToWallet(t, walletInstance, authToken, vcs["edvc"], vcs["bbsvc"])
  2227  		defer cleanup()
  2228  
  2229  		// key not found
  2230  		result, err = walletInstance.Prove(authToken, &ProofOptions{
  2231  			Controller: "did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd",
  2232  		},
  2233  			WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2234  		require.Empty(t, result)
  2235  		require.Contains(t, err.Error(), "cannot read data for keysetID")
  2236  
  2237  		// import keys manually
  2238  		session, err := sessionManager().getSession(authToken)
  2239  		require.NotEmpty(t, session)
  2240  		require.NoError(t, err)
  2241  
  2242  		kmgr := session.KeyManager
  2243  		require.NotEmpty(t, kmgr)
  2244  
  2245  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2246  		// nolint: errcheck, gosec
  2247  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2248  
  2249  		// invalid signature type
  2250  		result, err = walletInstance.Prove(authToken, &ProofOptions{
  2251  			Controller: didKey,
  2252  			ProofType:  "invalid",
  2253  		}, WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2254  		require.Empty(t, result)
  2255  		require.Contains(t, err.Error(), " unsupported signature type 'invalid'")
  2256  
  2257  		// wrong key type
  2258  		result, err = walletInstance.Prove(authToken, &ProofOptions{
  2259  			Controller: didKey,
  2260  			ProofType:  BbsBlsSignature2020,
  2261  		}, WithStoredCredentialsToProve(vcs["edvc"].ID, vcs["bbsvc"].ID))
  2262  		require.Empty(t, result)
  2263  		require.Contains(t, err.Error(), "failed to add linked data proof")
  2264  	})
  2265  }
  2266  
  2267  func Test_AddContext(t *testing.T) {
  2268  	loader, err := ldtestutil.DocumentLoader()
  2269  	require.NoError(t, err)
  2270  
  2271  	vc, err := verifiable.ParseCredential(testdata.SampleUDCVC, verifiable.WithJSONLDDocumentLoader(loader))
  2272  	require.NoError(t, err)
  2273  	require.NotEmpty(t, vc)
  2274  
  2275  	require.Len(t, vc.Context, 3)
  2276  	addContext(vc, bbsContext)
  2277  	require.Len(t, vc.Context, 3)
  2278  	addContext(vc, bbsContext+".01")
  2279  	require.Len(t, vc.Context, 4)
  2280  }
  2281  
  2282  func TestWallet_Verify(t *testing.T) {
  2283  	user := uuid.New().String()
  2284  	customVDR := &mockvdr.MockVDRegistry{
  2285  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
  2286  			if didID == sampleInvalidDIDID {
  2287  				d, e := did.ParseDocument(testdata.SampleInvalidDID)
  2288  				require.NoError(t, e)
  2289  
  2290  				return &did.DocResolution{DIDDocument: d}, nil
  2291  			} else if strings.HasPrefix(didID, "did:key:") {
  2292  				k := key.New()
  2293  
  2294  				d, e := k.Read(didID)
  2295  				if e != nil {
  2296  					return nil, e
  2297  				}
  2298  
  2299  				return d, nil
  2300  			}
  2301  
  2302  			return nil, fmt.Errorf("did not found")
  2303  		},
  2304  	}
  2305  
  2306  	sampleCrypto, err := tinkcrypto.New()
  2307  	require.NoError(t, err)
  2308  
  2309  	mockctx := newMockProvider(t)
  2310  	mockctx.VDRegistryValue = customVDR
  2311  	mockctx.CryptoValue = sampleCrypto
  2312  
  2313  	err = CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  2314  	require.NoError(t, err)
  2315  
  2316  	walletForIssue, err := New(user, mockctx)
  2317  	require.NoError(t, err)
  2318  
  2319  	tkn, err := walletForIssue.Open(WithUnlockByPassphrase(samplePassPhrase))
  2320  	require.NoError(t, err)
  2321  	require.NotEmpty(t, tkn)
  2322  
  2323  	// import keys manually
  2324  	session, err := sessionManager().getSession(tkn)
  2325  	require.NotEmpty(t, session)
  2326  	require.NoError(t, err)
  2327  
  2328  	kmgr := session.KeyManager
  2329  	require.NotEmpty(t, kmgr)
  2330  
  2331  	edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2332  	// nolint: errcheck, gosec
  2333  	kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2334  
  2335  	// issue a credential
  2336  	sampleVC, err := walletForIssue.Issue(tkn, testdata.SampleUDCVC, &ProofOptions{
  2337  		Controller: didKey,
  2338  	})
  2339  	require.NoError(t, err)
  2340  	require.NotEmpty(t, sampleVC)
  2341  	require.Len(t, sampleVC.Proofs, 1)
  2342  
  2343  	templateCred, err := verifiable.ParseCredential(testdata.SampleUDCVC, verifiable.WithDisabledProofCheck(),
  2344  		verifiable.WithJSONLDDocumentLoader(walletForIssue.jsonldDocumentLoader))
  2345  	require.NoError(t, err)
  2346  
  2347  	templateCred.Issuer.ID = didKey
  2348  
  2349  	templateData, err := templateCred.MarshalJSON()
  2350  	require.NoError(t, err)
  2351  
  2352  	// issue a JWT credential
  2353  	sampleJWTVC, err := walletForIssue.Issue(tkn, templateData, &ProofOptions{
  2354  		Controller:         didKey,
  2355  		VerificationMethod: sampleVerificationMethod,
  2356  		ProofFormat:        ExternalJWTProofFormat,
  2357  	})
  2358  	require.NoError(t, err)
  2359  	require.NotEmpty(t, sampleJWTVC)
  2360  	require.NotEqual(t, "", sampleJWTVC.JWT)
  2361  	require.True(t, jwt.IsJWS(sampleJWTVC.JWT))
  2362  
  2363  	// present a credential
  2364  	sampleVP, err := walletForIssue.Prove(tkn, &ProofOptions{Controller: didKey},
  2365  		WithCredentialsToProve(sampleVC))
  2366  	require.NoError(t, err)
  2367  	require.NotEmpty(t, sampleVP)
  2368  	require.Len(t, sampleVP.Proofs, 1)
  2369  
  2370  	// present a tampered credential
  2371  	invalidVC := *sampleVC
  2372  	invalidVC.Issuer.ID += "."
  2373  	sampleInvalidVP, err := walletForIssue.Prove(tkn, &ProofOptions{Controller: didKey},
  2374  		WithCredentialsToProve(&invalidVC))
  2375  	require.NoError(t, err)
  2376  	require.NotEmpty(t, sampleInvalidVP)
  2377  	require.Len(t, sampleInvalidVP.Proofs, 1)
  2378  
  2379  	require.True(t, walletForIssue.Close())
  2380  
  2381  	t.Run("Test VC wallet verifying a credential - success", func(t *testing.T) {
  2382  		walletInstance, err := New(user, mockctx)
  2383  		require.NotEmpty(t, walletInstance)
  2384  		require.NoError(t, err)
  2385  
  2386  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2387  		require.NoError(t, err)
  2388  		require.NotEmpty(t, tkn)
  2389  
  2390  		// save it in store
  2391  		vcBytes, err := sampleVC.MarshalJSON()
  2392  		require.NoError(t, err)
  2393  		require.NoError(t, walletInstance.Add(tkn, Credential, vcBytes))
  2394  
  2395  		// verify stored credential
  2396  		ok, err := walletInstance.Verify(tkn, WithStoredCredentialToVerify(sampleVC.ID))
  2397  		require.NoError(t, err)
  2398  		require.True(t, ok)
  2399  
  2400  		// verify raw credential
  2401  		rawBytes, err := sampleVC.MarshalJSON()
  2402  		require.NoError(t, err)
  2403  		ok, err = walletInstance.Verify(tkn, WithRawCredentialToVerify(rawBytes))
  2404  		require.NoError(t, err)
  2405  		require.True(t, ok)
  2406  
  2407  		require.NoError(t, walletInstance.Remove(tkn, Credential, "http://example.edu/credentials/1872"))
  2408  
  2409  		// verify JWT Credential object
  2410  		jwtBytes, err := sampleJWTVC.MarshalJSON()
  2411  		require.NoError(t, err)
  2412  		ok, err = walletInstance.Verify(tkn, WithRawCredentialToVerify(jwtBytes))
  2413  		require.NoError(t, err)
  2414  		require.True(t, ok)
  2415  
  2416  		// verify raw JWT credential
  2417  		ok, err = walletInstance.Verify(tkn, WithRawCredentialToVerify([]byte(sampleJWTVC.JWT)))
  2418  		require.NoError(t, err)
  2419  		require.True(t, ok)
  2420  
  2421  		require.True(t, walletInstance.Close())
  2422  	})
  2423  
  2424  	t.Run("Test VC wallet verifying a presentation - success", func(t *testing.T) {
  2425  		walletInstance, err := New(user, mockctx)
  2426  		require.NotEmpty(t, walletInstance)
  2427  		require.NoError(t, err)
  2428  
  2429  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2430  		require.NoError(t, err)
  2431  		require.NotEmpty(t, tkn)
  2432  
  2433  		// verify a raw presentation
  2434  		rawBytes, err := sampleVP.MarshalJSON()
  2435  		require.NoError(t, err)
  2436  		ok, err := walletInstance.Verify(tkn, WithRawPresentationToVerify(rawBytes))
  2437  		require.NoError(t, err)
  2438  		require.True(t, ok)
  2439  
  2440  		require.True(t, walletInstance.Close())
  2441  	})
  2442  
  2443  	t.Run("Test VC wallet verifying a credential - invalid signature", func(t *testing.T) {
  2444  		walletInstance, err := New(user, mockctx)
  2445  		require.NotEmpty(t, walletInstance)
  2446  		require.NoError(t, err)
  2447  
  2448  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2449  		require.NoError(t, err)
  2450  		require.NotEmpty(t, tkn)
  2451  
  2452  		// save tampered VC in store
  2453  		// save it in store
  2454  		tamperedVC := *sampleVC
  2455  		tamperedVC.Issuer.ID += "."
  2456  		vcBytes, err := tamperedVC.MarshalJSON()
  2457  		require.NoError(t, err)
  2458  		require.NoError(t, walletInstance.Add(tkn, Credential, vcBytes))
  2459  
  2460  		ok, err := walletInstance.Verify(tkn, WithStoredCredentialToVerify("http://example.edu/credentials/1872"))
  2461  		require.Error(t, err)
  2462  		require.Contains(t, err.Error(), "invalid signature")
  2463  		require.False(t, ok)
  2464  
  2465  		// verify raw credential
  2466  		rawBytes, err := tamperedVC.MarshalJSON()
  2467  		require.NoError(t, err)
  2468  		ok, err = walletInstance.Verify(tkn, WithRawCredentialToVerify(rawBytes))
  2469  		require.Contains(t, err.Error(), "invalid signature")
  2470  		require.False(t, ok)
  2471  
  2472  		require.True(t, walletInstance.Close())
  2473  	})
  2474  
  2475  	t.Run("Test VC wallet verifying a presentation - invalid signature", func(t *testing.T) {
  2476  		walletInstance, err := New(user, mockctx)
  2477  		require.NotEmpty(t, walletInstance)
  2478  		require.NoError(t, err)
  2479  
  2480  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2481  		require.NoError(t, err)
  2482  		require.NotEmpty(t, tkn)
  2483  
  2484  		// verify a raw presentation
  2485  		tamperedVP := *sampleVP
  2486  		tamperedVP.Holder += "."
  2487  		rawBytes, err := tamperedVP.MarshalJSON()
  2488  		require.NoError(t, err)
  2489  		ok, err := walletInstance.Verify(tkn, WithRawPresentationToVerify(rawBytes))
  2490  		require.Contains(t, err.Error(), "invalid signature")
  2491  		require.False(t, ok)
  2492  
  2493  		require.True(t, walletInstance.Close())
  2494  	})
  2495  
  2496  	t.Run("Test VC wallet verifying a presentation - invalid credential signature", func(t *testing.T) {
  2497  		walletInstance, err := New(user, mockctx)
  2498  		require.NotEmpty(t, walletInstance)
  2499  		require.NoError(t, err)
  2500  
  2501  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2502  		require.NoError(t, err)
  2503  		require.NotEmpty(t, tkn)
  2504  
  2505  		// verify a raw presentation
  2506  		rawBytes, err := sampleInvalidVP.MarshalJSON()
  2507  		require.NoError(t, err)
  2508  		ok, err := walletInstance.Verify(tkn, WithRawPresentationToVerify(rawBytes))
  2509  		require.Contains(t, err.Error(), "presentation verification failed: credential verification failed:")
  2510  		require.Contains(t, err.Error(), "invalid signature")
  2511  		require.False(t, ok)
  2512  
  2513  		require.True(t, walletInstance.Close())
  2514  	})
  2515  
  2516  	t.Run("Test VC wallet verifying a credential - invalid credential ID", func(t *testing.T) {
  2517  		walletInstance, err := New(user, mockctx)
  2518  		require.NotEmpty(t, walletInstance)
  2519  		require.NoError(t, err)
  2520  
  2521  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2522  		require.NoError(t, err)
  2523  		require.NotEmpty(t, tkn)
  2524  
  2525  		// verify non existent credential.
  2526  		ok, err := walletInstance.Verify(tkn, WithStoredCredentialToVerify("invalid-ID"))
  2527  		require.Error(t, err)
  2528  		require.Contains(t, err.Error(), "failed to get credential")
  2529  		require.False(t, ok)
  2530  
  2531  		require.True(t, walletInstance.Close())
  2532  	})
  2533  
  2534  	t.Run("Test VC wallet verifying a credential - invalid request", func(t *testing.T) {
  2535  		walletInstance, err := New(user, mockctx)
  2536  		require.NotEmpty(t, walletInstance)
  2537  		require.NoError(t, err)
  2538  
  2539  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2540  		require.NoError(t, err)
  2541  		require.NotEmpty(t, tkn)
  2542  
  2543  		// verify non existent credential.
  2544  		ok, err := walletInstance.Verify(tkn, WithStoredCredentialToVerify(""))
  2545  		require.Error(t, err)
  2546  		require.Contains(t, err.Error(), "invalid verify request")
  2547  		require.False(t, ok)
  2548  
  2549  		require.True(t, walletInstance.Close())
  2550  	})
  2551  }
  2552  
  2553  func TestWallet_Derive(t *testing.T) {
  2554  	user := uuid.New().String()
  2555  	customVDR := &mockvdr.MockVDRegistry{
  2556  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
  2557  			if didID == sampleInvalidDIDID {
  2558  				d, e := did.ParseDocument(testdata.SampleInvalidDID)
  2559  				require.NoError(t, e)
  2560  
  2561  				return &did.DocResolution{DIDDocument: d}, nil
  2562  			} else if strings.HasPrefix(didID, "did:key:") {
  2563  				k := key.New()
  2564  
  2565  				d, e := k.Read(didID)
  2566  				if e != nil {
  2567  					return nil, e
  2568  				}
  2569  
  2570  				return d, nil
  2571  			}
  2572  
  2573  			return nil, fmt.Errorf("did not found")
  2574  		},
  2575  	}
  2576  
  2577  	mockctx := newMockProvider(t)
  2578  	mockctx.VDRegistryValue = customVDR
  2579  
  2580  	customCrypto, err := tinkcrypto.New()
  2581  	require.NoError(t, err)
  2582  
  2583  	mockctx.CryptoValue = customCrypto
  2584  
  2585  	// create profile
  2586  	err = CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  2587  	require.NoError(t, err)
  2588  
  2589  	// prepare VCs for tests
  2590  	vcs := make(map[string]*verifiable.Credential, 2)
  2591  	walletForIssue, err := New(user, mockctx)
  2592  	require.NotEmpty(t, walletForIssue)
  2593  	require.NoError(t, err)
  2594  
  2595  	authToken, err := walletForIssue.Open(WithUnlockByPassphrase(samplePassPhrase))
  2596  	require.NoError(t, err)
  2597  	require.NotEmpty(t, authToken)
  2598  
  2599  	// import ED25519 & BLS12381G2Type keys manually
  2600  	session, err := sessionManager().getSession(authToken)
  2601  	require.NotEmpty(t, session)
  2602  	require.NoError(t, err)
  2603  
  2604  	kmgr := session.KeyManager
  2605  	require.NotEmpty(t, kmgr)
  2606  
  2607  	edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2608  	// nolint: errcheck, gosec
  2609  	kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2610  
  2611  	privKeyBBS, err := bbs12381g2pub.UnmarshalPrivateKey(base58.Decode(pkBBSBase58))
  2612  	require.NoError(t, err)
  2613  	// nolint: errcheck, gosec
  2614  	kmgr.ImportPrivateKey(privKeyBBS, kms.BLS12381G2Type, kms.WithKeyID(keyIDBBS))
  2615  
  2616  	// issue a credential with Ed25519Signature2018
  2617  	result, err := walletForIssue.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  2618  		Controller: didKey,
  2619  	})
  2620  	require.NoError(t, err)
  2621  	require.NotEmpty(t, result)
  2622  	require.Len(t, result.Proofs, 1)
  2623  	vcs["edvc"] = result
  2624  
  2625  	// issue a credential with BbsBlsSignature2020
  2626  	proofRepr := verifiable.SignatureProofValue
  2627  	result, err = walletForIssue.Issue(authToken, testdata.SampleUDCVC, &ProofOptions{
  2628  		Controller:          didKeyBBS,
  2629  		ProofType:           BbsBlsSignature2020,
  2630  		ProofRepresentation: &proofRepr,
  2631  	})
  2632  	require.NoError(t, err)
  2633  	require.NotEmpty(t, result)
  2634  	require.Len(t, result.Proofs, 1)
  2635  	vcs["bbsvc"] = result
  2636  
  2637  	require.True(t, walletForIssue.Close())
  2638  
  2639  	// prepare frame
  2640  	var frameDoc map[string]interface{}
  2641  
  2642  	require.NoError(t, json.Unmarshal(testdata.SampleFrame, &frameDoc))
  2643  
  2644  	t.Run("Test derive a credential from wallet - success", func(t *testing.T) {
  2645  		walletInstance, err := New(user, mockctx)
  2646  		require.NotEmpty(t, walletInstance)
  2647  		require.NoError(t, err)
  2648  
  2649  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2650  		require.NoError(t, err)
  2651  
  2652  		// save BBS VC in store
  2653  		vcBytes, err := vcs["bbsvc"].MarshalJSON()
  2654  		require.NoError(t, err)
  2655  		require.NoError(t, walletInstance.Add(tkn, Credential, vcBytes))
  2656  
  2657  		sampleNonce := uuid.New().String()
  2658  
  2659  		verifyBBSProof := func(proofs []verifiable.Proof) {
  2660  			require.Len(t, proofs, 1)
  2661  			require.NotEmpty(t, proofs[0])
  2662  			require.Equal(t, proofs[0]["type"], "BbsBlsSignatureProof2020")
  2663  			require.NotEmpty(t, proofs[0]["nonce"])
  2664  			require.EqualValues(t, proofs[0]["nonce"], base64.StdEncoding.EncodeToString([]byte(sampleNonce)))
  2665  			require.NotEmpty(t, proofs[0]["proofValue"])
  2666  		}
  2667  
  2668  		// derive stored credential
  2669  		vc, err := walletInstance.Derive(tkn, FromStoredCredential(vcs["bbsvc"].ID), &DeriveOptions{
  2670  			Nonce: sampleNonce,
  2671  			Frame: frameDoc,
  2672  		})
  2673  		require.NoError(t, err)
  2674  		require.NotEmpty(t, vc)
  2675  		verifyBBSProof(vc.Proofs)
  2676  
  2677  		// derive raw credential
  2678  		vc, err = walletInstance.Derive(tkn, FromRawCredential(vcBytes), &DeriveOptions{
  2679  			Nonce: sampleNonce,
  2680  			Frame: frameDoc,
  2681  		})
  2682  		require.NoError(t, err)
  2683  		require.NotEmpty(t, vc)
  2684  		verifyBBSProof(vc.Proofs)
  2685  
  2686  		// derive from credential instance
  2687  		vc, err = walletInstance.Derive(tkn, FromCredential(vcs["bbsvc"]), &DeriveOptions{
  2688  			Nonce: sampleNonce,
  2689  			Frame: frameDoc,
  2690  		})
  2691  		require.NoError(t, err)
  2692  		require.NotEmpty(t, vc)
  2693  		verifyBBSProof(vc.Proofs)
  2694  
  2695  		require.True(t, walletInstance.Close())
  2696  	})
  2697  
  2698  	t.Run("Test derive credential failures", func(t *testing.T) {
  2699  		walletInstance, err := New(user, mockctx)
  2700  		require.NotEmpty(t, walletInstance)
  2701  		require.NoError(t, err)
  2702  
  2703  		tkn, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  2704  		require.NoError(t, err)
  2705  
  2706  		// invalid request
  2707  		vc, err := walletInstance.Derive(tkn, FromStoredCredential(""), &DeriveOptions{})
  2708  		require.Empty(t, vc)
  2709  		require.Error(t, err)
  2710  		require.Contains(t, err.Error(), "invalid request to derive credential")
  2711  
  2712  		// credential not found in store
  2713  		vc, err = walletInstance.Derive(tkn, FromStoredCredential("invalid-id"), &DeriveOptions{})
  2714  		require.Empty(t, vc)
  2715  		require.Error(t, err)
  2716  		require.Contains(t, err.Error(), "data not found")
  2717  
  2718  		// invalid credential in store
  2719  		require.NoError(t, walletInstance.Add(tkn, Credential, []byte(sampleInvalidDIDContent)))
  2720  
  2721  		vc, err = walletInstance.Derive(tkn, FromStoredCredential("did:example:sampleInvalidDIDContent"), &DeriveOptions{})
  2722  		require.Empty(t, vc)
  2723  		require.Error(t, err)
  2724  		require.Contains(t, err.Error(), "credential type of unknown structure")
  2725  
  2726  		// invalid raw credential
  2727  		vc, err = walletInstance.Derive(tkn, FromRawCredential([]byte(sampleInvalidDIDContent)), &DeriveOptions{})
  2728  		require.Empty(t, vc)
  2729  		require.Error(t, err)
  2730  		require.Contains(t, err.Error(), "credential type of unknown structure")
  2731  
  2732  		// invalid raw credential
  2733  		vc, err = walletInstance.Derive(tkn, FromCredential(vcs["bbsvc"]), &DeriveOptions{})
  2734  		require.Empty(t, vc)
  2735  		require.Error(t, err)
  2736  		require.Contains(t, err.Error(), "failed to derive credential")
  2737  
  2738  		// try deriving wrong proof type - no BbsBlsSignature2020 proof present
  2739  		vc, err = walletInstance.Derive(tkn, FromCredential(vcs["edvc"]), &DeriveOptions{
  2740  			Frame: frameDoc,
  2741  		})
  2742  		require.Empty(t, vc)
  2743  		require.Error(t, err)
  2744  		require.Contains(t, err.Error(), "no BbsBlsSignature2020 proof present")
  2745  
  2746  		require.True(t, walletInstance.Close())
  2747  	})
  2748  }
  2749  
  2750  func TestWallet_CreateKeyPair(t *testing.T) {
  2751  	sampleKeyPairUser := uuid.New().String()
  2752  	mockctx := newMockProvider(t)
  2753  	err := CreateProfile(sampleKeyPairUser, mockctx, WithPassphrase(samplePassPhrase))
  2754  	require.NoError(t, err)
  2755  
  2756  	wallet, err := New(sampleKeyPairUser, mockctx)
  2757  	require.NoError(t, err)
  2758  	require.NotEmpty(t, wallet)
  2759  
  2760  	token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase), WithUnlockExpiry(500*time.Millisecond))
  2761  	require.NoError(t, err)
  2762  	require.NotEmpty(t, token)
  2763  
  2764  	defer wallet.Close()
  2765  
  2766  	t.Run("test creating key pair", func(t *testing.T) {
  2767  		keyPair, err := wallet.CreateKeyPair(token, kms.ED25519)
  2768  		require.NoError(t, err)
  2769  		require.NotEmpty(t, keyPair)
  2770  		require.NotEmpty(t, keyPair.KeyID)
  2771  		require.NotEmpty(t, keyPair.PublicKey)
  2772  	})
  2773  
  2774  	t.Run("test creating key pair with invalid auth", func(t *testing.T) {
  2775  		keyPair, err := wallet.CreateKeyPair(sampleFakeTkn, kms.ED25519)
  2776  		require.True(t, errors.Is(err, ErrInvalidAuthToken))
  2777  		require.Empty(t, keyPair)
  2778  	})
  2779  
  2780  	t.Run("test failure while creating key pair", func(t *testing.T) {
  2781  		keyPair, err := wallet.CreateKeyPair(token, kms.KeyType("invalid"))
  2782  		require.Error(t, err)
  2783  		require.Contains(t, err.Error(), "failed to create new key")
  2784  		require.Empty(t, keyPair)
  2785  	})
  2786  }
  2787  
  2788  func TestWallet_ResolveCredentialManifest(t *testing.T) {
  2789  	mockctx := newMockProvider(t)
  2790  	user := uuid.New().String()
  2791  
  2792  	// create a wallet
  2793  	err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  2794  	require.NoError(t, err)
  2795  
  2796  	wallet, err := New(user, mockctx)
  2797  	require.NoError(t, err)
  2798  	require.NotEmpty(t, wallet)
  2799  
  2800  	// get token
  2801  	token, err := wallet.Open(WithUnlockByPassphrase(samplePassPhrase), WithUnlockExpiry(500*time.Millisecond))
  2802  	require.NoError(t, err)
  2803  	require.NotEmpty(t, token)
  2804  
  2805  	responseVP, err := verifiable.ParsePresentation(testdata.CredentialResponseWithMultipleVCs,
  2806  		verifiable.WithPresDisabledProofCheck(),
  2807  		verifiable.WithPresJSONLDDocumentLoader(mockctx.JSONLDDocumentLoader()))
  2808  	require.NoError(t, err)
  2809  
  2810  	vc, err := verifiable.ParseCredential(testdata.SampleUDCVC,
  2811  		verifiable.WithJSONLDDocumentLoader(mockctx.JSONLDDocumentLoader()))
  2812  	require.NoError(t, err)
  2813  
  2814  	require.NoError(t, wallet.Add(token, Credential, testdata.SampleUDCVC))
  2815  
  2816  	t.Run("Test Resolving credential manifests", func(t *testing.T) {
  2817  		testTable := map[string]struct {
  2818  			manifest    []byte
  2819  			resolve     ResolveManifestOption
  2820  			resultCount int
  2821  			error       string
  2822  		}{
  2823  			"testing resolve by raw credential response": {
  2824  				manifest:    testdata.CredentialManifestMultipleVCs,
  2825  				resolve:     ResolveRawResponse(testdata.CredentialResponseWithMultipleVCs),
  2826  				resultCount: 2,
  2827  			},
  2828  			"testing resolve by credential response": {
  2829  				manifest:    testdata.CredentialManifestMultipleVCs,
  2830  				resolve:     ResolveResponse(responseVP),
  2831  				resultCount: 2,
  2832  			},
  2833  			"testing resolve by raw credential": {
  2834  				manifest:    testdata.CredentialManifestMultipleVCs,
  2835  				resolve:     ResolveRawCredential("udc_output", testdata.SampleUDCVC),
  2836  				resultCount: 1,
  2837  			},
  2838  			"testing resolve by raw JWT credential": {
  2839  				manifest:    testdata.CredentialManifestMultipleVCs,
  2840  				resolve:     ResolveRawCredential("udc_output", testdata.SampleUDCJWTVC),
  2841  				resultCount: 1,
  2842  			},
  2843  			"testing resolve by credential": {
  2844  				manifest:    testdata.CredentialManifestMultipleVCs,
  2845  				resolve:     ResolveCredential("udc_output", vc),
  2846  				resultCount: 1,
  2847  			},
  2848  			"testing resolve by credential ID": {
  2849  				manifest:    testdata.CredentialManifestMultipleVCs,
  2850  				resolve:     ResolveCredentialID("udc_output", vc.ID),
  2851  				resultCount: 1,
  2852  			},
  2853  			"testing failure - resolve by empty resolve option": {
  2854  				manifest:    testdata.CredentialManifestMultipleVCs,
  2855  				resolve:     ResolveCredential("udc_output", nil),
  2856  				resultCount: 0,
  2857  				error:       "invalid option",
  2858  			},
  2859  			"testing failure - resolve by invalid raw response": {
  2860  				manifest:    testdata.CredentialManifestMultipleVCs,
  2861  				resolve:     ResolveRawResponse([]byte("{}")),
  2862  				resultCount: 0,
  2863  				error:       "verifiable presentation is not valid",
  2864  			},
  2865  			"testing failure - resolve by invalid raw credential": {
  2866  				manifest:    testdata.CredentialManifestMultipleVCs,
  2867  				resolve:     ResolveRawCredential("", []byte("{}")),
  2868  				resultCount: 0,
  2869  				error:       "credential type of unknown structure",
  2870  			},
  2871  			"testing failure - invalid credential manifest": {
  2872  				manifest:    []byte("{}"),
  2873  				resolve:     ResolveResponse(responseVP),
  2874  				resultCount: 0,
  2875  				error:       "invalid credential manifest",
  2876  			},
  2877  			"testing failure  - resolve raw credential by invalid descriptor ID": {
  2878  				manifest:    testdata.CredentialManifestMultipleVCs,
  2879  				resolve:     ResolveRawCredential("invalid", testdata.SampleUDCVC),
  2880  				resultCount: 0,
  2881  				error:       "unable to find matching descriptor",
  2882  			},
  2883  			"testing failure  - resolve credential by invalid descriptor ID": {
  2884  				manifest:    testdata.CredentialManifestMultipleVCs,
  2885  				resolve:     ResolveCredential("invalid", vc),
  2886  				resultCount: 0,
  2887  				error:       "unable to find matching descriptor",
  2888  			},
  2889  			"testing failure  - resolve credential by invalid credential ID": {
  2890  				manifest:    testdata.CredentialManifestMultipleVCs,
  2891  				resolve:     ResolveCredentialID("udc_output", "incorrect"),
  2892  				resultCount: 0,
  2893  				error:       "failed to get credential to resolve from wallet",
  2894  			},
  2895  		}
  2896  
  2897  		t.Parallel()
  2898  
  2899  		for testName, testData := range testTable {
  2900  			t.Run(testName, func(t *testing.T) {
  2901  				resolved, err := wallet.ResolveCredentialManifest(token, testData.manifest, testData.resolve)
  2902  
  2903  				if testData.error != "" {
  2904  					require.Error(t, err)
  2905  					require.Contains(t, err.Error(), testData.error)
  2906  					require.Len(t, resolved, testData.resultCount)
  2907  
  2908  					return
  2909  				}
  2910  
  2911  				require.NoError(t, err)
  2912  				require.NotEmpty(t, resolved)
  2913  				require.Len(t, resolved, testData.resultCount)
  2914  
  2915  				for _, result := range resolved {
  2916  					require.NotEmpty(t, result.DescriptorID)
  2917  					require.NotEmpty(t, result.Title)
  2918  					require.NotEmpty(t, result.Properties)
  2919  				}
  2920  			})
  2921  		}
  2922  	})
  2923  }
  2924  
  2925  func TestWallet_verifiableClaimsToJWT(t *testing.T) {
  2926  	customVDR := &mockvdr.MockVDRegistry{
  2927  		ResolveFunc: func(didID string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) {
  2928  			if didID == sampleInvalidDIDID {
  2929  				d, e := did.ParseDocument(testdata.SampleInvalidDID)
  2930  				require.NoError(t, e)
  2931  
  2932  				return &did.DocResolution{DIDDocument: d}, nil
  2933  			} else if strings.HasPrefix(didID, "did:key:") {
  2934  				k := key.New()
  2935  
  2936  				d, e := k.Read(didID)
  2937  				if e != nil {
  2938  					return nil, e
  2939  				}
  2940  
  2941  				return d, nil
  2942  			}
  2943  
  2944  			return nil, fmt.Errorf("did not found")
  2945  		},
  2946  	}
  2947  
  2948  	user := uuid.New().String()
  2949  
  2950  	mockctx := newMockProvider(t)
  2951  	mockctx.VDRegistryValue = customVDR
  2952  	mockctx.CryptoValue = &cryptomock.Crypto{}
  2953  
  2954  	err := CreateProfile(user, mockctx, WithPassphrase(samplePassPhrase))
  2955  	require.NoError(t, err)
  2956  
  2957  	t.Run("success", func(t *testing.T) {
  2958  		type keyImporterFunc func(kmgr kms.KeyManager) (string, string, error)
  2959  
  2960  		ecKeyTestCase := func(
  2961  			curve elliptic.Curve,
  2962  			fpCodec uint64,
  2963  			kt kms.KeyType,
  2964  		) keyImporterFunc {
  2965  			return func(kmgr kms.KeyManager) (string, string, error) {
  2966  				priv, err := ecdsa.GenerateKey(curve, rand.Reader)
  2967  				if err != nil {
  2968  					return "", "", err
  2969  				}
  2970  
  2971  				pubKeyBytes := elliptic.MarshalCompressed(priv.Curve, priv.X, priv.Y)
  2972  
  2973  				fp := fingerprint.KeyFingerprint(fpCodec, pubKeyBytes)
  2974  				k, vm := fingerprint.CreateDIDKeyByCode(fpCodec, pubKeyBytes)
  2975  
  2976  				// nolint: errcheck, gosec
  2977  				kmgr.ImportPrivateKey(priv, kt, kms.WithKeyID(fp))
  2978  
  2979  				return k, vm, nil
  2980  			}
  2981  		}
  2982  
  2983  		testCases := []struct {
  2984  			name    string
  2985  			keyFunc keyImporterFunc
  2986  		}{
  2987  			{
  2988  				name: "Ed25519",
  2989  				keyFunc: func(kmgr kms.KeyManager) (string, string, error) {
  2990  					edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  2991  					// nolint: errcheck, gosec
  2992  					kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  2993  
  2994  					return didKey, sampleVerificationMethod, nil
  2995  				},
  2996  			},
  2997  			{
  2998  				name:    "P256",
  2999  				keyFunc: ecKeyTestCase(elliptic.P256(), fingerprint.P256PubKeyMultiCodec, kms.ECDSAP256TypeIEEEP1363),
  3000  			},
  3001  			{
  3002  				name:    "P384",
  3003  				keyFunc: ecKeyTestCase(elliptic.P384(), fingerprint.P384PubKeyMultiCodec, kms.ECDSAP384TypeIEEEP1363),
  3004  			},
  3005  			{
  3006  				name:    "P521",
  3007  				keyFunc: ecKeyTestCase(elliptic.P521(), fingerprint.P521PubKeyMultiCodec, kms.ECDSAP521TypeIEEEP1363),
  3008  			},
  3009  		}
  3010  
  3011  		for _, tc := range testCases {
  3012  			t.Run(tc.name, func(t *testing.T) {
  3013  				walletInstance, err := New(user, mockctx)
  3014  				require.NotEmpty(t, walletInstance)
  3015  				require.NoError(t, err)
  3016  
  3017  				// unlock wallet
  3018  				authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  3019  				require.NoError(t, err)
  3020  				require.NotEmpty(t, authToken)
  3021  
  3022  				defer walletInstance.Close()
  3023  
  3024  				// add private key
  3025  				session, err := sessionManager().getSession(authToken)
  3026  				require.NotEmpty(t, session)
  3027  				require.NoError(t, err)
  3028  
  3029  				kmgr := session.KeyManager
  3030  				require.NotEmpty(t, kmgr)
  3031  
  3032  				k, vm, err := tc.keyFunc(kmgr)
  3033  				require.NoError(t, err)
  3034  
  3035  				_, err = walletInstance.verifiableClaimsToJWT(authToken, &verifiable.JWTCredClaims{}, &ProofOptions{
  3036  					Controller:         k,
  3037  					VerificationMethod: vm,
  3038  				})
  3039  				require.NoError(t, err)
  3040  			})
  3041  		}
  3042  	})
  3043  
  3044  	t.Run("error initializing KMS signer", func(t *testing.T) {
  3045  		walletInstance, err := New(user, mockctx)
  3046  		require.NotEmpty(t, walletInstance)
  3047  		require.NoError(t, err)
  3048  
  3049  		// unlock wallet
  3050  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  3051  		require.NoError(t, err)
  3052  		require.NotEmpty(t, authToken)
  3053  
  3054  		defer walletInstance.Close()
  3055  
  3056  		_, err = walletInstance.verifiableClaimsToJWT(authToken, nil, &ProofOptions{})
  3057  		require.Error(t, err)
  3058  		require.Contains(t, err.Error(), "initializing signer")
  3059  	})
  3060  
  3061  	t.Run("unsupported keytype", func(t *testing.T) {
  3062  		walletInstance, err := New(user, mockctx)
  3063  		require.NotEmpty(t, walletInstance)
  3064  		require.NoError(t, err)
  3065  
  3066  		// unlock wallet
  3067  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  3068  		require.NoError(t, err)
  3069  		require.NotEmpty(t, authToken)
  3070  
  3071  		defer walletInstance.Close()
  3072  
  3073  		// add private key
  3074  		session, err := sessionManager().getSession(authToken)
  3075  		require.NotEmpty(t, session)
  3076  		require.NoError(t, err)
  3077  
  3078  		kmgr := session.KeyManager
  3079  		require.NotEmpty(t, kmgr)
  3080  
  3081  		privKeyBBS, err := bbs12381g2pub.UnmarshalPrivateKey(base58.Decode(pkBBSBase58))
  3082  		require.NoError(t, err)
  3083  		// nolint: errcheck, gosec
  3084  		kmgr.ImportPrivateKey(privKeyBBS, kms.BLS12381G2Type, kms.WithKeyID(keyIDBBS))
  3085  
  3086  		_, err = walletInstance.verifiableClaimsToJWT(authToken, &verifiable.JWTCredClaims{}, &ProofOptions{
  3087  			Controller:         didKeyBBS,
  3088  			VerificationMethod: didKeyBBS + "#" + keyIDBBS,
  3089  		})
  3090  		require.Error(t, err)
  3091  		require.Contains(t, err.Error(), "unsupported keytype for JWT")
  3092  	})
  3093  
  3094  	t.Run("fail to sign", func(t *testing.T) {
  3095  		walletInstance, err := New(user, mockctx)
  3096  		require.NotEmpty(t, walletInstance)
  3097  		require.NoError(t, err)
  3098  
  3099  		expectErr := errors.New("expected error")
  3100  
  3101  		walletInstance.walletCrypto = &cryptomock.Crypto{
  3102  			SignErr: expectErr,
  3103  		}
  3104  
  3105  		// unlock wallet
  3106  		authToken, err := walletInstance.Open(WithUnlockByPassphrase(samplePassPhrase))
  3107  		require.NoError(t, err)
  3108  		require.NotEmpty(t, authToken)
  3109  
  3110  		defer walletInstance.Close()
  3111  
  3112  		// add private key
  3113  		session, err := sessionManager().getSession(authToken)
  3114  		require.NotEmpty(t, session)
  3115  		require.NoError(t, err)
  3116  
  3117  		kmgr := session.KeyManager
  3118  		require.NotEmpty(t, kmgr)
  3119  
  3120  		edPriv := ed25519.PrivateKey(base58.Decode(pkBase58))
  3121  		// nolint: errcheck, gosec
  3122  		kmgr.ImportPrivateKey(edPriv, kms.ED25519, kms.WithKeyID(kid))
  3123  
  3124  		_, err = walletInstance.verifiableClaimsToJWT(authToken, &verifiable.JWTCredClaims{}, &ProofOptions{
  3125  			Controller:         didKey,
  3126  			VerificationMethod: sampleVerificationMethod,
  3127  		})
  3128  		require.Error(t, err)
  3129  		require.ErrorIs(t, err, expectErr)
  3130  		require.Contains(t, err.Error(), "failed to sign JWS")
  3131  	})
  3132  }
  3133  
  3134  func newMockProvider(t *testing.T) *mockprovider.Provider {
  3135  	t.Helper()
  3136  
  3137  	loader, err := ldtestutil.DocumentLoader()
  3138  	require.NoError(t, err)
  3139  
  3140  	return &mockprovider.Provider{
  3141  		StorageProviderValue:              mockstorage.NewMockStoreProvider(),
  3142  		ProtocolStateStorageProviderValue: mockstorage.NewMockStoreProvider(),
  3143  		DocumentLoaderValue:               loader,
  3144  	}
  3145  }
  3146  
  3147  func createSampleProfile(t *testing.T, mockctx *mockprovider.Provider) {
  3148  	err := CreateProfile(sampleUserID, mockctx, WithPassphrase(samplePassPhrase))
  3149  	require.NoError(t, err)
  3150  
  3151  	wallet, err := New(sampleUserID, mockctx)
  3152  	require.NoError(t, err)
  3153  	require.NotEmpty(t, wallet)
  3154  	require.NotEmpty(t, wallet.profile.MasterLockCipher)
  3155  }
  3156  
  3157  // adds credentials to wallet and returns handle for cleanup.
  3158  func addCredentialsToWallet(t *testing.T, walletInstance *Wallet, auth string, vcs ...*verifiable.Credential) func() {
  3159  	for _, vc := range vcs {
  3160  		vcBytes, err := vc.MarshalJSON()
  3161  		require.NoError(t, err)
  3162  		require.NoError(t, walletInstance.Remove(auth, Credential, vc.ID))
  3163  		require.NoError(t, walletInstance.Add(auth, Credential, vcBytes))
  3164  	}
  3165  
  3166  	return func() {
  3167  		for _, vc := range vcs {
  3168  			err := walletInstance.Remove(auth, Credential, vc.ID)
  3169  			if err != nil {
  3170  				t.Logf("failed to cleanup wallet instance store: %s", err)
  3171  			}
  3172  		}
  3173  	}
  3174  }
  3175  
  3176  const testPD = `
  3177  {
  3178    "id": "32f54163-7166-48f1-93d8-ff217bdb0654",
  3179    "input_descriptors": [
  3180      {
  3181        "id": "type",
  3182        "name": "type",
  3183        "purpose": "We can only interact with specific status information for Verifiable Credentials",
  3184        "schema": [
  3185          {
  3186            "uri": "https://www.w3.org/2018/credentials#VerifiableCredential"
  3187          }
  3188        ],
  3189        "constraints": {
  3190          "fields": [
  3191            {
  3192              "path": [
  3193                "$.credentialStatus.type",
  3194                "$.vc.credentialStatus.type"
  3195              ],
  3196              "purpose": "We can only interact with specific status information for Verifiable Credentials",
  3197              "filter": {
  3198                "type": "string",
  3199                "enum": [
  3200                  "StatusList2021Entry",
  3201                  "RevocationList2021Status",
  3202                  "RevocationList2020Status"
  3203                ]
  3204              }
  3205            }
  3206          ]
  3207        }
  3208      },
  3209      {
  3210        "id": "degree",
  3211        "name": "degree",
  3212        "purpose": "We can only hire with bachelor degree.",
  3213        "schema": [
  3214          {
  3215            "uri": "https://www.w3.org/2018/credentials#VerifiableCredential"
  3216          }
  3217        ],
  3218        "constraints": {
  3219          "fields": [
  3220            {
  3221              "path": [
  3222                "$.credentialSubject.degree.type",
  3223                "$.vc.credentialSubject.degree.type"
  3224              ],
  3225              "purpose": "We can only hire with bachelor degree.",
  3226              "filter": {
  3227                "type": "string",
  3228                "const": "BachelorDegree"
  3229              }
  3230            }
  3231          ]
  3232        }
  3233      }
  3234    ]
  3235  }`
  3236  
  3237  //nolint:lll
  3238  const testJSONLD = `
  3239  {
  3240    "@context": [
  3241      "https://www.w3.org/2018/credentials/v1",
  3242      "https://w3id.org/vc/status-list/2021/v1"
  3243    ],
  3244    "credentialStatus": {
  3245      "id": "urn:uuid:1d8e36ae-6334-4bbf-bf33-8df69191b163",
  3246      "statusListCredential": "http://vc-rest-echo.trustbloc.local:8075/issuer/profiles/i_myprofile_cp_p384/credentials/status/1",
  3247      "statusListIndex": "28",
  3248      "statusPurpose": "revocation",
  3249      "type": "StatusList2021Entry"
  3250    },
  3251    "credentialSubject": {
  3252      "id": "did:orb:uAAA:EiBmZDwNdNMN6eh96dTakcdN8EPjmGoLHOijLw-NGY84Yg",
  3253      "identifier": "3a185b8f-078a-4646-8343-76a45c2856a5",
  3254      "name": "Heavy Sour Dilbit"
  3255    },
  3256    "description": "Crude oil stream, produced from diluted bitumen.",
  3257    "id": "urn:uuid:urn:uuid:ec57b5a1-d986-4268-9c55-de23e936aa46",
  3258    "issuanceDate": "2020-05-01T00:45:04.789Z",
  3259    "issuer": {
  3260      "id": "did:orb:uAAA:EiA34UbWMH_0iKQfgcJ1jBPWvQvXZHuxpZ1g13PUw4xysw",
  3261      "name": "i_myprofile_cp_p384"
  3262    },
  3263    "name": "Heavy Sour Dilbit",
  3264    "type": [
  3265      "VerifiableCredential"
  3266    ]
  3267  }`
  3268  
  3269  //nolint:lll
  3270  const testSDJWT = "eyJhbGciOiJFUzM4NCIsImtpZCI6ImRpZDpvcmI6dUFBQTpFaUQ2STdvMHhzUVBCakxsVXhwSC0xM3ptNkZnbXpiQWs5cHhSRlFSdTZDT2J3IzM4MzczODZjLWJiODYtNDExYS05ODljLTZmMzMwZTQ1MzQxNiJ9.eyJpYXQiOjEuNTg0Mzk4MjQ2ZSswOSwiaXNzIjoiZGlkOm9yYjp1QUFBOkVpRDZJN28weHNRUEJqTGxVeHBILTEzem02RmdtemJBazlweFJGUVJ1NkNPYnciLCJqdGkiOiJ1cm46dXVpZDp1cm46dXVpZDpkNmE3NDIyNy1iMzljLTRhOGUtOWI3OS1hNmRiNjE0MWUzNDYiLCJuYmYiOjEuNTg0Mzk4MjQ2ZSswOSwic3ViIjoiZGlkOm9yYjp1QUFBOkVpQm1aRHdOZE5NTjZlaDk2ZFRha2NkTjhFUGptR29MSE9pakx3LU5HWTg0WWciLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL2V4YW1wbGVzL3YxIiwiaHR0cHM6Ly93M2MtY2NnLmdpdGh1Yi5pby92Yy1yZXZvY2F0aW9uLWxpc3QtMjAyMS9jb250ZXh0cy92MS5qc29ubGQiXSwiX3NkX2FsZyI6InNoYS0zODQiLCJjcmVkZW50aWFsU3RhdHVzIjp7ImlkIjoidXJuOnV1aWQ6NDE0YzZlNDUtNTQzZC00NDUyLWEwYzEtMGM3MWRhYjczMGY1Iiwic3RhdHVzTGlzdENyZWRlbnRpYWwiOiJodHRwOi8vdmMtcmVzdC1lY2hvLnRydXN0YmxvYy5sb2NhbDo4MDc1L2lzc3Vlci9wcm9maWxlcy9pX215cHJvZmlsZV91ZF9lczM4NF9zZGp3dC9jcmVkZW50aWFscy9zdGF0dXMvMSIsInN0YXR1c0xpc3RJbmRleCI6IjI3IiwidHlwZSI6IlJldm9jYXRpb25MaXN0MjAyMVN0YXR1cyJ9LCJjcmVkZW50aWFsU3ViamVjdCI6eyJfc2QiOlsiLWEwRmdBU3FEekZMRjg1bXc3WXFGVmh6cmlUaTFVWjV0d2V4d3otczc4ZVhUYWV1YmZ4TjVsRjFmS3FFMkRxbyIsImI2TDR2ZlFMYUNRWkZZTExfT21SeXhSQTcxVkRGMnVPMXZMdTkxbzVmTlV2YlNja0Y4X29fTU53S3RwUHBIWFIiXSwiZGVncmVlIjp7Il9zZCI6WyJZZ0RxNHNkbDdSQ3FOQnI0bTI0REhwS3RCdzZLUUk0OXhkalBWa0hhVm9DZmNtYUJiMkJlTVB4SVMwS2djcjlUIiwiNVg0czdRdkZZR2VzRmRMTjE0VjA3Zy0yUjBHWFZMWTVzNG5RclB1MFNsM3VBZHA4ZVJxTFlnX3dkLU1nLVF0XyJdfSwiaWQiOiJkaWQ6b3JiOnVBQUE6RWlCbVpEd05kTk1ONmVoOTZkVGFrY2ROOEVQam1Hb0xIT2lqTHctTkdZODRZZyJ9LCJpZCI6InVybjp1dWlkOnVybjp1dWlkOmQ2YTc0MjI3LWIzOWMtNGE4ZS05Yjc5LWE2ZGI2MTQxZTM0NiIsImlzc3VhbmNlRGF0ZSI6IjIwMjAtMDMtMTZUMjI6Mzc6MjZaIiwiaXNzdWVyIjp7ImlkIjoiZGlkOm9yYjp1QUFBOkVpRDZJN28weHNRUEJqTGxVeHBILTEzem02RmdtemJBazlweFJGUVJ1NkNPYnciLCJuYW1lIjoiaV9teXByb2ZpbGVfdWRfZXMzODRfc2Rqd3QifSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIlVuaXZlcnNpdHlEZWdyZWVDcmVkZW50aWFsIl19fQ.MGYCMQCQKQuj6IHGMSxsv_Jip3Ne8NkyqDMPcigsOk07LEBa1W9tiv_KdAcSz4LB3hM03dcCMQCiPRF2tJ0QvWXANq6QFLsGQrSLi8UyN57kOXn_WEln_JrN0BkpimA3Cx3d09e4pCU~WyJnSjBJRUxtRFpwQnFkLXJMM3I5NmN3IiwiZGVncmVlIiwiTUlUIl0~WyI2RHdTR3VqVnhCVUdwblhPRlowX0dBIiwidHlwZSIsIkJhY2hlbG9yRGVncmVlIl0~WyJ0d2ZzaXVSM00xNTNCUDB2U2ptWkd3IiwibmFtZSIsIkpheWRlbiBEb2UiXQ~WyI3Q0lzNFNPWGNnYnVjSkZONXFJdDlBIiwic3BvdXNlIiwiZGlkOmV4YW1wbGU6YzI3NmUxMmVjMjFlYmZlYjFmNzEyZWJjNmYxIl0~"