github.com/hyperledger/aries-framework-go@v0.3.2/pkg/wallet/storage.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 //nolint 8 package wallet 9 10 import ( 11 "encoding/json" 12 "errors" 13 "fmt" 14 "net/http" 15 16 "github.com/hyperledger/aries-framework-go/pkg/crypto/webkms" 17 18 "github.com/hyperledger/aries-framework-go/component/storage/edv" 19 20 "github.com/hyperledger/aries-framework-go/pkg/crypto" 21 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 22 "github.com/hyperledger/aries-framework-go/pkg/didcomm/packer" 23 "github.com/hyperledger/aries-framework-go/pkg/doc/jose" 24 "github.com/hyperledger/aries-framework-go/pkg/kms" 25 "github.com/hyperledger/aries-framework-go/spi/storage" 26 ) 27 28 // storageProvider all wallet content storage provider operations. 29 // if profile has EDV settings then call to OpenStore will return EDV store instance by creating new EDV provider. 30 // Otherwise default provider will be used to open store. 31 // (Refer #2745 for more details) 32 type storageProvider struct { 33 profile *profile 34 defaultProvider storage.Provider 35 } 36 37 func newWalletStorageProvider(profile *profile, provider storage.Provider) *storageProvider { 38 return &storageProvider{profile: profile, defaultProvider: provider} 39 } 40 41 // OpenStore opens and returns store and sets store config to provider. 42 // if wallet profile has EDV settings then auth provided will be used to initialize edv storage provider. 43 func (s *storageProvider) OpenStore(keyMgr kms.KeyManager, opts *unlockOpts, config storage.StoreConfiguration) (storage.Store, error) { 44 var provider storage.Provider 45 var err error 46 47 if s.profile.EDVConf != nil { 48 provider, err = createEDVStorageProvider(keyMgr, s.profile, opts) 49 if err != nil { 50 return nil, err 51 } 52 } else { 53 provider = s.defaultProvider 54 } 55 56 store, err := provider.OpenStore(s.profile.ID) 57 if err != nil { 58 return nil, fmt.Errorf("failed to open store : %w", err) 59 } 60 61 err = provider.SetStoreConfig(s.profile.ID, config) 62 if err != nil { 63 e := store.Close() 64 if e != nil { 65 logger.Warnf("failed to close store: %s", e) 66 } 67 68 return nil, fmt.Errorf("failed to set store config: %w", err) 69 } 70 71 return store, nil 72 } 73 74 // TODO (#2815): find a way to allow EDV to be used without importing the edv package, since it causes the main Aries 75 // module to depend on edv 76 func createEDVStorageProvider(keyMgr kms.KeyManager, profile *profile, opts *unlockOpts) (storage.Provider, error) { 77 if profile.EDVConf.EncryptionKeyID == "" || profile.EDVConf.MACKeyID == "" { 78 return nil, errors.New("invalid EDV configuration found in wallet profile, key IDs for encryption and MAC operations are missing") //nolint: lll 79 } 80 81 var err error 82 83 // get crypto 84 var cryptoImpl crypto.Crypto 85 if profile.KeyServerURL != "" { 86 cryptoImpl = webkms.New(profile.KeyServerURL, http.DefaultClient, opts.webkmsOpts...) 87 } else { 88 cryptoImpl, err = tinkcrypto.New() 89 if err != nil { 90 return nil, fmt.Errorf("failed to create crypto: %w", err) 91 } 92 } 93 94 // get jwe encrypter 95 jweEncrypter, err := getJWSEncrypter(profile.EDVConf.EncryptionKeyID, keyMgr, cryptoImpl) 96 if err != nil { 97 return nil, fmt.Errorf("failed to create JWE encrypter: %w", err) 98 } 99 100 // get jwe decrypter 101 jweDecrypter := jose.NewJWEDecrypt(nil, cryptoImpl, keyMgr) 102 103 // get MAC crypto 104 macCrypto, err := getMacCrypto(profile.EDVConf.MACKeyID, keyMgr, cryptoImpl) 105 if err != nil { 106 return nil, fmt.Errorf("failed to create mac crypto: %w", err) 107 } 108 109 var edvOpts []edv.RESTProviderOption 110 if opts != nil { 111 edvOpts = append(edvOpts, opts.edvOpts...) 112 } 113 114 // create EDV provider 115 return edv.NewRESTProvider(profile.EDVConf.ServerURL, profile.EDVConf.VaultID, 116 edv.NewEncryptedFormatter(jweEncrypter, jweDecrypter, macCrypto, edv.WithDeterministicDocumentIDs()), 117 edvOpts...), nil 118 } 119 120 // getJWSEncrypter creates and returns jwe encrypter based on key manager & crypto provided 121 func getJWSEncrypter(kid string, keyMgr kms.KeyManager, cryptoImpl crypto.Crypto) (*jose.JWEEncrypt, error) { 122 pubKeyBytes, _, err := keyMgr.ExportPubKeyBytes(kid) 123 if err != nil { 124 return nil, err 125 } 126 127 ecPubKey := new(crypto.PublicKey) 128 129 ecPubKey.KID = kid 130 131 err = json.Unmarshal(pubKeyBytes, ecPubKey) 132 if err != nil { 133 return nil, fmt.Errorf("failed to unmarshal JWE public key bytes to an EC public key: %w", err) 134 } 135 136 return jose.NewJWEEncrypt(jose.A256GCM, packer.EnvelopeEncodingTypeV2, "", "", nil, 137 []*crypto.PublicKey{ecPubKey}, cryptoImpl) 138 } 139 140 // getMacCrypto creates and returns MAC crypto based on key manager & crypto provided 141 func getMacCrypto(kid string, keyMgr kms.KeyManager, cryptoImpl crypto.Crypto) (*edv.MACCrypto, error) { 142 keyHandle, err := keyMgr.Get(kid) 143 if err != nil { 144 return nil, err 145 } 146 147 return edv.NewMACCrypto(keyHandle, cryptoImpl), nil 148 }