github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/packer/legacy/authcrypt/authcrypt_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package authcrypt 8 9 import ( 10 "crypto/ed25519" 11 "crypto/rand" 12 "encoding/base64" 13 "errors" 14 "fmt" 15 "io" 16 insecurerand "math/rand" 17 "testing" 18 19 "github.com/btcsuite/btcutil/base58" 20 "github.com/stretchr/testify/require" 21 22 "github.com/hyperledger/aries-framework-go/pkg/doc/util/jwkkid" 23 24 cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto" 25 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 26 "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" 27 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 28 "github.com/hyperledger/aries-framework-go/pkg/kms" 29 "github.com/hyperledger/aries-framework-go/pkg/kms/localkms" 30 "github.com/hyperledger/aries-framework-go/pkg/kms/webkms" 31 mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" 32 mockStorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 33 "github.com/hyperledger/aries-framework-go/pkg/secretlock" 34 "github.com/hyperledger/aries-framework-go/pkg/secretlock/noop" 35 "github.com/hyperledger/aries-framework-go/spi/storage" 36 ) 37 38 // failReader wraps a Reader, used for testing different failure checks for encryption tests. 39 // count: count the number of Reads called before the failWriter fails. 40 type failReader struct { 41 count int 42 data io.Reader 43 } 44 45 // newFailReader constructs a failWriter. 46 func newFailReader(numSuccesses int, reader io.Reader) *failReader { 47 fw := failReader{numSuccesses, reader} 48 return &fw 49 } 50 51 // Write will count down a counter, with each call, and fail when the counter is 0 52 // It calls the wrapped Writer until it's time to fail, after which all calls fail. 53 // Note: the wrapped Writer can still return errors. 54 func (fw *failReader) Read(out []byte) (int, error) { 55 if fw.count <= 0 { 56 // panic(fw) 57 return 0, errors.New("mock Reader has failed intentionally") 58 } 59 60 fw.count-- 61 62 return fw.data.Read(out) 63 } 64 65 type provider struct { 66 storeProvider storage.Provider 67 kms kms.KeyManager 68 secretLock secretlock.Service 69 cryptoService cryptoapi.Crypto 70 } 71 72 func (p *provider) StorageProvider() storage.Provider { 73 return p.storeProvider 74 } 75 76 func (p *provider) Crypto() cryptoapi.Crypto { 77 return p.cryptoService 78 } 79 80 type kmsProvider struct { 81 store kms.Store 82 secretLockService secretlock.Service 83 } 84 85 func (k *kmsProvider) StorageProvider() kms.Store { 86 return k.store 87 } 88 89 func (k *kmsProvider) SecretLock() secretlock.Service { 90 return k.secretLockService 91 } 92 93 func newKMS(t *testing.T) (kms.KeyManager, storage.Store) { 94 msp := mockStorage.NewMockStoreProvider() 95 p := &provider{storeProvider: msp, secretLock: &noop.NoLock{}} 96 97 store, err := p.StorageProvider().OpenStore("test-kms") 98 require.NoError(t, err) 99 100 kmsStore, err := kms.NewAriesProviderWrapper(msp) 101 require.NoError(t, err) 102 103 kmsProv := &kmsProvider{ 104 store: kmsStore, 105 secretLockService: &noop.NoLock{}, 106 } 107 108 customKMS, err := localkms.New("local-lock://primary/test/", kmsProv) 109 require.NoError(t, err) 110 111 return customKMS, store 112 } 113 114 func persistKey(t *testing.T, pub, priv string, km kms.KeyManager) error { 115 t.Helper() 116 117 kid, err := jwkkid.CreateKID(base58.Decode(pub), kms.ED25519Type) 118 if err != nil { 119 return err 120 } 121 122 edPriv := ed25519.PrivateKey(base58.Decode(priv)) 123 if len(edPriv) == 0 { 124 return fmt.Errorf("error converting bad public key") 125 } 126 127 k1, _, err := km.ImportPrivateKey(edPriv, kms.ED25519Type, kms.WithKeyID(kid)) 128 require.NoError(t, err) 129 require.Equal(t, kid, k1) 130 131 return nil 132 } 133 134 func (p *provider) KMS() kms.KeyManager { 135 return p.kms 136 } 137 138 func newWithKMSAndCrypto(t *testing.T, k kms.KeyManager) *Packer { 139 c, err := tinkcrypto.New() 140 require.NoError(t, err) 141 142 return New(&provider{ 143 kms: k, 144 cryptoService: c, 145 }) 146 } 147 148 func (p *provider) SecretLock() secretlock.Service { 149 return p.secretLock 150 } 151 152 func (p *provider) VDRegistry() vdrapi.Registry { 153 return nil 154 } 155 156 func createKey(t *testing.T, km kms.KeyManager) []byte { 157 _, key, err := km.CreateAndExportPubKeyBytes(kms.ED25519Type) 158 require.NoError(t, err) 159 160 return key 161 } 162 163 func TestEncodingType(t *testing.T) { 164 testKMS, store := newKMS(t) 165 require.NotEmpty(t, testKMS) 166 167 packer := New(&provider{ 168 storeProvider: mockStorage.NewCustomMockStoreProvider(store), 169 kms: testKMS, 170 }) 171 require.NotEmpty(t, packer) 172 173 require.Equal(t, encodingType, packer.EncodingType()) 174 } 175 176 func TestEncrypt(t *testing.T) { 177 testingKMS, _ := newKMS(t) 178 senderKey := createKey(t, testingKMS) 179 180 t.Run("Failure: pack without any recipients", func(t *testing.T) { 181 packer := newWithKMSAndCrypto(t, testingKMS) 182 require.NotEmpty(t, packer) 183 184 _, err := packer.Pack("", []byte("Test Message"), senderKey, [][]byte{}) 185 require.EqualError(t, err, "empty recipients keys, must have at least one recipient") 186 }) 187 188 t.Run("Failure: pack with an invalid recipient key", func(t *testing.T) { 189 packer := newWithKMSAndCrypto(t, testingKMS) 190 require.NotEmpty(t, packer) 191 192 badKey := "6ZAQ7QpmR9EqhJdwx1jQsjq6nnpehwVqUbhVxiEiYEV7" 193 194 _, err := packer.Pack("", []byte("Test Message"), senderKey, [][]byte{base58.Decode(badKey)}) 195 require.EqualError(t, err, "pack: failed to build recipients: recipients keys are empty") 196 }) 197 198 recipientKey := createKey(t, testingKMS) 199 200 t.Run("Failure: pack with an invalid-size sender key", func(t *testing.T) { 201 packer := newWithKMSAndCrypto(t, testingKMS) 202 require.NotEmpty(t, packer) 203 204 _, err := packer.Pack("", []byte("Test Message"), []byte{1, 2, 3}, [][]byte{recipientKey}) 205 require.Error(t, err) 206 require.Contains(t, err.Error(), "recipients keys are empty") 207 }) 208 209 t.Run("Success test case: given keys, generate envelope", func(t *testing.T) { 210 packer := newWithKMSAndCrypto(t, testingKMS) 211 require.NotEmpty(t, packer) 212 213 enc, e := packer.Pack("", []byte("Pack my box with five dozen liquor jugs!"), 214 senderKey, [][]byte{recipientKey}) 215 require.NoError(t, e) 216 require.NotEmpty(t, enc) 217 }) 218 219 t.Run("Generate testcase with multiple recipients", func(t *testing.T) { 220 senderKey1 := createKey(t, testingKMS) 221 rec1Key := createKey(t, testingKMS) 222 rec2Key := createKey(t, testingKMS) 223 rec3Key := createKey(t, testingKMS) 224 rec4Key := createKey(t, testingKMS) 225 226 recipientKeys := [][]byte{rec1Key, rec2Key, rec3Key, rec4Key} 227 packer := newWithKMSAndCrypto(t, testingKMS) 228 require.NotEmpty(t, packer) 229 230 enc, err := packer.Pack("", []byte("God! a red nugget! A fat egg under a dog!"), senderKey1, recipientKeys) 231 require.NoError(t, err) 232 require.NotEmpty(t, enc) 233 }) 234 235 t.Run("Pack empty payload using deterministic random source, verify result", func(t *testing.T) { 236 senderPub := "4SPtrDH1ZH8Zsh6upbUG3TbgXjYbW1CEBRnNY6iMudX9" 237 senderPriv := "5MF9crszXCvzh9tWUWQwAuydh6tY2J5ErsaebwRzTsbNXx74mfaJXaKq7oTkoN4VMc2RtKktjMpPoU7vti9UnrdZ" 238 239 recipientPub := "CP1eVoFxCguQe1ttDbS3L35ZiJckZ8PZykX1SCDNgEYZ" 240 recipientPriv := "5aFcdEMws6ZUL7tWYrJ6DsZvY2GHZYui1jLcYquGr8uHfmyHCs96QU3nRUarH1gVYnMU2i4uUPV5STh2mX7EHpNu" 241 242 kms2, _ := newKMS(t) 243 require.NoError(t, persistKey(t, senderPub, senderPriv, kms2)) 244 require.NoError(t, persistKey(t, recipientPub, recipientPriv, kms2)) 245 246 source := insecurerand.NewSource(5937493) // constant fixed to ensure constant output 247 constRand := insecurerand.New(source) //nolint:gosec 248 249 packer := newWithKMSAndCrypto(t, kms2) 250 require.NotEmpty(t, packer) 251 packer.randSource = constRand 252 enc, err := packer.Pack("", nil, base58.Decode(senderPub), [][]byte{base58.Decode(recipientPub)}) 253 require.NoError(t, err) 254 255 test := "eyJwcm90ZWN0ZWQiOiJleUpsYm1NaU9pSmphR0ZqYUdFeU1IQnZiSGt4TXpBMVgybGxkR1lpTENKMGVYQWlPaUpLVjAwdk1TNHdJaXdpWVd4bklqb2lRWFYwYUdOeWVYQjBJaXdpY21WamFYQnBaVzUwY3lJNlczc2laVzVqY25sd2RHVmtYMnRsZVNJNklqSmlVRFl0VnpaWldXZHpjMlZpVWxOaU0xWlljV0pMTlZWa2FpMDNOSGxGTTFFdFZXaHpjMUF3Vm1aclRHNVhiMFk0WjBSNVVHRkJlREI0VWtGM2NIVWlMQ0pvWldGa1pYSWlPbnNpYTJsa0lqb2lRMUF4WlZadlJuaERaM1ZSWlRGMGRFUmlVek5NTXpWYWFVcGphMW80VUZwNWExZ3hVME5FVG1kRldWb2lMQ0p6Wlc1a1pYSWlPaUpHYzIwMU5WOUNTRkJzVkdsd2RUQlFabEZDY2t0SmRuZ3lTRGw0VTBndFVtbHpXRzgxVVdoemQwTTNjR28yTm5BMVNtOUpVVjlIT1hGdFRrVldNRzVGVG5sTVIwczFlVVZuUzJoeU5ESTBVMnBJYkRWSmQzQnljRnBqYUdGNVprNWtWa2xJTFdKNlprRnhjbXhDWTIxUVZEWkpkR2R4Y3poclRHczlJaXdpYVhZaU9pSm1OV3BVT0VKS2FHeEVZbTQwUWxvMFNGcGZSSEExTkU5TGQyWmxRV1JSTWlKOWZWMTkiLCJpdiI6ImlLZHFxRWpzTktpeW4taGsiLCJ0YWciOiIySm5SbF9iXzM2QS1WaWFKNzNCb1FBPT0ifQ==" // nolint: lll 256 257 require.Equal(t, test, base64.URLEncoding.EncodeToString(enc)) 258 }) 259 260 t.Run("Pack payload using deterministic random source for multiple recipients, verify result", func(t *testing.T) { 261 senderPub := "9NKZ9pHL9YVS7BzqJsz3e9uVvk44rJodKfLKbq4hmeUw" 262 senderPriv := "2VZLugb22G3iovUvGrecKj3VHFUNeCetkApeB4Fn4zkgBqYaMSFTW2nvF395voJ76vHkfnUXH2qvJoJnFydRoQBR" 263 senderKMS, _ := newKMS(t) 264 require.NoError(t, persistKey(t, senderPub, senderPriv, senderKMS)) 265 266 rec1Pub := base58.Decode("DDk4ac2ZA19P8qXjk8XaCY9Fx7WwAmCtELkxeDNqS6Vs") 267 rec2Pub := base58.Decode("G79vtfWgtBG5J7R2QaBQpZfPUQaAab1QJWedWH7q3VK1") 268 rec3Pub := base58.Decode("7snUUwA23DVBmafz9ibmBgwFFCUwzgTzmvcJGepuzjmK") 269 rec4Pub := base58.Decode("GSRovbnQy8HRjVjvzGbbfN387EX9NFfLj89C1ScXYfrF") 270 271 source := insecurerand.NewSource(6572692) // constant fixed to ensure constant output 272 constRand := insecurerand.New(source) //nolint:gosec 273 274 packer := newWithKMSAndCrypto(t, senderKMS) 275 require.NotEmpty(t, packer) 276 packer.randSource = constRand 277 enc, err := packer.Pack( 278 "", 279 []byte("Sphinx of black quartz, judge my vow!"), 280 base58.Decode(senderPub), 281 [][]byte{rec1Pub, rec2Pub, rec3Pub, rec4Pub}) 282 require.NoError(t, err) 283 284 test := "eyJwcm90ZWN0ZWQiOiJleUpsYm1NaU9pSmphR0ZqYUdFeU1IQnZiSGt4TXpBMVgybGxkR1lpTENKMGVYQWlPaUpLVjAwdk1TNHdJaXdpWVd4bklqb2lRWFYwYUdOeWVYQjBJaXdpY21WamFYQnBaVzUwY3lJNlczc2laVzVqY25sd2RHVmtYMnRsZVNJNkltRlliRkl0Umkwd2JEZFZTMU10Vkhwb1MwaGFWMmhIWlMxUU5tbzRlVUYwU2pFeFVEbHlSMU4yVFZGQmNHVnpZbk5wTUVsRE5XVmlVREJoVW5kVFozVWlMQ0pvWldGa1pYSWlPbnNpYTJsa0lqb2lSRVJyTkdGak1scEJNVGxRT0hGWWFtczRXR0ZEV1RsR2VEZFhkMEZ0UTNSRlRHdDRaVVJPY1ZNMlZuTWlMQ0p6Wlc1a1pYSWlPaUk1ZG1oRVdHMXBMWFJVVDBaS1FuRTRXSGhSZUROVmFUVk1SemxIT0ZoRlUxTTBaVjlST0ZCNVFUQlhhR0pCZHkxR2FscFpNVzlRWjJSb1YwOWhPVWRCTlVFd1puSkVVMHBzWm5Nd2VVNDRNVmsxV0V0a1MyUlZOVkJoTlRGdlRuQmFOVlV4VmtKSGQycG1WMmxhU0hOc05DMHhOamhuVG01cGVFazlJaXdpYVhZaU9pSjBUMjlFTW1RMVZrdFdRV2xITlMxNGNqWnFNM1UzTkZWalZUWlVibTlVWHlKOWZTeDdJbVZ1WTNKNWNIUmxaRjlyWlhraU9pSmZZa3RtVUdjM056WnphRmR5TXpWMmVXWm1jV05NZW1oTE1VUlJRV0owWTFaQ1pFVXlNM1ZUVEVGUmRHSkdNVUZMYkRrMmJHcE5WSHBzTmt4d2JuYzBJaXdpYUdWaFpHVnlJanA3SW10cFpDSTZJa2MzT1haMFpsZG5kRUpITlVvM1VqSlJZVUpSY0ZwbVVGVlJZVUZoWWpGUlNsZGxaRmRJTjNFelZrc3hJaXdpYzJWdVpHVnlJam9pVUVWNlZrc3laM1JJU25OcWFuSjVNbEZ3ZG0xYVFXazRSSGRUT1ZrM2RuVkZkakJ3Wm1JdFgyc3pRbmxQUjJoSGRHUmxUMlJUVjJaaVZrazFXRVJuV0UxNFVVWjNNM1prWHpoa2RtUndSMFZDWlZsVlNFbHBRMEZuT0VaNlZqSkNZVkZyWDFCSGRDMUliMjFJVFZoNVp6VTBUbHBCVWtsS2RXNVZQU0lzSW1sMklqb2lVV1ZRU0RRM2FsTkxXVU14Y2pSb1h6QldjMlJJVlRSWU1FZENkME5ZVWtVaWZYMHNleUpsYm1OeWVYQjBaV1JmYTJWNUlqb2lTMVZDU3pWRFIwMU5SR1ZDVkV4dFYwSmZObWQxWVhCSGNWWlZaRUpQTWxFdFkyTkdaVXRHZEZjMWRqZEpUbmhWY1VKa1FWcExlRkpGZWxFMlNEQnpXaUlzSW1obFlXUmxjaUk2ZXlKcmFXUWlPaUkzYzI1VlZYZEJNak5FVmtKdFlXWjZPV2xpYlVKbmQwWkdRMVYzZW1kVWVtMTJZMHBIWlhCMWVtcHRTeUlzSW5ObGJtUmxjaUk2SW1NdFZHRnlTSGgyVW5WTlgybFBTRnBFWkZkbVkwbG1jSGhtYVV3eVdXVlRObk4yYUZKRFRuZGlkMUpxWXpBdFJFZFllbVpTU0RkSVNEaDBOa0ZpYm5SbE1FeG5ZbGd4VGpjelQyMVJUM1ZHVUVkWlQxbFdiRGw2YTFCSlprdzNMWGh4YmtKRVF6Tm5MVkpFU0ZoNlgxSkpSSEp3WWpOVU1VTk9UVDBpTENKcGRpSTZJbGgwYVc5SFUyOWxOR0ZWV1Rac2JYcHNOVkIxWlRkMU9FOWxSMWN4YkVNNEluMTlMSHNpWlc1amNubHdkR1ZrWDJ0bGVTSTZJbEV5Wld4YVQyRktiWFZCYjA5S05GRjJXWE52YVc5R1RsRm9ha2w0UjJSWFZuZHpkV2R3WW05Q1ZucHViVVJHTjB4RFZ6RjNjMUZoTUVwMVpreHFkMjhpTENKb1pXRmtaWElpT25zaWEybGtJam9pUjFOU2IzWmlibEY1T0VoU2FsWnFkbnBIWW1KbVRqTTROMFZZT1U1R1preHFPRGxETVZOaldGbG1ja1lpTENKelpXNWtaWElpT2lKc1NYcGxNR0p3UzJ4cWNuVlRMWGREV21wUWVuWmZRMDAwUW1SdmMweHpNbDlKTUZZeFUxQnZla05uWDA5emNVRTViVEZCUVhoWmVVMXZhVXhvVkUxdU9ERmtPREo2YUd4WmVXVmxVMWxTZVdaSmNUZGFYMTlrTVRNemExcE9Wa054UVdwWFEyRllURmxxVjNoamVIUlNjRFJTYkVwYVlrOUxRVVU5SWl3aWFYWWlPaUpvTUdWTGJtRkZOVXhoWDJKYVpHVkNVR0Z1Vm0wNFpGZFVlRkZEU2xGQ2VpSjlmVjE5IiwiaXYiOiJZb3VDVi1nbGZRaFBhbDc1IiwiY2lwaGVydGV4dCI6Il9jRUNrMDQ3Y2w4Y3dFaUs1UnZLbHZORDJjTlo1bTZBTW9vdlI4MnBpMEhLbzFnZlZBPT0iLCJ0YWciOiJCYWZ4TW1CU2R5bmI0dmxvQ3ptUVNRPT0ifQ==" // nolint: lll 285 286 require.Equal(t, test, base64.URLEncoding.EncodeToString(enc)) 287 }) 288 } 289 290 func TestEncryptComponents(t *testing.T) { 291 senderPub := "9NKZ9pHL9YVS7BzqJsz3e9uVvk44rJodKfLKbq4hmeUw" 292 senderPriv := "2VZLugb22G3iovUvGrecKj3VHFUNeCetkApeB4Fn4zkgBqYaMSFTW2nvF395voJ76vHkfnUXH2qvJoJnFydRoQBR" 293 rec1Pub := "DDk4ac2ZA19P8qXjk8XaCY9Fx7WwAmCtELkxeDNqS6Vs" 294 295 testKMS, _ := newKMS(t) 296 require.NoError(t, persistKey(t, senderPub, senderPriv, testKMS)) 297 298 packer := newWithKMSAndCrypto(t, testKMS) 299 300 t.Run("Failure: content encryption nonce generation fails", func(t *testing.T) { 301 failRand := newFailReader(0, rand.Reader) 302 packer.randSource = failRand 303 304 _, err := packer.Pack( 305 "", 306 []byte("Lorem Ipsum Dolor Sit Amet Consectetur Adispici Elit"), 307 base58.Decode(senderPub), [][]byte{base58.Decode(rec1Pub)}) 308 require.EqualError(t, err, "pack: failed to generate random nonce: mock Reader has failed intentionally") 309 }) 310 311 t.Run("Failure: CEK generation fails", func(t *testing.T) { 312 failRand := newFailReader(1, rand.Reader) 313 packer.randSource = failRand 314 315 _, err := packer.Pack( 316 "", 317 []byte("Lorem Ipsum Dolor Sit Amet Consectetur Adispici Elit"), 318 base58.Decode(senderPub), [][]byte{base58.Decode(rec1Pub)}) 319 require.EqualError(t, err, "pack: failed to generate cek: mock Reader has failed intentionally") 320 }) 321 322 t.Run("Failure: recipient nonce generation fails", func(t *testing.T) { 323 failRand := newFailReader(2, rand.Reader) 324 packer.randSource = failRand 325 326 _, err := packer.Pack( 327 "", []byte( 328 "Lorem Ipsum Dolor Sit Amet Consectetur Adispici Elit"), 329 base58.Decode(senderPub), [][]byte{base58.Decode(rec1Pub)}) 330 require.EqualError(t, err, "pack: failed to build recipients: recipients keys are empty") 331 }) 332 333 t.Run("Failure: recipient sodiumBoxSeal nonce generation fails", func(t *testing.T) { 334 failRand := newFailReader(3, rand.Reader) 335 packer.randSource = failRand 336 337 _, err := packer.Pack( 338 "", 339 []byte("Lorem Ipsum Dolor Sit Amet Consectetur Adispici Elit"), 340 base58.Decode(senderPub), [][]byte{base58.Decode(rec1Pub)}) 341 require.EqualError(t, err, "pack: failed to build recipients: recipients keys are empty") 342 }) 343 344 t.Run("Success: 4 reads necessary for pack", func(t *testing.T) { 345 failRand := newFailReader(4, rand.Reader) 346 packer.randSource = failRand 347 348 _, err := packer.Pack( 349 "", 350 []byte("Lorem Ipsum Dolor Sit Amet Consectetur Adispici Elit"), 351 base58.Decode(senderPub), [][]byte{base58.Decode(rec1Pub)}) 352 require.NoError(t, err) 353 }) 354 355 packer2 := newWithKMSAndCrypto(t, testKMS) 356 357 t.Run("Failure: generate recipient header with bad sender key", func(t *testing.T) { 358 _, err := packer2.buildRecipient(&[32]byte{}, []byte(""), base58.Decode(rec1Pub)) 359 require.EqualError(t, err, "buildRecipient: failed to create KID for public key: createKID: "+ 360 "empty key") 361 }) 362 363 t.Run("Failure: generate recipient header with bad recipient key", func(t *testing.T) { 364 _, err := packer2.buildRecipient(&[32]byte{}, base58.Decode(senderPub), base58.Decode("AAAA")) 365 require.EqualError(t, err, "buildRecipient: failed to convert public Ed25519 to Curve25519: "+ 366 "3-byte key size is invalid") 367 }) 368 } 369 370 func TestDecrypt(t *testing.T) { 371 testingKMS, _ := newKMS(t) 372 _, senderKey, err := testingKMS.CreateAndExportPubKeyBytes(kms.ED25519Type) 373 require.NoError(t, err) 374 375 _, recKey, err := testingKMS.CreateAndExportPubKeyBytes(kms.ED25519Type) 376 require.NoError(t, err) 377 378 t.Run("Success: pack then unpack, same packer", func(t *testing.T) { 379 packer := newWithKMSAndCrypto(t, testingKMS) 380 msgIn := []byte("Junky qoph-flags vext crwd zimb.") 381 382 var ( 383 enc []byte 384 env *transport.Envelope 385 ) 386 387 enc, err = packer.Pack("", msgIn, senderKey, [][]byte{recKey}) 388 require.NoError(t, err) 389 env, err = packer.Unpack(enc) 390 require.NoError(t, err) 391 392 require.ElementsMatch(t, msgIn, env.Message) 393 require.Equal(t, senderKey, env.FromKey) 394 require.Equal(t, recKey, env.ToKey) 395 }) 396 397 t.Run("Success: pack and unpack, different packers, including fail recipient who wasn't sent the message", func(t *testing.T) { // nolint: lll 398 rec1KMS, _ := newKMS(t) 399 rec1Key := createKey(t, rec1KMS) 400 401 rec2KMS, _ := newKMS(t) 402 rec2Key := createKey(t, rec2KMS) 403 404 rec3KMS, _ := newKMS(t) 405 rec3Key := createKey(t, rec3KMS) 406 407 require.NoError(t, err) 408 409 sendPacker := newWithKMSAndCrypto(t, testingKMS) 410 rec2Packer := newWithKMSAndCrypto(t, rec2KMS) 411 412 msgIn := []byte("Junky qoph-flags vext crwd zimb.") 413 414 var ( 415 enc []byte 416 env *transport.Envelope 417 ) 418 419 enc, err = sendPacker.Pack("", msgIn, senderKey, [][]byte{rec1Key, rec2Key, rec3Key}) 420 require.NoError(t, err) 421 env, err = rec2Packer.Unpack(enc) 422 require.NoError(t, err) 423 require.ElementsMatch(t, msgIn, env.Message) 424 require.Equal(t, senderKey, env.FromKey) 425 require.Equal(t, rec2Key, env.ToKey) 426 427 emptyKMS, _ := newKMS(t) 428 rec4Packer := newWithKMSAndCrypto(t, emptyKMS) 429 430 _, err = rec4Packer.Unpack(enc) 431 require.NotNil(t, err) 432 require.Contains(t, err.Error(), "no key accessible") 433 }) 434 435 t.Run("Test unpacking python envelope", func(t *testing.T) { 436 env := `{"protected": "eyJlbmMiOiAieGNoYWNoYTIwcG9seTEzMDVfaWV0ZiIsICJ0eXAiOiAiSldNLzEuMCIsICJhbGciOiAiQXV0aGNyeXB0IiwgInJlY2lwaWVudHMiOiBbeyJlbmNyeXB0ZWRfa2V5IjogIkVhTVl4b3RKYjg4Vmt2ZmxNN1htajdFUzdvVVVSOEJSWWZ1akJGS1FGT3Y4Q2o3c0F2RndVWE5QdWVWanZ0SkEiLCAiaGVhZGVyIjogeyJraWQiOiAiRjdtTnRGMmZyTHVSdTJjTUVqWEJuV2RZY1RaQVhOUDlqRWtwclh4aWFaaTEiLCAic2VuZGVyIjogInJna1lWLUlxTWxlQUNkdE1qYXE4YnpwQXBKLXlRbjdWdzRIUnFZODNJVFozNzJkc0Y5RzV6bTVKMGhyNDVuSzBnS2JUYzRRYk5VZ1NreUExUlpZbEl6WHBwanN5eGdZUkU5ek9IbUFDcF9ldWZzejZ4YUxFOVRxN01KVT0iLCAiaXYiOiAiQ04wZWd4TFM2R19oUThDVXBjZkdZWmxzNjFtMm9YUVQifX1dfQ==", "iv": "Y4osZIg1IWaa1kFb", "ciphertext": "m9otQmcqYHOxZh4XfLbdCNouqnuPz7lGtcL5ga_1PZcPZDrhnGWPyLW2rPN2lRTftyYGPPT3tOlu4GFecZIz4zXI9kdz", "tag": "CoV9tCdrFnBbVe2h-pYyhQ=="}` // nolint: lll 437 438 msg := "Yvgu yrf vy jgbuffi tvjc hgsj fhlusfm hsuf tiw fun s kb si kfuh bssnc" 439 440 recPub := "F7mNtF2frLuRu2cMEjXBnWdYcTZAXNP9jEkprXxiaZi1" 441 recPriv := "2nYsWTQ1ZguQ7G2HYfMWjMNqWagBQfaKB9GLbsFk7Z7tKVBEr2arwpVKDwgLUbaxguUzQuf7o67aWKzgtHmKaypM" 442 443 recKMS, _ := newKMS(t) 444 require.NoError(t, persistKey(t, recPub, recPriv, recKMS)) 445 446 recPacker := newWithKMSAndCrypto(t, recKMS) 447 448 var envOut *transport.Envelope 449 envOut, err = recPacker.Unpack([]byte(env)) 450 require.NoError(t, err) 451 require.ElementsMatch(t, []byte(msg), envOut.Message) 452 require.NotEmpty(t, envOut.FromKey) 453 require.NotEmpty(t, envOut.ToKey) 454 require.Equal(t, recPub, base58.Encode(envOut.ToKey)) 455 }) 456 457 t.Run("Test unpacking python envelope with multiple recipients", func(t *testing.T) { 458 env := `{"protected": "eyJlbmMiOiAieGNoYWNoYTIwcG9seTEzMDVfaWV0ZiIsICJ0eXAiOiAiSldNLzEuMCIsICJhbGciOiAiQXV0aGNyeXB0IiwgInJlY2lwaWVudHMiOiBbeyJlbmNyeXB0ZWRfa2V5IjogImd4X3NySTljSEtNTEJnaktNOTlybUx3alFZUjJxVTdMOXc0QWo3Z1lTbDJvUTRubE5WN2tZSmJ0bVFlaWVueE8iLCAiaGVhZGVyIjogeyJraWQiOiAiQ2ZGUmluZDh0eGYxOHJmVHl1aE1pZ2t4UVBhbVNUb3hVM2prdW5ldjR5dnUiLCAic2VuZGVyIjogImFWRW03ak5Kajg2Zm9NM0VYaXZjYWpOWlFnN3pGUm0wTnk5ZzdZTzFueUpvblI2bmNVaV9EZWZzWVBHa25KcG1ZbFhuRDIzVU5nLXNBN1lWUnh5WW15aFZBSm5XNWZwdjBuNE5jaFdBTjl5S3pIMTd3NjZQLVV2WjVDcz0iLCAiaXYiOiAieVB0NGhHZVpObWFLN0hMMGtoWjhreFJzQjc3c3BOX2UifX0sIHsiZW5jcnlwdGVkX2tleSI6ICJ3a3RrWjY3VDR4R2NjTW1GZnRIRmNEV2FZMVQxRFQ3YURhMHBPeUpqTHU2REU2UGVKMUhuVXlRWXlOZ2VPR3ExIiwgImhlYWRlciI6IHsia2lkIjogIko1c2hTVlo2QW9DWHFxWWROR2tVdjFDTWZRYWVLRnNGRU4zaFdwNVBLVEN3IiwgInNlbmRlciI6ICJWdEQtakZfZFNDbmVxOUtTcVB0SUtHbHdHb0FzVHB0UkhzMTRYaWhNR0U4LUh4SjU5aVhtSnVLellxTjM2b19ZOWxfYmRFT1pRSjN0R2tRX1BqbTJyQ3VqWkRIbjdDS3Fsd3N4QlNVemYweW43aWliaDFQazJ6R0wyb2M9IiwgIml2IjogIm5acW1CbzBfT2QyTHlXejlHclJJMUlhWlRXUk4zbGVBIn19LCB7ImVuY3J5cHRlZF9rZXkiOiAiUlBsQWtTS1NsdFpGeEFJc1VzbWNiUVVMUTJWWHhRT2kzUEIxelhTbGs3TlBtMkZ2TE9zVDdQSEFHQU5Hem5oNiIsICJoZWFkZXIiOiB7ImtpZCI6ICJCS3ZqbUZFYkMyYjF3YkVycUN4R2syYmdxdkc5dUx3UlU5cWdOS3lINXRURiIsICJzZW5kZXIiOiAiTVhvRXl0NlZULXVFQnFzWEM1SWF1VXdZYXFxakxIYTdWWlF0NGRJX3FBaFZHVWhUTi01c004cXB6TnBnQlpUUHJrazFSMlBnbjlraU4waEpTUXk1T0FmOGdkSE43YXRTVDhUWEtMSHJNdm4wcDcyNUNUd3pZVnZFVnlNPSIsICJpdiI6ICJPb2FTVWgycVdOVk5qWVV6ZnZTNTdCQ1RnY3ZQYVhMeCJ9fSwgeyJlbmNyeXB0ZWRfa2V5IjogImY1cXV2amt1c2l6TmtRcm9HMk51akFsa0NzbllleUF1R1pMWDZmXy1DeG4taUNENjI2akp0aEk4OFBSei1TWWUiLCAiaGVhZGVyIjogeyJraWQiOiAiRWZ3cFR3aFVSU0QzY3lxanNWYlNWU0VMeU4yN250Tlk4V3dhZHNnVUNEOW0iLCAic2VuZGVyIjogImlOMDJNRzllSEpZZmQ3V3pGd1VFeWJBNmFWeU1Ma1JHcXVhYlJGQnJobFU3Q29EMzFHdW5yTWhEWTZETGFJV0FoX2dPMVRLMWtpMzYtTzQ4TlEyZGdOLU1RdS0wZTV5V2dQS1dzV1MtQ2xPbllEQ0RpVkc1VHBJS2dpVT0iLCAiaXYiOiAiZUg0cDZOX0dGNnpzU2trQk5nY0dWN3RRQkxfRl93MS0ifX0sIHsiZW5jcnlwdGVkX2tleSI6ICJqa3FnbHlmUlNWSXZqVnpkZ04wSGN4SGVzMTBoTjE3ckJLejZhcUtlczR3UTRLWGNGYjNpa3pNSmFSWHAwblVSIiwgImhlYWRlciI6IHsia2lkIjogIkFROW5IdExubXVHODFweTY0WUc1Z2VGMnZkNWhRQ0tIaTVNcnFRMUxZQ1hFIiwgInNlbmRlciI6ICJpSXJFOVUyOUVUbTRWa045aFdvYy1UN0dGYjVrdHB4SGtGeWp6d3BLcDJ5MWh2WWQ0NDF0SzdFUXlhTXhHeG9KNklMaWFHNnNpbTF4WS05UHV2Ny03clB4QTFCb3FxMTY0VzJZZU9FRjFwbnBOV2VmYmdTc1dtQUk0QlU9IiwgIml2IjogIm03S2h3THJ1OGtyQ1VXN1BiNTczZWpGblI3Ymlod3lNIn19XX0=", "iv": "1_pOOQhySyaYcVxi", "ciphertext": "CYHrOg1HeNxhUECoRIQRLNAOXwAjagUYf0xLp0Knnj6mEALg8lFbfmoh_oDptJ4El8jVbgDLiBExaEXIxYVnR7DR-hZjxjdbOBQAOAMUYnnvAk0lHJM0KBWlhE0AWrek1JlAfTnq-L6VsCXEqGYHg1uvpBIJicE=", "tag": "l1KfDt-VQIAImCTl7SA2og=="}` // nolint: lll 459 460 msg := "Iiwufh utiweuop fji olioy pio omlim, om kutxrwu gvgbkn kutxr " + 461 "w srt luhsnehim. Igywenomwe fji omwuie fnomhwuie, fjimwef." 462 463 recPub := "AQ9nHtLnmuG81py64YG5geF2vd5hQCKHi5MrqQ1LYCXE" 464 recPriv := "2YbSVZzSVaim41bWDdsBzamrhXrPFKKEpzXZRmgDuoFJco5VQELRSj1oWFR9aRdaufsdUyw8sozTtZuX8Mzsqboz" 465 466 recKMS, _ := newKMS(t) 467 require.NoError(t, persistKey(t, recPub, recPriv, recKMS)) 468 469 recPacker := newWithKMSAndCrypto(t, recKMS) 470 471 var envOut *transport.Envelope 472 envOut, err = recPacker.Unpack([]byte(env)) 473 require.NoError(t, err) 474 require.ElementsMatch(t, []byte(msg), envOut.Message) 475 require.NotEmpty(t, envOut.FromKey) 476 require.NotEmpty(t, envOut.ToKey) 477 require.Equal(t, recPub, base58.Encode(envOut.ToKey)) 478 }) 479 480 t.Run("Test unpacking python envelope with invalid recipient", func(t *testing.T) { 481 env := `{"protected": "eyJlbmMiOiAieGNoYWNoYTIwcG9seTEzMDVfaWV0ZiIsICJ0eXAiOiAiSldNLzEuMCIsICJhbGciOiAiQXV0aGNyeXB0IiwgInJlY2lwaWVudHMiOiBbeyJlbmNyeXB0ZWRfa2V5IjogIjdzN0ZTRXR6Sy1vTzdSWmdISklsSTlzX1lVU2xkMUpnRldPeUNhYUdGY1Y0aHBSTWxQbG0wNDBFcUJXRWVwY3oiLCAiaGVhZGVyIjogeyJraWQiOiAiN0RLbk56TWJHRWNYODYxOGp2WWtiNlhQTFR6eXU2YnhSbTh3RnhZb0d3SHEiLCAic2VuZGVyIjogInFLYTRDeXV1OXZOcmJzX1RCLXhQWXI2aFg2cXJZLTM4Vjd4VXdOQjFyd0J1TjVNTUVJYmRERDFvRElhV2o0QUpSYUZDTEVhSzMtakFSZHBsR1UtM2d4TWY2dkpRZWhiZkZhZHNwemdxRE9iWFZDWUJONGxrVXZLZWhvND0iLCAiaXYiOiAiSWFqeVdudFdSMENxS1BYUWJpWWptbWJRWFNNTEp2X1UifX0sIHsiZW5jcnlwdGVkX2tleSI6ICJZa05vVGh2ZUlIcC13NGlrRW1kQU51VHdxTEx1ZjBocVlVbXRJc2c5WlJMd1BKaUZHWVZuTXl1ZktKZWRvcmthIiwgImhlYWRlciI6IHsia2lkIjogIjdDRURlZUpZTnlRUzhyQjdNVHpvUHhWYXFIWm9ZZkQxNUVIVzhaVVN3VnVhIiwgInNlbmRlciI6ICJ3ZEhjc1hDemdTSjhucDRFU0pDcmJ5OWNrNjJaUEFFVjhJRjYwQmotaUhhbXJLRnBKOTJpZVNTaE1JcTdwdTNmQWZQLWo5S3J6ajAwMEV0SXB5cm05SmNrM0QwSnRBcmtYV2VsSzBoUF9ZeDR4Vlc5dW43MWlfdFBXNWM9IiwgIml2IjogIkRlbUlJbHRKaXd5TU1faGhIS29kcTZpQkx4Q1J5Z2Z3In19XX0=", "iv": "BKWHs6z0UHxGddwg", "ciphertext": "YC2eQQPYVjPHj3wIxUXxBj0yXFLuRN5Lc-9WM8hY6TXoekh-ca9-UWbHasikbcxyukTT3e-QiteOilG-6X7e9x4wiQmWn_NFLOLrqoFe669JIbkgvjHYwuQEQkIVfbD-2woSxsMUl9yln5RS-NssI5cEIVH_C1w=", "tag": "M8GPexbguDoZk5L51AvLjA=="}` // nolint: lll 482 483 recPub := "A3KnccxQu27yWQrSLwA2YFbfoSs4CHo3q6LjvhmpKz9h" 484 recPriv := "49Y63zwonNoj2jEhMYE22TDwQCn7RLKMqNeSkSoBBucbAWceJuXXNCACXfpbXD7PHKM13SWaySyDukEakPVn5sWs" 485 486 recKMS, _ := newKMS(t) 487 require.NoError(t, persistKey(t, recPub, recPriv, recKMS)) 488 489 recPacker := newWithKMSAndCrypto(t, recKMS) 490 491 _, err = recPacker.Unpack([]byte(env)) 492 require.NotNil(t, err) 493 require.Contains(t, err.Error(), "no key accessible") 494 }) 495 } 496 497 func unpackComponentFailureTest(t *testing.T, protectedHeader, msg, recKeyPub, recKeyPriv, errString string) { 498 t.Helper() 499 500 fullMessage := `{"protected": "` + base64.URLEncoding.EncodeToString([]byte(protectedHeader)) + "\", " + msg 501 502 w, _ := newKMS(t) 503 504 err := persistKey(t, recKeyPub, recKeyPriv, w) 505 506 if errString == "createKID: empty key" { 507 require.EqualError(t, err, errString) 508 return 509 } 510 511 require.NoError(t, err) 512 513 recPacker := newWithKMSAndCrypto(t, w) 514 _, err = recPacker.Unpack([]byte(fullMessage)) 515 require.NotNil(t, err) 516 require.Contains(t, err.Error(), errString) 517 } 518 519 func TestUnpackComponents(t *testing.T) { 520 recKeyPub := "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v" 521 recKeyPriv := "5pG8rLcp9WqPXQLSyQetPiyTEnLuanjS2TGd7h4DqutY6gNbLD6pnvT3H8nC5K9vEjy1UJdTtwaejf1xqDyhCrzr" 522 523 t.Run("Fail: non-JSON envelope", func(t *testing.T) { 524 msg := `ed": "eyJlbmMiOiAieGNoYWNoYTIwcG9seTEzMDVfaWV0ZiIsICJ0eXAiOiAiSldNLzEu"}` 525 526 w, _ := newKMS(t) 527 require.NoError(t, persistKey(t, recKeyPub, recKeyPriv, w)) 528 529 recPacker := newWithKMSAndCrypto(t, w) 530 531 _, err := recPacker.Unpack([]byte(msg)) 532 require.EqualError(t, err, "invalid character 'e' looking for beginning of value") 533 }) 534 535 t.Run("Fail: non-base64 protected header", func(t *testing.T) { 536 msg := `{"protected": "&**^(&^%", "iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}` // nolint: lll 537 538 w, _ := newKMS(t) 539 require.NoError(t, persistKey(t, recKeyPub, recKeyPriv, w)) 540 541 recPacker := newWithKMSAndCrypto(t, w) 542 543 _, err := recPacker.Unpack([]byte(msg)) 544 require.EqualError(t, err, "illegal base64 data at input byte 0") 545 }) 546 547 t.Run("Fail: header not json", func(t *testing.T) { 548 unpackComponentFailureTest(t, 549 `}eyJlbmMiOiAieGNoYWNoYTIwcG9seTEzMDVfaWV0ZiIsICJ0eXAiOiAiSldNLzEuMC`, 550 `"not important":[]}`, 551 recKeyPub, recKeyPriv, 552 "invalid character '}' looking for beginning of value") 553 }) 554 555 t.Run("Fail: bad 'typ' field", func(t *testing.T) { 556 unpackComponentFailureTest(t, 557 `{"enc": "xchacha20poly1305_ietf", "typ": "JSON", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 558 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 559 recKeyPub, recKeyPriv, 560 "message type JSON not supported") 561 }) 562 563 t.Run("Fail: anoncrypt not supported", func(t *testing.T) { 564 unpackComponentFailureTest(t, 565 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Anoncrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 566 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, //nolint: lll 567 recKeyPub, recKeyPriv, 568 "message format Anoncrypt not supported") 569 }) 570 571 t.Run("Fail: no recipients in header", func(t *testing.T) { 572 unpackComponentFailureTest(t, 573 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": []}`, 574 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 575 recKeyPub, recKeyPriv, 576 "no key accessible") 577 }) 578 579 t.Run("Fail: invalid public key", func(t *testing.T) { 580 recPub := "6ZAQ7QpmR9EqhJdwx1jQsjq6nnpehwVqUbhVxiEiYEV7" // invalid key, won't convert 581 582 unpackComponentFailureTest(t, 583 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "6ZAQ7QpmR9EqhJdwx1jQsjq6nnpehwVqUbhVxiEiYEV7", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 584 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 585 recPub, recKeyPriv, 586 "sealOpen: failed to convert pub Ed25519 to X25519 key: error converting public key") 587 }) 588 589 t.Run("Fail: invalid public key", func(t *testing.T) { 590 recPub := "57N4aoQKaxUGNeEn3ETnTKgeD1L5Wm3U3Vb8qi3hupLn" // mismatched keypair, won't decrypt 591 592 unpackComponentFailureTest(t, 593 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "57N4aoQKaxUGNeEn3ETnTKgeD1L5Wm3U3Vb8qi3hupLn", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 594 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 595 recPub, recKeyPriv, 596 "failed to unpack") 597 }) 598 599 t.Run("Sender is invalid base64 data", func(t *testing.T) { 600 unpackComponentFailureTest(t, 601 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "*^&", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 602 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 603 recKeyPub, recKeyPriv, 604 "illegal base64 data at input byte 0") 605 }) 606 607 t.Run("Sender is invalid public key", func(t *testing.T) { 608 unpackComponentFailureTest(t, 609 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "7ZA_k_bM4FRp6jY_LNzv9pjuOh1NbVlbBA-yTjzsc22HnPKPK8_MKUNU1Rlt0woNUNWLZI4ShBD_th14ULmTjggBI8K4A8efTI4efxv5xTYEemj9uVPvvLKs4Go=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 610 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 611 recKeyPub, recKeyPriv, 612 "error converting public key") 613 }) 614 615 t.Run("Message auth fail, protected header has extra whitespace", func(t *testing.T) { 616 unpackComponentFailureTest(t, 617 ` {"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 618 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 619 recKeyPub, recKeyPriv, 620 "chacha20poly1305: message authentication failed") 621 }) 622 623 t.Run("Nonce is invalid base64 data", func(t *testing.T) { 624 unpackComponentFailureTest(t, 625 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "(^_^)"}}]}`, // nolint: lll 626 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 627 recKeyPub, recKeyPriv, 628 "illegal base64 data at input byte 0") 629 }) 630 631 t.Run("Encrypted CEK is invalid base64 data", func(t *testing.T) { 632 unpackComponentFailureTest(t, 633 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "_-", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 634 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 635 recKeyPub, recKeyPriv, 636 "illegal base64 data at input byte 0") 637 }) 638 639 t.Run("Bad encrypted key cannot be decrypted", func(t *testing.T) { 640 unpackComponentFailureTest(t, 641 `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_W", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}`, // nolint: lll 642 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 643 recKeyPub, recKeyPriv, 644 "failed to decrypt CEK") 645 }) 646 647 // valid protected header for envelope being used 648 prot := `{"enc": "xchacha20poly1305_ietf", "typ": "JWM/1.0", "alg": "Authcrypt", "recipients": [{"encrypted_key": "DaZGim_WCyntSdziFgnQanpQlR_tVHzHznGbW-yhTYDVgGuc5nr6J5svu7dQbBg3", "header": {"kid": "Ak528pLhb6DNFrGWY6HjMUjpNV613h2qtAJ47j1FYe8v", "sender": "wZ4cC42eDMeLApmJvJC4INbuKINzdZZECGHpWDgsrmBURPJN_bWOkUV3E6oORN4ILAf_xEuWefS4b_goRycCogkZvTyS1HgvBtx2YO1A2q-a7tp__08Ky4qtSiY=", "iv": "A818WMvddPrZ8mmYqp2iuu8gqoZZC2Hx"}}]}` // nolint: lll 649 650 t.Run("Ciphertext nonce not valid b64 data", func(t *testing.T) { 651 unpackComponentFailureTest(t, 652 prot, 653 `"iv": "!!!!!", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 654 recKeyPub, recKeyPriv, 655 "illegal base64 data at input byte 0") 656 }) 657 658 t.Run("Ciphertext not valid b64 data", func(t *testing.T) { 659 unpackComponentFailureTest(t, 660 prot, `"iv": "oDZpVO648Po3UcoW", "ciphertext": "=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, 661 recKeyPub, recKeyPriv, 662 "illegal base64 data at input byte 0") 663 }) 664 665 t.Run("Ciphertext tag not valid b64 data", func(t *testing.T) { 666 unpackComponentFailureTest(t, 667 prot, 668 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "123"}`, // nolint: lll 669 recKeyPub, recKeyPriv, 670 "illegal base64 data at input byte 0") 671 }) 672 673 badKeyPriv := "badkeyabcdefghijklmnopqrstuvwxyzbadkeyabcdefghijklmnopqrstuvwxyz" 674 badKeyPub := "badkeyabcdefghijklmnopqrstuvwxyz" 675 676 t.Run("Recipient Key not valid key", func(t *testing.T) { 677 unpackComponentFailureTest(t, 678 prot, 679 `"iv": "oDZpVO648Po3UcoW", "ciphertext": "pLrFQ6dND0aB4saHjSklcNTDAvpFPmIvebCis7S6UupzhhPOHwhp6o97_EphsWbwqqHl0HTiT7W9kUqrvd8jcWgx5EATtkx5o3PSyHfsfm9jl0tmKsqu6VG0RML_OokZiFv76ZUZuGMrHKxkCHGytILhlpSwajg=", "tag": "6GigdWnW59aC9Y8jhy76rA=="}`, // nolint: lll 680 badKeyPub, badKeyPriv, 681 "createKID: empty key") 682 }) 683 } 684 685 func Test_getCEK(t *testing.T) { 686 k := mockkms.KeyManager{ 687 GetKeyValue: nil, 688 GetKeyErr: fmt.Errorf("mock error"), 689 } 690 691 recs := []recipient{ 692 { 693 EncryptedKey: "", 694 Header: recipientHeader{ 695 KID: "BADKEY", 696 }, 697 }, 698 } 699 700 _, err := getCEK(recs, &k) 701 require.EqualError(t, err, "getCEK: no key accessible none of the recipient keys were found in kms: "+ 702 "[mock error]") 703 } 704 705 func Test_newCryptoBox(t *testing.T) { 706 _, err := newCryptoBox(&mockkms.KeyManager{}) 707 require.EqualError(t, err, "cannot use parameter argument as KMS") 708 709 _, err = newCryptoBox(&webkms.RemoteKMS{}) 710 require.NoError(t, err) 711 }