github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/jose/encrypter_decrypter_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package jose_test 8 9 import ( 10 "bytes" 11 "crypto/ecdsa" 12 "crypto/ed25519" 13 "crypto/rand" 14 "crypto/rsa" 15 _ "embed" 16 "encoding/base64" 17 "encoding/json" 18 "fmt" 19 "math/big" 20 "strings" 21 "testing" 22 "time" 23 24 "github.com/go-jose/go-jose/v3" 25 hybrid "github.com/google/tink/go/hybrid/subtle" 26 "github.com/google/tink/go/keyset" 27 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 28 "github.com/google/tink/go/subtle" 29 "github.com/stretchr/testify/require" 30 31 ecdhpb "github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto" 32 "github.com/hyperledger/aries-framework-go/component/kmscrypto/doc/jose/jwk" 33 "github.com/hyperledger/aries-framework-go/component/kmscrypto/doc/util/jwkkid" 34 cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto" 35 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 36 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh" 37 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/keyio" 38 ariesjose "github.com/hyperledger/aries-framework-go/pkg/doc/jose" 39 "github.com/hyperledger/aries-framework-go/pkg/doc/jose/kid/resolver" 40 "github.com/hyperledger/aries-framework-go/pkg/doc/util/kmsdidkey" 41 "github.com/hyperledger/aries-framework-go/pkg/kms" 42 mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" 43 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 44 ) 45 46 const ( 47 // EnvelopeEncodingType representing the JWE 'Typ' protected type header for DIDComm V2 (example for tests). 48 EnvelopeEncodingType = "application/didcomm-encrypted+json" 49 // DIDCommContentEncodingType represent the JWE `Cty` protected type header for DIDComm V2 (example for tests). 50 DIDCommContentEncodingType = "application/didcomm-plain+json" 51 52 compactSerialization = "Compact" 53 fullSerialization = "Full" 54 flattenedSerialization = "Flattened" 55 ) 56 57 //nolint:gocognit,gocyclo 58 func TestJWEEncryptRoundTrip(t *testing.T) { 59 _, err := ariesjose.NewJWEEncrypt("", "", "", "", nil, nil, nil) 60 require.EqualError(t, err, "empty recipientsPubKeys list", 61 "NewJWEEncrypt should fail with empty recipientPubKeys") 62 63 singleRecipientNISTPKWError := "jwedecrypt: failed to unwrap cek: [unwrapKey: deriveKEKAndUnwrap:" + 64 " failed to AES unwrap key: go-jose/go-jose: key wrap input must be 8 byte blocks]" 65 66 singleRecipientX25519KWError := "jwedecrypt: failed to unwrap cek: [unwrapKey: deriveKEKAndUnwrap: failed to XC20P " + 67 "unwrap key: unwrap support: OKP unwrap invalid key]" 68 69 multiRecKWError := "jwedecrypt: failed to build recipients WK: unable to read " + 70 "JWK: invalid character 's' looking for beginning of value" 71 72 tests := []struct { 73 name string 74 kt *tinkpb.KeyTemplate 75 enc ariesjose.EncAlg 76 keyType kms.KeyType 77 recipientKWError string 78 nbRec int 79 useCompact bool 80 }{ 81 { 82 name: "P-256 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)", 83 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 84 enc: ariesjose.A256GCM, 85 keyType: kms.NISTP256ECDHKWType, 86 nbRec: 2, 87 recipientKWError: multiRecKWError, 88 }, 89 { 90 name: "P-256 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)", 91 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 92 enc: ariesjose.A256GCM, 93 keyType: kms.NISTP256ECDHKWType, 94 nbRec: 1, 95 recipientKWError: singleRecipientNISTPKWError, 96 }, 97 { 98 name: "P-256 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)", 99 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 100 enc: ariesjose.A256GCM, 101 keyType: kms.NISTP256ECDHKWType, 102 nbRec: 1, 103 useCompact: true, 104 recipientKWError: singleRecipientNISTPKWError, 105 }, 106 { 107 name: "P-384 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)", 108 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 109 enc: ariesjose.A256GCM, 110 keyType: kms.NISTP384ECDHKWType, 111 nbRec: 2, 112 recipientKWError: multiRecKWError, 113 }, 114 { 115 name: "P-384 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)", 116 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 117 enc: ariesjose.A256GCM, 118 keyType: kms.NISTP384ECDHKWType, 119 nbRec: 1, 120 recipientKWError: singleRecipientNISTPKWError, 121 }, 122 { 123 name: "P-384 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)", 124 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 125 enc: ariesjose.A256GCM, 126 keyType: kms.NISTP384ECDHKWType, 127 nbRec: 1, 128 useCompact: true, 129 recipientKWError: singleRecipientNISTPKWError, 130 }, 131 { 132 name: "P-521 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)", 133 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 134 enc: ariesjose.A256GCM, 135 keyType: kms.NISTP521ECDHKWType, 136 nbRec: 2, 137 recipientKWError: multiRecKWError, 138 }, 139 { 140 name: "P-521 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)", 141 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 142 enc: ariesjose.A256GCM, 143 keyType: kms.NISTP521ECDHKWType, 144 nbRec: 1, 145 recipientKWError: singleRecipientNISTPKWError, 146 }, 147 { 148 name: "P-521 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)", 149 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 150 enc: ariesjose.A256GCM, 151 keyType: kms.NISTP521ECDHKWType, 152 nbRec: 1, 153 useCompact: true, 154 recipientKWError: singleRecipientNISTPKWError, 155 }, 156 { 157 name: "X25519 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)", 158 kt: ecdh.X25519ECDHKWKeyTemplate(), 159 enc: ariesjose.A256GCM, 160 keyType: kms.X25519ECDHKWType, 161 nbRec: 2, 162 recipientKWError: multiRecKWError, 163 }, 164 { 165 name: "X25519 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)", 166 kt: ecdh.X25519ECDHKWKeyTemplate(), 167 enc: ariesjose.A256GCM, 168 keyType: kms.X25519ECDHKWType, 169 nbRec: 1, 170 recipientKWError: singleRecipientX25519KWError, 171 }, 172 { 173 name: "X25519 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)", 174 kt: ecdh.X25519ECDHKWKeyTemplate(), 175 enc: ariesjose.A256GCM, 176 keyType: kms.X25519ECDHKWType, 177 nbRec: 1, 178 useCompact: true, 179 recipientKWError: singleRecipientX25519KWError, 180 }, 181 { 182 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 183 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 184 enc: ariesjose.XC20P, 185 keyType: kms.NISTP256ECDHKWType, 186 nbRec: 2, 187 recipientKWError: multiRecKWError, 188 }, 189 { 190 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 191 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 192 enc: ariesjose.XC20P, 193 keyType: kms.NISTP256ECDHKWType, 194 nbRec: 1, 195 recipientKWError: singleRecipientNISTPKWError, 196 }, 197 { 198 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 199 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 200 enc: ariesjose.XC20P, 201 keyType: kms.NISTP256ECDHKWType, 202 nbRec: 1, 203 useCompact: true, 204 recipientKWError: singleRecipientNISTPKWError, 205 }, 206 { 207 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 208 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 209 enc: ariesjose.XC20P, 210 keyType: kms.NISTP384ECDHKWType, 211 nbRec: 2, 212 recipientKWError: multiRecKWError, 213 }, 214 { 215 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 216 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 217 enc: ariesjose.XC20P, 218 keyType: kms.NISTP384ECDHKWType, 219 nbRec: 1, 220 recipientKWError: singleRecipientNISTPKWError, 221 }, 222 { 223 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 224 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 225 enc: ariesjose.XC20P, 226 keyType: kms.NISTP384ECDHKWType, 227 nbRec: 1, 228 useCompact: true, 229 recipientKWError: singleRecipientNISTPKWError, 230 }, 231 { 232 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 233 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 234 enc: ariesjose.XC20P, 235 keyType: kms.NISTP521ECDHKWType, 236 nbRec: 2, 237 recipientKWError: multiRecKWError, 238 }, 239 { 240 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 241 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 242 enc: ariesjose.XC20P, 243 keyType: kms.NISTP521ECDHKWType, 244 nbRec: 1, 245 recipientKWError: singleRecipientNISTPKWError, 246 }, 247 { 248 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 249 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 250 enc: ariesjose.XC20P, 251 keyType: kms.NISTP521ECDHKWType, 252 nbRec: 1, 253 useCompact: true, 254 recipientKWError: singleRecipientNISTPKWError, 255 }, 256 { 257 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 258 kt: ecdh.X25519ECDHKWKeyTemplate(), 259 enc: ariesjose.XC20P, 260 keyType: kms.X25519ECDHKWType, 261 nbRec: 2, 262 recipientKWError: multiRecKWError, 263 }, 264 { 265 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 266 kt: ecdh.X25519ECDHKWKeyTemplate(), 267 enc: ariesjose.XC20P, 268 keyType: kms.X25519ECDHKWType, 269 nbRec: 1, 270 recipientKWError: singleRecipientX25519KWError, 271 }, 272 { 273 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 274 kt: ecdh.X25519ECDHKWKeyTemplate(), 275 enc: ariesjose.XC20P, 276 keyType: kms.X25519ECDHKWType, 277 nbRec: 1, 278 useCompact: true, 279 recipientKWError: singleRecipientX25519KWError, 280 }, 281 { 282 name: "P-256 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)", 283 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 284 enc: ariesjose.A128CBCHS256, 285 keyType: kms.NISTP256ECDHKWType, 286 nbRec: 2, 287 recipientKWError: multiRecKWError, 288 }, 289 { 290 name: "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)", 291 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 292 enc: ariesjose.A128CBCHS256, 293 keyType: kms.NISTP256ECDHKWType, 294 nbRec: 1, 295 recipientKWError: singleRecipientNISTPKWError, 296 }, 297 { 298 name: "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)", 299 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 300 enc: ariesjose.A128CBCHS256, 301 keyType: kms.NISTP256ECDHKWType, 302 nbRec: 1, 303 useCompact: true, 304 recipientKWError: singleRecipientNISTPKWError, 305 }, 306 { 307 name: "X25519 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)", 308 kt: ecdh.X25519ECDHKWKeyTemplate(), 309 enc: ariesjose.A128CBCHS256, 310 keyType: kms.X25519ECDHKWType, 311 nbRec: 2, 312 recipientKWError: multiRecKWError, 313 }, 314 { 315 name: "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)", 316 kt: ecdh.X25519ECDHKWKeyTemplate(), 317 enc: ariesjose.A128CBCHS256, 318 keyType: kms.X25519ECDHKWType, 319 nbRec: 1, 320 recipientKWError: singleRecipientX25519KWError, 321 }, 322 { 323 name: "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)", 324 kt: ecdh.X25519ECDHKWKeyTemplate(), 325 enc: ariesjose.A128CBCHS256, 326 keyType: kms.X25519ECDHKWType, 327 nbRec: 1, 328 useCompact: true, 329 recipientKWError: singleRecipientX25519KWError, 330 }, 331 { 332 name: "P-256 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)", 333 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 334 enc: ariesjose.A192CBCHS384, 335 keyType: kms.NISTP256ECDHKWType, 336 nbRec: 2, 337 recipientKWError: multiRecKWError, 338 }, 339 { 340 name: "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)", 341 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 342 enc: ariesjose.A192CBCHS384, 343 keyType: kms.NISTP256ECDHKWType, 344 nbRec: 1, 345 recipientKWError: singleRecipientNISTPKWError, 346 }, 347 { 348 name: "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)", 349 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 350 enc: ariesjose.A192CBCHS384, 351 keyType: kms.NISTP256ECDHKWType, 352 nbRec: 1, 353 useCompact: true, 354 recipientKWError: singleRecipientNISTPKWError, 355 }, 356 { 357 name: "X25519 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)", 358 kt: ecdh.X25519ECDHKWKeyTemplate(), 359 enc: ariesjose.A192CBCHS384, 360 keyType: kms.X25519ECDHKWType, 361 nbRec: 2, 362 recipientKWError: multiRecKWError, 363 }, 364 { 365 name: "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)", 366 kt: ecdh.X25519ECDHKWKeyTemplate(), 367 enc: ariesjose.A192CBCHS384, 368 keyType: kms.X25519ECDHKWType, 369 nbRec: 1, 370 recipientKWError: singleRecipientX25519KWError, 371 }, 372 { 373 name: "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)", 374 kt: ecdh.X25519ECDHKWKeyTemplate(), 375 enc: ariesjose.A192CBCHS384, 376 keyType: kms.X25519ECDHKWType, 377 nbRec: 1, 378 useCompact: true, 379 recipientKWError: singleRecipientX25519KWError, 380 }, 381 { 382 name: "P-256 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)", 383 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 384 enc: ariesjose.A256CBCHS384, 385 keyType: kms.NISTP256ECDHKWType, 386 nbRec: 2, 387 recipientKWError: multiRecKWError, 388 }, 389 { 390 name: "P-256 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)", 391 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 392 enc: ariesjose.A256CBCHS384, 393 keyType: kms.NISTP256ECDHKWType, 394 nbRec: 1, 395 recipientKWError: singleRecipientNISTPKWError, 396 }, 397 { 398 name: "P-256 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)", 399 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 400 enc: ariesjose.A256CBCHS384, 401 keyType: kms.NISTP256ECDHKWType, 402 nbRec: 1, 403 useCompact: true, 404 recipientKWError: singleRecipientNISTPKWError, 405 }, 406 { 407 name: "X25519 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)", 408 kt: ecdh.X25519ECDHKWKeyTemplate(), 409 enc: ariesjose.A256CBCHS384, 410 keyType: kms.X25519ECDHKWType, 411 nbRec: 2, 412 recipientKWError: multiRecKWError, 413 }, 414 { 415 name: "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)", 416 kt: ecdh.X25519ECDHKWKeyTemplate(), 417 enc: ariesjose.A256CBCHS384, 418 keyType: kms.X25519ECDHKWType, 419 nbRec: 1, 420 recipientKWError: singleRecipientX25519KWError, 421 }, 422 { 423 name: "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)", 424 kt: ecdh.X25519ECDHKWKeyTemplate(), 425 enc: ariesjose.A256CBCHS384, 426 keyType: kms.X25519ECDHKWType, 427 nbRec: 1, 428 useCompact: true, 429 recipientKWError: singleRecipientX25519KWError, 430 }, 431 { 432 name: "P-256 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)", 433 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 434 enc: ariesjose.A256CBCHS512, 435 keyType: kms.NISTP256ECDHKWType, 436 nbRec: 2, 437 recipientKWError: multiRecKWError, 438 }, 439 { 440 name: "P-256 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)", 441 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 442 enc: ariesjose.A256CBCHS512, 443 keyType: kms.NISTP256ECDHKWType, 444 nbRec: 1, 445 recipientKWError: singleRecipientNISTPKWError, 446 }, 447 { 448 name: "P-256 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)", 449 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 450 enc: ariesjose.A256CBCHS512, 451 keyType: kms.NISTP256ECDHKWType, 452 nbRec: 1, 453 useCompact: true, 454 recipientKWError: singleRecipientNISTPKWError, 455 }, 456 { 457 name: "X25519 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)", 458 kt: ecdh.X25519ECDHKWKeyTemplate(), 459 enc: ariesjose.A256CBCHS512, 460 keyType: kms.X25519ECDHKWType, 461 nbRec: 2, 462 recipientKWError: multiRecKWError, 463 }, 464 { 465 name: "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)", 466 kt: ecdh.X25519ECDHKWKeyTemplate(), 467 enc: ariesjose.A256CBCHS512, 468 keyType: kms.X25519ECDHKWType, 469 nbRec: 1, 470 recipientKWError: singleRecipientX25519KWError, 471 }, 472 { 473 name: "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)", 474 kt: ecdh.X25519ECDHKWKeyTemplate(), 475 enc: ariesjose.A256CBCHS512, 476 keyType: kms.X25519ECDHKWType, 477 nbRec: 1, 478 useCompact: true, 479 recipientKWError: singleRecipientX25519KWError, 480 }, 481 } 482 483 for _, tt := range tests { 484 tc := tt 485 t.Run(tc.name, func(t *testing.T) { 486 t.Log("creating recipients keys..") 487 recECKeys, recKHs, _, recDIDKeys := createRecipientsByKeyTemplate(t, tc.nbRec, tc.kt, tc.keyType) 488 489 cryptoSvc, kmsSvc := createCryptoAndKMSServices(t, recKHs) 490 491 _, err = ariesjose.NewJWEEncrypt("", "", "", "", nil, recECKeys, cryptoSvc) 492 require.EqualError(t, err, "encryption algorithm '' not supported", 493 "NewJWEEncrypt should fail with empty encAlg") 494 495 jweEncrypter, err := ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType, 496 DIDCommContentEncodingType, "", nil, recECKeys, cryptoSvc) 497 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 498 499 pt := []byte("secret message") 500 aad := []byte("aad value") 501 502 if tc.useCompact { // compact serialization does not use AAD 503 aad = nil 504 } 505 506 testEncTime := time.Now() 507 jwe, err := jweEncrypter.EncryptWithAuthData(pt, aad) 508 t.Logf("ECDH-ES KW in EncryptWithAuthData took %v", time.Since(testEncTime)) 509 require.NoError(t, err) 510 require.Equal(t, len(recECKeys), len(jwe.Recipients)) 511 512 cty, ok := jwe.ProtectedHeaders.ContentType() 513 require.True(t, ok) 514 require.Equal(t, DIDCommContentEncodingType, cty) 515 516 typ, ok := jwe.ProtectedHeaders.Type() 517 require.True(t, ok) 518 require.Equal(t, EnvelopeEncodingType, typ) 519 520 alg, ok := jwe.ProtectedHeaders.Algorithm() 521 if alg != "" { 522 require.True(t, ok) 523 require.Contains(t, []string{"ECDH-ES+A256KW", "ECDH-ES+XC20PKW"}, alg) 524 } else { 525 require.False(t, ok) 526 } 527 528 kid, ok := jwe.ProtectedHeaders.KeyID() 529 if kid != "" { 530 require.True(t, ok) 531 require.NotEmpty(t, kid) 532 } else { 533 require.False(t, ok) 534 } 535 536 var serializedJWE, jweStr string 537 serialization := fullSerialization 538 539 if tc.useCompact { 540 testSerTime := time.Now() 541 serializedJWE, err = jwe.CompactSerialize(json.Marshal) 542 t.Logf("CompactSerilize took %v", time.Since(testSerTime)) 543 require.NoError(t, err) 544 require.NotEmpty(t, serializedJWE) 545 546 jweStr = serializedJWE 547 serialization = compactSerialization 548 } else { 549 testSerTime := time.Now() 550 serializedJWE, err = jwe.FullSerialize(json.Marshal) 551 t.Logf("JSON Serialize took %v", time.Since(testSerTime)) 552 require.NoError(t, err) 553 require.NotEmpty(t, serializedJWE) 554 555 jweStr, err = prettyPrint([]byte(serializedJWE)) 556 require.NoError(t, err) 557 if tc.nbRec == 1 { 558 serialization = flattenedSerialization 559 } 560 } 561 562 t.Logf("* anoncrypt JWE (%s serialization): %s", serialization, jweStr) 563 564 mPh, err := json.Marshal(jwe.ProtectedHeaders) 565 require.NoError(t, err) 566 567 protectedHeadersStr, err := prettyPrint(mPh) 568 require.NoError(t, err) 569 570 t.Logf("* protected headers: %s", protectedHeadersStr) 571 572 // try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink) 573 joseJWE, err := jose.ParseEncrypted(serializedJWE) 574 require.NoError(t, err) 575 require.NotEmpty(t, joseJWE) 576 577 // try to deserialize with local package 578 testDeserTime := time.Now() 579 localJWE, err := ariesjose.Deserialize(serializedJWE) 580 t.Logf("JWE Deserialize took %v", time.Since(testDeserTime)) 581 require.NoError(t, err) 582 583 t.Run("Decrypting JWE tests failures", func(t *testing.T) { 584 jweDecrypter := ariesjose.NewJWEDecrypt(nil, cryptoSvc, kmsSvc) 585 586 // decrypt empty JWE 587 _, err = jweDecrypter.Decrypt(nil) 588 require.EqualError(t, err, "jwedecrypt: jwe is nil") 589 590 var badJWE *ariesjose.JSONWebEncryption 591 592 badJWE, err = ariesjose.Deserialize(serializedJWE) 593 require.NoError(t, err) 594 595 ph := badJWE.ProtectedHeaders 596 badJWE.ProtectedHeaders = nil 597 598 // decrypt JWE with empty ProtectHeaders 599 _, err = jweDecrypter.Decrypt(badJWE) 600 require.EqualError(t, err, "jwedecrypt: jwe is missing protected headers") 601 602 badJWE.ProtectedHeaders = ariesjose.Headers{} 603 badJWE.ProtectedHeaders["somKey"] = "badKey" 604 _, err = jweDecrypter.Decrypt(badJWE) 605 require.EqualError(t, err, "jwedecrypt: jwe is missing encryption algorithm 'enc' header") 606 607 badJWE.ProtectedHeaders = map[string]interface{}{ 608 ariesjose.HeaderEncryption: "badEncHeader", 609 ariesjose.HeaderType: "test", 610 } 611 612 // decrypt JWE with bad Enc header value 613 _, err = jweDecrypter.Decrypt(badJWE) 614 require.EqualError(t, err, "jwedecrypt: encryption algorithm 'badEncHeader' not supported") 615 616 badJWE.ProtectedHeaders = ph 617 618 // decrypt JWE with invalid recipient key 619 badJWE.Recipients = []*ariesjose.Recipient{ 620 { 621 EncryptedKey: "someKey", 622 Header: &ariesjose.RecipientHeaders{ 623 EPK: []byte("somerawbytes"), 624 }, 625 }, 626 } 627 628 if tc.nbRec > 1 { 629 badJWE.Recipients = append(badJWE.Recipients, &ariesjose.Recipient{ 630 EncryptedKey: "someOtherKey", 631 Header: &ariesjose.RecipientHeaders{ 632 EPK: []byte("someotherrawbytes"), 633 }, 634 }) 635 } 636 637 _, err = jweDecrypter.Decrypt(badJWE) 638 require.EqualError(t, err, tc.recipientKWError) 639 640 // decrypt JWE with unsupported recipient key 641 var privKey *rsa.PrivateKey 642 643 privKey, err = rsa.GenerateKey(rand.Reader, 2048) 644 645 unsupportedJWK := jwk.JWK{ 646 JSONWebKey: jose.JSONWebKey{ 647 Key: &privKey.PublicKey, 648 }, 649 } 650 651 var mk []byte 652 653 mk, err = unsupportedJWK.MarshalJSON() 654 require.NoError(t, err) 655 656 badJWE.Recipients = []*ariesjose.Recipient{ 657 { 658 EncryptedKey: "someKey", 659 Header: &ariesjose.RecipientHeaders{ 660 EPK: mk, 661 }, 662 }, 663 } 664 665 if tc.nbRec > 1 { 666 badJWE.Recipients = append(badJWE.Recipients, &ariesjose.Recipient{ 667 EncryptedKey: "someOtherKey", 668 Header: &ariesjose.RecipientHeaders{ 669 EPK: mk, 670 }, 671 }) 672 } 673 674 _, err = jweDecrypter.Decrypt(badJWE) 675 if tc.nbRec == 1 { 676 require.EqualError(t, err, tc.recipientKWError) 677 } else { 678 require.EqualError(t, err, "jwedecrypt: failed to build recipients WK: unsupported recipient key type") 679 } 680 }) 681 682 t.Run("Decrypting JWE test success ", func(t *testing.T) { 683 jweDecrypter := ariesjose.NewJWEDecrypt(nil, cryptoSvc, kmsSvc) 684 685 var msg []byte 686 687 testDecTime := time.Now() 688 msg, err = jweDecrypter.Decrypt(localJWE) 689 t.Logf("JWE Decrypt took %v", time.Since(testDecTime)) 690 require.NoError(t, err) 691 require.EqualValues(t, pt, msg) 692 }) 693 694 t.Run("ECDH-ES Encrypt and Decrypt JWE test success with kid as did:key", func(t *testing.T) { 695 recKeys := make([]*cryptoapi.PublicKey, 0) 696 for i, k := range recECKeys { 697 k.KID = recDIDKeys[i] 698 recKeys = append(recKeys, k) 699 } 700 701 jweEncrypter, err = ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType, 702 DIDCommContentEncodingType, "", nil, recKeys, cryptoSvc) 703 require.NoError(t, err) 704 705 testEncTime = time.Now() 706 jwe, err = jweEncrypter.EncryptWithAuthData(pt, aad) 707 t.Logf("ECDH-ES KW in EncryptWithAuthData with kid as did:key took %v", time.Since(testEncTime)) 708 require.NoError(t, err) 709 require.Equal(t, len(recECKeys), len(jwe.Recipients)) 710 711 if tc.useCompact { 712 testSerTime := time.Now() 713 serializedJWE, err = jwe.CompactSerialize(json.Marshal) 714 t.Logf("CompactSerilize JWE with as did:key took %v", time.Since(testSerTime)) 715 require.NoError(t, err) 716 require.NotEmpty(t, serializedJWE) 717 718 jweStr = serializedJWE 719 serialization = compactSerialization 720 } else { 721 testSerTime := time.Now() 722 serializedJWE, err = jwe.FullSerialize(json.Marshal) 723 t.Logf("JSON Serialize with kid as did:key took %v", time.Since(testSerTime)) 724 require.NoError(t, err) 725 require.NotEmpty(t, serializedJWE) 726 727 jweStr, err = prettyPrint([]byte(serializedJWE)) 728 require.NoError(t, err) 729 if tc.nbRec == 1 { 730 serialization = flattenedSerialization 731 } 732 } 733 734 t.Logf("* anoncrypt JWE (%s serialization) with kid as did:key: %s", serialization, jweStr) 735 736 // try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink) 737 joseJWE, err := jose.ParseEncrypted(serializedJWE) 738 require.NoError(t, err) 739 require.NotEmpty(t, joseJWE) 740 741 // try to deserialize with local package 742 testDeserTime := time.Now() 743 localJWE, err = ariesjose.Deserialize(serializedJWE) 744 t.Logf("JWE with kid as did:key Deserialize took %v", time.Since(testDeserTime)) 745 require.NoError(t, err) 746 747 jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.DIDKeyResolver{}}, cryptoSvc, kmsSvc) 748 749 var msg []byte 750 751 testDecTime := time.Now() 752 msg, err = jweDecrypter.Decrypt(localJWE) 753 t.Logf("JWE with kid as did:key Decrypt took %v", time.Since(testDecTime)) 754 require.NoError(t, err) 755 require.EqualValues(t, pt, msg) 756 757 if tc.nbRec > 1 { 758 t.Run("decrypt with failing kid resolver", func(t *testing.T) { 759 failingResolver := &mockResolver{resolveError: fmt.Errorf("resolve kid failure")} 760 jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{failingResolver}, cryptoSvc, kmsSvc) 761 762 _, err = jweDecrypter.Decrypt(localJWE) 763 require.EqualError(t, err, "jwedecrypt: failed to unwrap cek: [resolveKID: "+ 764 "[resolve kid failure] resolveKID: [resolve kid failure]]") 765 }) 766 } 767 }) 768 }) 769 } 770 } 771 772 type mockResolver struct { 773 resolveValue *cryptoapi.PublicKey 774 resolveError error 775 } 776 777 func (m *mockResolver) Resolve(kid string) (*cryptoapi.PublicKey, error) { 778 return m.resolveValue, m.resolveError 779 } 780 781 func TestInteropWithGoJoseEncryptAndLocalJoseDecryptUsingCompactSerialize(t *testing.T) { 782 recECKeys, recKHs, recKIDs, _ := createRecipients(t, 1) 783 gjRecipients := convertToGoJoseRecipients(t, recECKeys, recKIDs) 784 785 c, k := createCryptoAndKMSServices(t, recKHs) 786 787 eo := &jose.EncrypterOptions{} 788 gjEncrypter, err := jose.NewEncrypter(jose.A256GCM, gjRecipients[0], 789 eo.WithType(EnvelopeEncodingType)) 790 require.NoError(t, err) 791 792 pt := []byte("Test secret message") 793 794 // encrypt pt using go-jose encryption 795 gjJWEEncrypter, err := gjEncrypter.Encrypt(pt) 796 require.NoError(t, err) 797 798 // get go-jose serialized JWE 799 gjSerializedJWE, err := gjJWEEncrypter.CompactSerialize() 800 require.NoError(t, err) 801 802 // deserialize using local jose package 803 localJWE, err := ariesjose.Deserialize(gjSerializedJWE) 804 require.NoError(t, err) 805 806 t.Run("Decrypting JWE message encrypted by go-jose test success", func(t *testing.T) { 807 jweDecrypter := ariesjose.NewJWEDecrypt(nil, c, k) 808 809 var msg []byte 810 811 msg, err = jweDecrypter.Decrypt(localJWE) 812 require.NoError(t, err) 813 require.EqualValues(t, pt, msg) 814 }) 815 } 816 817 func TestInteropWithGoJoseEncryptAndLocalJoseDecrypt(t *testing.T) { 818 recECKeys, recKHs, recKIDs, _ := createRecipients(t, 3) 819 gjRecipients := convertToGoJoseRecipients(t, recECKeys, recKIDs) 820 821 c, k := createCryptoAndKMSServices(t, recKHs) 822 823 eo := &jose.EncrypterOptions{} 824 gjEncrypter, err := jose.NewMultiEncrypter(jose.A256GCM, gjRecipients, 825 eo.WithType(EnvelopeEncodingType)) 826 require.NoError(t, err) 827 828 pt := []byte("Test secret message") 829 aad := []byte("Test some auth data") 830 831 // encrypt pt using go-jose encryption 832 gjJWEEncrypter, err := gjEncrypter.EncryptWithAuthData(pt, aad) 833 require.NoError(t, err) 834 835 // get go-jose serialized JWE 836 gjSerializedJWE := gjJWEEncrypter.FullSerialize() 837 838 // deserialize using local jose package 839 localJWE, err := ariesjose.Deserialize(gjSerializedJWE) 840 require.NoError(t, err) 841 842 t.Run("Decrypting JWE message encrypted by go-jose test success", func(t *testing.T) { 843 jweDecrypter := ariesjose.NewJWEDecrypt(nil, c, k) 844 845 var msg []byte 846 847 msg, err = jweDecrypter.Decrypt(localJWE) 848 require.NoError(t, err) 849 require.EqualValues(t, pt, msg) 850 }) 851 } 852 853 func TestInteropWithLocalJoseEncryptAndGoJoseDecrypt(t *testing.T) { 854 c, err := tinkcrypto.New() 855 require.NoError(t, err) 856 857 // get two generated recipient Tink keys 858 recECKeys, _, _, _ := createRecipients(t, 2) //nolint:dogsled 859 // create a normal recipient key (not using Tink) 860 rec3PrivKey, err := ecdsa.GenerateKey(subtle.GetCurve(recECKeys[0].Curve), rand.Reader) 861 require.NoError(t, err) 862 863 // add third key to recECKeys 864 recECKeys = append(recECKeys, &cryptoapi.PublicKey{ 865 X: rec3PrivKey.PublicKey.X.Bytes(), 866 Y: rec3PrivKey.PublicKey.Y.Bytes(), 867 Curve: rec3PrivKey.PublicKey.Curve.Params().Name, 868 Type: "EC", 869 }) 870 871 // encrypt using local jose package 872 jweEncrypter, err := ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType, 873 "", nil, recECKeys, c) 874 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 875 876 pt := []byte("some msg") 877 jwe, err := jweEncrypter.EncryptWithAuthData(pt, []byte("aad value")) 878 require.NoError(t, err) 879 require.Equal(t, len(recECKeys), len(jwe.Recipients)) 880 881 serializedJWE, err := jwe.FullSerialize(json.Marshal) 882 require.NoError(t, err) 883 884 // now parse serializedJWE using go-jose 885 gjParsedJWE, err := jose.ParseEncrypted(serializedJWE) 886 require.NoError(t, err) 887 888 // Decrypt with third recipient's private key (non Tink key) 889 i, _, msg, err := gjParsedJWE.DecryptMulti(rec3PrivKey) 890 require.NoError(t, err) 891 require.EqualValues(t, pt, msg) 892 893 // the third recipient's index is 2 894 require.Equal(t, 2, i) 895 } 896 897 func TestInteropWithLocalJoseEncryptAndGoJoseDecryptUsingCompactSerialization(t *testing.T) { 898 var recECKeys []*cryptoapi.PublicKey 899 // create a normal recipient key (not using Tink) 900 recPrivKey, err := ecdsa.GenerateKey(subtle.GetCurve("NIST_P256"), rand.Reader) 901 require.NoError(t, err) 902 903 c, err := tinkcrypto.New() 904 require.NoError(t, err) 905 906 recECKeys = append(recECKeys, &cryptoapi.PublicKey{ 907 X: recPrivKey.PublicKey.X.Bytes(), 908 Y: recPrivKey.PublicKey.Y.Bytes(), 909 Curve: recPrivKey.PublicKey.Curve.Params().Name, 910 Type: "EC", 911 }) 912 913 // encrypt using local jose package 914 jweEncrypter, err := ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType, 915 "", nil, recECKeys, c) 916 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 917 918 pt := []byte("some msg") 919 jwe, err := jweEncrypter.Encrypt(pt) 920 require.NoError(t, err) 921 require.Equal(t, len(recECKeys), len(jwe.Recipients)) 922 923 serializedJWE, err := jwe.CompactSerialize(json.Marshal) 924 require.NoError(t, err) 925 926 // now parse serializedJWE using go-jose 927 gjParsedJWE, err := jose.ParseEncrypted(serializedJWE) 928 require.NoError(t, err) 929 930 // Decrypt with recipient's private key 931 msg, err := gjParsedJWE.Decrypt(recPrivKey) 932 require.NoError(t, err) 933 require.EqualValues(t, pt, msg) 934 } 935 936 func convertToGoJoseRecipients(t *testing.T, keys []*cryptoapi.PublicKey, kids []string) []jose.Recipient { 937 t.Helper() 938 939 var joseRecipients []jose.Recipient 940 941 for i, key := range keys { 942 c := subtle.GetCurve(key.Curve) 943 gjKey := jose.Recipient{ 944 KeyID: kids[i], 945 Algorithm: jose.ECDH_ES_A256KW, 946 Key: &ecdsa.PublicKey{ 947 Curve: c, 948 X: new(big.Int).SetBytes(key.X), 949 Y: new(big.Int).SetBytes(key.Y), 950 }, 951 } 952 953 joseRecipients = append(joseRecipients, gjKey) 954 } 955 956 return joseRecipients 957 } 958 959 func createRecipients(t *testing.T, 960 nbOfEntities int) ([]*cryptoapi.PublicKey, map[string]*keyset.Handle, []string, []string) { 961 return createRecipientsByKeyTemplate(t, nbOfEntities, ecdh.NISTP256ECDHKWKeyTemplate(), kms.NISTP256ECDHKWType) 962 } 963 964 // createRecipients and return their public key and keyset.Handle. 965 func createRecipientsByKeyTemplate(t *testing.T, nbOfEntities int, kt *tinkpb.KeyTemplate, 966 keyType kms.KeyType) ([]*cryptoapi.PublicKey, map[string]*keyset.Handle, []string, []string) { 967 t.Helper() 968 969 r := make([]*cryptoapi.PublicKey, 0) 970 rKH := make(map[string]*keyset.Handle) 971 rKID := make([]string, 0) 972 rDIDKey := make([]string, 0) 973 974 for i := 0; i < nbOfEntities; i++ { 975 mrKey, kh, kid, didKey := createAndMarshalEntityKey(t, kt, keyType) 976 977 ecPubKey := new(cryptoapi.PublicKey) 978 err := json.Unmarshal(mrKey, ecPubKey) 979 require.NoError(t, err) 980 981 ecPubKey.KID = kid 982 rKH[kid] = kh 983 984 r = append(r, ecPubKey) 985 rKID = append(rKID, kid) 986 rDIDKey = append(rDIDKey, didKey) 987 } 988 989 return r, rKH, rKID, rDIDKey 990 } 991 992 // createAndMarshalEntityKey creates a new recipient keyset.Handle, extracts public key, marshals it and returns 993 // both marshalled public key and original recipient keyset.Handle. 994 func createAndMarshalEntityKey(t *testing.T, kt *tinkpb.KeyTemplate, 995 keyType kms.KeyType) ([]byte, *keyset.Handle, string, string) { 996 t.Helper() 997 998 kh, err := keyset.NewHandle(kt) 999 require.NoError(t, err) 1000 1001 pubKH, err := kh.Public() 1002 require.NoError(t, err) 1003 1004 buf := new(bytes.Buffer) 1005 pubKeyWriter := keyio.NewWriter(buf) 1006 require.NotEmpty(t, pubKeyWriter) 1007 1008 err = pubKH.WriteWithNoSecrets(pubKeyWriter) 1009 require.NoError(t, err) 1010 1011 mKeyBytes := buf.Bytes() 1012 1013 kid, err := jwkkid.CreateKID(mKeyBytes, keyType) 1014 require.NoError(t, err) 1015 1016 didKey, err := kmsdidkey.BuildDIDKeyByKeyType(mKeyBytes, keyType) 1017 require.NoError(t, err) 1018 1019 printKey(t, mKeyBytes, kid) 1020 1021 return mKeyBytes, kh, kid, didKey 1022 } 1023 1024 func printKey(t *testing.T, mPubKey []byte, kid string) { 1025 t.Helper() 1026 1027 pubKey := new(cryptoapi.PublicKey) 1028 err := json.Unmarshal(mPubKey, pubKey) 1029 require.NoError(t, err) 1030 1031 switch pubKey.Type { 1032 case ecdhpb.KeyType_EC.String(): 1033 t.Logf("** EC key: %s, kid: %s", getPrintedECPubKey(t, pubKey), kid) 1034 case ecdhpb.KeyType_OKP.String(): 1035 t.Logf("** X25519 key: %s, kid: %s", getPrintedX25519PubKey(t, pubKey), kid) 1036 default: 1037 t.Errorf("not supported key type: %s", pubKey.Type) 1038 } 1039 } 1040 1041 func prettyPrint(msg []byte) (string, error) { 1042 var prettyJSON bytes.Buffer 1043 1044 err := json.Indent(&prettyJSON, msg, "", "\t") 1045 if err != nil { 1046 return "", err 1047 } 1048 1049 return prettyJSON.String(), nil 1050 } 1051 1052 func getPrintedECPubKey(t *testing.T, pubKey *cryptoapi.PublicKey) string { 1053 crv, err := hybrid.GetCurve(pubKey.Curve) 1054 require.NoError(t, err) 1055 1056 j := jose.JSONWebKey{ 1057 Key: &ecdsa.PublicKey{ 1058 Curve: crv, 1059 X: new(big.Int).SetBytes(pubKey.X), 1060 Y: new(big.Int).SetBytes(pubKey.Y), 1061 }, 1062 } 1063 1064 jwkByte, err := j.MarshalJSON() 1065 require.NoError(t, err) 1066 jwkStr, err := prettyPrint(jwkByte) 1067 require.NoError(t, err) 1068 1069 return jwkStr 1070 } 1071 1072 func getPrintedX25519PubKey(t *testing.T, pubKeyType *cryptoapi.PublicKey) string { 1073 j := jose.JSONWebKey{ 1074 Key: ed25519.PublicKey(pubKeyType.X), 1075 } 1076 1077 jwkByte, err := j.MarshalJSON() 1078 require.NoError(t, err) 1079 1080 jwkStr, err := prettyPrint(jwkByte) 1081 require.NoError(t, err) 1082 1083 return strings.Replace(jwkStr, "Ed25519", "X25519", 1) 1084 } 1085 1086 func TestFailNewJWEEncrypt(t *testing.T) { 1087 c, err := tinkcrypto.New() 1088 require.NoError(t, err) 1089 1090 recipients, recsKH, kids, _ := createRecipients(t, 2) 1091 1092 t.Run("test with missing skid", func(t *testing.T) { 1093 _, err = ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType, 1094 "", recsKH[kids[0]], recipients, c) 1095 require.EqualError(t, err, "senderKID is required with senderKH") 1096 }) 1097 1098 t.Run("test with missing crypto", func(t *testing.T) { 1099 _, err = ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType, 1100 kids[0], recsKH[kids[0]], recipients, nil) 1101 require.EqualError(t, err, "crypto service is required to create a JWEEncrypt instance") 1102 }) 1103 } 1104 1105 //nolint:gocognit 1106 func TestECDH1PU(t *testing.T) { 1107 tests := []struct { 1108 name string 1109 kt *tinkpb.KeyTemplate 1110 enc ariesjose.EncAlg 1111 keyType kms.KeyType 1112 nbRec int 1113 useCompact bool 1114 }{ 1115 { 1116 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 1117 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1118 enc: ariesjose.XC20P, 1119 keyType: kms.NISTP256ECDHKWType, 1120 nbRec: 2, 1121 }, 1122 { 1123 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 1124 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1125 enc: ariesjose.XC20P, 1126 keyType: kms.NISTP256ECDHKWType, 1127 nbRec: 1, 1128 }, 1129 { 1130 name: "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 1131 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1132 enc: ariesjose.XC20P, 1133 keyType: kms.NISTP256ECDHKWType, 1134 nbRec: 1, 1135 useCompact: true, 1136 }, 1137 { 1138 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 1139 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1140 enc: ariesjose.XC20P, 1141 keyType: kms.NISTP384ECDHKWType, 1142 nbRec: 2, 1143 }, 1144 { 1145 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 1146 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1147 enc: ariesjose.XC20P, 1148 keyType: kms.NISTP384ECDHKWType, 1149 nbRec: 1, 1150 }, 1151 { 1152 name: "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 1153 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1154 enc: ariesjose.XC20P, 1155 keyType: kms.NISTP384ECDHKWType, 1156 nbRec: 1, 1157 useCompact: true, 1158 }, 1159 { 1160 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 1161 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1162 enc: ariesjose.XC20P, 1163 keyType: kms.NISTP521ECDHKWType, 1164 nbRec: 2, 1165 }, 1166 { 1167 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 1168 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1169 enc: ariesjose.XC20P, 1170 keyType: kms.NISTP521ECDHKWType, 1171 nbRec: 1, 1172 }, 1173 { 1174 name: "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 1175 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1176 enc: ariesjose.XC20P, 1177 keyType: kms.NISTP521ECDHKWType, 1178 nbRec: 1, 1179 useCompact: true, 1180 }, 1181 { 1182 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)", 1183 kt: ecdh.X25519ECDHKWKeyTemplate(), 1184 enc: ariesjose.XC20P, 1185 keyType: kms.X25519ECDHKWType, 1186 nbRec: 2, 1187 }, 1188 { 1189 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)", 1190 kt: ecdh.X25519ECDHKWKeyTemplate(), 1191 enc: ariesjose.XC20P, 1192 keyType: kms.X25519ECDHKWType, 1193 nbRec: 1, 1194 }, 1195 { 1196 name: "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)", 1197 kt: ecdh.X25519ECDHKWKeyTemplate(), 1198 enc: ariesjose.XC20P, 1199 keyType: kms.X25519ECDHKWType, 1200 nbRec: 1, 1201 useCompact: true, 1202 }, 1203 { 1204 name: "P-256 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)", 1205 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1206 enc: ariesjose.A128CBCHS256, 1207 keyType: kms.NISTP256ECDHKWType, 1208 nbRec: 2, 1209 }, 1210 { 1211 name: "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)", 1212 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1213 enc: ariesjose.A128CBCHS256, 1214 keyType: kms.NISTP256ECDHKWType, 1215 nbRec: 1, 1216 }, 1217 { 1218 name: "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)", 1219 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1220 enc: ariesjose.A128CBCHS256, 1221 keyType: kms.NISTP256ECDHKWType, 1222 nbRec: 1, 1223 useCompact: true, 1224 }, 1225 { 1226 name: "X25519 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)", 1227 kt: ecdh.X25519ECDHKWKeyTemplate(), 1228 enc: ariesjose.A128CBCHS256, 1229 keyType: kms.X25519ECDHKWType, 1230 nbRec: 2, 1231 }, 1232 { 1233 name: "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)", 1234 kt: ecdh.X25519ECDHKWKeyTemplate(), 1235 enc: ariesjose.A128CBCHS256, 1236 keyType: kms.X25519ECDHKWType, 1237 nbRec: 1, 1238 }, 1239 { 1240 name: "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)", 1241 kt: ecdh.X25519ECDHKWKeyTemplate(), 1242 enc: ariesjose.A128CBCHS256, 1243 keyType: kms.X25519ECDHKWType, 1244 nbRec: 1, 1245 useCompact: true, 1246 }, 1247 { 1248 name: "P-256 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)", 1249 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1250 enc: ariesjose.A192CBCHS384, 1251 keyType: kms.NISTP256ECDHKWType, 1252 nbRec: 2, 1253 }, 1254 { 1255 name: "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)", 1256 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1257 enc: ariesjose.A192CBCHS384, 1258 keyType: kms.NISTP256ECDHKWType, 1259 nbRec: 1, 1260 }, 1261 { 1262 name: "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)", 1263 kt: ecdh.NISTP256ECDHKWKeyTemplate(), 1264 enc: ariesjose.A192CBCHS384, 1265 keyType: kms.NISTP256ECDHKWType, 1266 nbRec: 1, 1267 useCompact: true, 1268 }, 1269 { 1270 name: "P-384 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)", 1271 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1272 enc: ariesjose.A192CBCHS384, 1273 keyType: kms.NISTP384ECDHKWType, 1274 nbRec: 2, 1275 }, 1276 { 1277 name: "P-384 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)", 1278 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1279 enc: ariesjose.A192CBCHS384, 1280 keyType: kms.NISTP384ECDHKWType, 1281 nbRec: 1, 1282 }, 1283 { 1284 name: "P-384 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)", 1285 kt: ecdh.NISTP384ECDHKWKeyTemplate(), 1286 enc: ariesjose.A192CBCHS384, 1287 keyType: kms.NISTP384ECDHKWType, 1288 nbRec: 1, 1289 useCompact: true, 1290 }, 1291 { 1292 name: "X25519 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)", 1293 kt: ecdh.X25519ECDHKWKeyTemplate(), 1294 enc: ariesjose.A192CBCHS384, 1295 keyType: kms.X25519ECDHKWType, 1296 nbRec: 2, 1297 }, 1298 { 1299 name: "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)", 1300 kt: ecdh.X25519ECDHKWKeyTemplate(), 1301 enc: ariesjose.A192CBCHS384, 1302 keyType: kms.X25519ECDHKWType, 1303 nbRec: 1, 1304 }, 1305 { 1306 name: "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)", 1307 kt: ecdh.X25519ECDHKWKeyTemplate(), 1308 enc: ariesjose.A192CBCHS384, 1309 keyType: kms.X25519ECDHKWType, 1310 nbRec: 1, 1311 useCompact: true, 1312 }, 1313 { 1314 name: "X25519 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)", 1315 kt: ecdh.X25519ECDHKWKeyTemplate(), 1316 enc: ariesjose.A256CBCHS384, 1317 keyType: kms.X25519ECDHKWType, 1318 nbRec: 2, 1319 }, 1320 { 1321 name: "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)", 1322 kt: ecdh.X25519ECDHKWKeyTemplate(), 1323 enc: ariesjose.A256CBCHS384, 1324 keyType: kms.X25519ECDHKWType, 1325 nbRec: 1, 1326 }, 1327 { 1328 name: "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)", 1329 kt: ecdh.X25519ECDHKWKeyTemplate(), 1330 enc: ariesjose.A256CBCHS384, 1331 keyType: kms.X25519ECDHKWType, 1332 nbRec: 1, 1333 useCompact: true, 1334 }, 1335 { 1336 name: "P-521 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)", 1337 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1338 enc: ariesjose.A256CBCHS512, 1339 keyType: kms.NISTP521ECDHKWType, 1340 nbRec: 2, 1341 }, 1342 { 1343 name: "P-521 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)", 1344 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1345 enc: ariesjose.A256CBCHS512, 1346 keyType: kms.NISTP521ECDHKWType, 1347 nbRec: 1, 1348 }, 1349 { 1350 name: "P-521 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)", 1351 kt: ecdh.NISTP521ECDHKWKeyTemplate(), 1352 enc: ariesjose.A256CBCHS512, 1353 keyType: kms.NISTP521ECDHKWType, 1354 nbRec: 1, 1355 useCompact: true, 1356 }, 1357 { 1358 name: "X25519 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)", 1359 kt: ecdh.X25519ECDHKWKeyTemplate(), 1360 enc: ariesjose.A256CBCHS512, 1361 keyType: kms.X25519ECDHKWType, 1362 nbRec: 2, 1363 }, 1364 { 1365 name: "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)", 1366 kt: ecdh.X25519ECDHKWKeyTemplate(), 1367 enc: ariesjose.A256CBCHS512, 1368 keyType: kms.X25519ECDHKWType, 1369 nbRec: 1, 1370 }, 1371 { 1372 name: "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)", 1373 kt: ecdh.X25519ECDHKWKeyTemplate(), 1374 enc: ariesjose.A256CBCHS512, 1375 keyType: kms.X25519ECDHKWType, 1376 nbRec: 1, 1377 useCompact: true, 1378 }, 1379 } 1380 1381 for _, tt := range tests { 1382 tc := tt 1383 t.Run(tc.name, func(t *testing.T) { 1384 t.Log("creating Sender key..") 1385 senders, senderKHs, senderKIDs, senderDIDKeys := createRecipientsByKeyTemplate(t, 1, tc.kt, tc.keyType) 1386 t.Log("creating recipients keys..") 1387 recipientsKeys, recKHs, _, recDIDKeys := createRecipientsByKeyTemplate(t, tc.nbRec, tc.kt, tc.keyType) 1388 1389 cryptoSvc, kmsSvc := createCryptoAndKMSServices(t, recKHs) 1390 1391 senderPubKey, err := json.Marshal(senders[0]) 1392 require.NoError(t, err) 1393 1394 jweEncrypter, err := ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType, DIDCommContentEncodingType, 1395 senderKIDs[0], senderKHs[senderKIDs[0]], recipientsKeys, cryptoSvc) 1396 require.NoError(t, err) 1397 require.NotEmpty(t, jweEncrypter) 1398 1399 mockStoreMap := make(map[string]mockstorage.DBEntry) 1400 mockStore := &mockstorage.MockStore{ 1401 Store: mockStoreMap, 1402 } 1403 1404 storeResolver := []resolver.KIDResolver{&resolver.StoreResolver{Store: mockStore}} 1405 1406 pt := []byte("secret message") 1407 aad := []byte("aad value") 1408 1409 if tc.useCompact { // Compact serialization does not use aad 1410 aad = nil 1411 } 1412 1413 // test JWEEncrypt for ECDH1PU 1414 testEncTime := time.Now() 1415 jwe, err := jweEncrypter.EncryptWithAuthData(pt, aad) 1416 t.Logf("ECDH-1PU KW in EncryptWithAuthData took %v", time.Since(testEncTime)) 1417 require.NoError(t, err) 1418 1419 cty, ok := jwe.ProtectedHeaders.ContentType() 1420 require.True(t, ok) 1421 require.Equal(t, DIDCommContentEncodingType, cty) 1422 1423 typ, ok := jwe.ProtectedHeaders.Type() 1424 require.True(t, ok) 1425 require.Equal(t, EnvelopeEncodingType, typ) 1426 1427 alg, ok := jwe.ProtectedHeaders.Algorithm() 1428 if alg != "" { 1429 cbcHMACAlgs := []string{ 1430 tinkcrypto.ECDH1PUA128KWAlg, tinkcrypto.ECDH1PUA192KWAlg, 1431 tinkcrypto.ECDH1PUA256KWAlg, tinkcrypto.ECDH1PUXC20PKWAlg, 1432 } 1433 1434 require.True(t, ok) 1435 require.Contains(t, cbcHMACAlgs, alg) 1436 } else { 1437 require.False(t, ok) 1438 } 1439 1440 kid, ok := jwe.ProtectedHeaders.KeyID() 1441 if kid != "" { 1442 require.True(t, ok) 1443 require.NotEmpty(t, kid) 1444 } else { 1445 require.False(t, ok) 1446 } 1447 1448 var serializedJWE, jweStr string 1449 serialization := fullSerialization 1450 1451 if tc.useCompact { 1452 testSerTime := time.Now() 1453 serializedJWE, err = jwe.CompactSerialize(json.Marshal) 1454 t.Logf("Compact serialize took %v", time.Since(testSerTime)) 1455 require.NoError(t, err) 1456 require.NotEmpty(t, serializedJWE) 1457 1458 jweStr = serializedJWE 1459 serialization = compactSerialization 1460 } else { 1461 testSerTime := time.Now() 1462 serializedJWE, err = jwe.FullSerialize(json.Marshal) 1463 t.Logf("JSON serialize took %v", time.Since(testSerTime)) 1464 require.NoError(t, err) 1465 require.NotEmpty(t, serializedJWE) 1466 1467 jweStr, err = prettyPrint([]byte(serializedJWE)) 1468 require.NoError(t, err) 1469 if tc.nbRec == 1 { 1470 serialization = flattenedSerialization 1471 } 1472 } 1473 1474 t.Logf("* authcrypt JWE (%s serialization): %s", serialization, jweStr) 1475 1476 mPh, err := json.Marshal(jwe.ProtectedHeaders) 1477 require.NoError(t, err) 1478 1479 protectedHeadersStr, err := prettyPrint(mPh) 1480 require.NoError(t, err) 1481 1482 t.Logf("* protected headers: %s", protectedHeadersStr) 1483 1484 testDeserTime := time.Now() 1485 localJWE, err := ariesjose.Deserialize(serializedJWE) 1486 t.Logf("JWE deserialize took %v", time.Since(testDeserTime)) 1487 require.NoError(t, err) 1488 1489 t.Run("ECDH-1PU JWE message without kid key in the KID storeResolver's store should fail", func(t *testing.T) { 1490 jd := ariesjose.NewJWEDecrypt(storeResolver, cryptoSvc, kmsSvc) 1491 require.NotEmpty(t, jd) 1492 1493 _, err = jd.Decrypt(localJWE) 1494 require.EqualError(t, err, "jwedecrypt: failed to add sender public key for skid: fetchSenderPubKey: "+ 1495 "resolveKID: [storeResolver: failed to resolve kid from store: data not found]") 1496 }) 1497 1498 // add sender pubkey into the recipient's mock store to prepare for a successful JWEDecrypt() for each recipient 1499 mockStoreMap[senderKIDs[0]] = mockstorage.DBEntry{Value: senderPubKey} 1500 1501 t.Run("Decrypting JWE message test success", func(t *testing.T) { 1502 jd := ariesjose.NewJWEDecrypt(storeResolver, cryptoSvc, kmsSvc) 1503 require.NotEmpty(t, jd) 1504 1505 var msg []byte 1506 1507 testDecTime := time.Now() 1508 msg, err = jd.Decrypt(localJWE) 1509 t.Logf("JWE deserialize took %v", time.Since(testDecTime)) 1510 require.NoError(t, err) 1511 require.EqualValues(t, pt, msg) 1512 }) 1513 1514 t.Run("ECDH-1PU Encrypt and Decrypt JWE test success with skid/kid as did:key", func(t *testing.T) { 1515 recKeys := make([]*cryptoapi.PublicKey, 0) 1516 for i, k := range recipientsKeys { 1517 k.KID = recDIDKeys[i] 1518 recKeys = append(recKeys, k) 1519 } 1520 1521 jweEncrypter, err = ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType, 1522 DIDCommContentEncodingType, senderDIDKeys[0], senderKHs[senderKIDs[0]], recKeys, cryptoSvc) 1523 require.NoError(t, err) 1524 1525 testEncTime = time.Now() 1526 jwe, err = jweEncrypter.EncryptWithAuthData(pt, aad) 1527 t.Logf("ECDH-1PU KW in EncryptWithAuthData with kid as did:key took %v", time.Since(testEncTime)) 1528 require.NoError(t, err) 1529 require.Equal(t, len(recipientsKeys), len(jwe.Recipients)) 1530 1531 if tc.useCompact { 1532 testSerTime := time.Now() 1533 serializedJWE, err = jwe.CompactSerialize(json.Marshal) 1534 t.Logf("CompactSerilize JWE with as did:key took %v", time.Since(testSerTime)) 1535 require.NoError(t, err) 1536 require.NotEmpty(t, serializedJWE) 1537 1538 jweStr = serializedJWE 1539 serialization = compactSerialization 1540 } else { 1541 testSerTime := time.Now() 1542 serializedJWE, err = jwe.FullSerialize(json.Marshal) 1543 t.Logf("JSON Serialize with kid as did:key took %v", time.Since(testSerTime)) 1544 require.NoError(t, err) 1545 require.NotEmpty(t, serializedJWE) 1546 1547 jweStr, err = prettyPrint([]byte(serializedJWE)) 1548 require.NoError(t, err) 1549 if tc.nbRec == 1 { 1550 serialization = flattenedSerialization 1551 } 1552 } 1553 1554 t.Logf("* authcrypt JWE (%s serialization) with kid as did:key: %s", serialization, jweStr) 1555 1556 // try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink) 1557 joseJWE, err := jose.ParseEncrypted(serializedJWE) 1558 require.NoError(t, err) 1559 require.NotEmpty(t, joseJWE) 1560 1561 // try to deserialize with local package 1562 testDeserTime := time.Now() 1563 localJWE, err = ariesjose.Deserialize(serializedJWE) 1564 t.Logf("JWE with kid as did:key Deserialize took %v", time.Since(testDeserTime)) 1565 require.NoError(t, err) 1566 1567 jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.DIDKeyResolver{}}, cryptoSvc, kmsSvc) 1568 1569 var msg []byte 1570 1571 testDecTime := time.Now() 1572 msg, err = jweDecrypter.Decrypt(localJWE) 1573 t.Logf("JWE with kid as did:key Decrypt took %v", time.Since(testDecTime)) 1574 require.NoError(t, err) 1575 require.EqualValues(t, pt, msg) 1576 }) 1577 }) 1578 } 1579 } 1580 1581 func createCryptoAndKMSServices(t *testing.T, keys map[string]*keyset.Handle) (cryptoapi.Crypto, kms.KeyManager) { 1582 c, err := tinkcrypto.New() 1583 require.NoError(t, err) 1584 1585 k := &mockKMSGetter{ 1586 keys: keys, 1587 } 1588 1589 require.NoError(t, err) 1590 1591 return c, k 1592 } 1593 1594 type mockKMSGetter struct { 1595 mockkms.KeyManager 1596 keys map[string]*keyset.Handle 1597 } 1598 1599 func (k *mockKMSGetter) Get(kid string) (interface{}, error) { 1600 return k.keys[kid], nil 1601 } 1602 1603 // nolint:gochecknoglobals // embedded test data 1604 var ( 1605 // test vector retrieved from: 1606 //nolint:lll 1607 // (github: https://github.com/NeilMadden/jose-ecdh-1pu/blob/master/draft-madden-jose-ecdh-1pu-04/draft-madden-jose-ecdh-1pu-04.txt#L740) 1608 // (ietf draft: https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04#appendix-B) 1609 //go:embed testdata/alice_key_ref.json 1610 aliceKeyRef string 1611 //go:embed testdata/bob_key_ref.json 1612 bobKeyRef string 1613 //go:embed testdata/charlie_key_ref.json 1614 charlieKeyRef string 1615 //go:embed testdata/jwe_ref.json 1616 jweRef string 1617 ) 1618 1619 func Test1PUDraft4ExampleBDecrypt(t *testing.T) { 1620 testJWE := trimSpace(jweRef) 1621 aliceKey := trimSpace(aliceKeyRef) 1622 bobKey := trimSpace(bobKeyRef) 1623 charlieKey := trimSpace(charlieKeyRef) 1624 1625 skid := "Alice" 1626 keys := convertX25519ToKH(t, []string{aliceKey, bobKey, charlieKey}, []string{skid, "bob-key-2", "2021-05-06"}) 1627 1628 c, k := createCryptoAndKMSServices(t, keys) 1629 1630 mockStoreMap := make(map[string]mockstorage.DBEntry) 1631 1632 pubKH, err := keys[skid].Public() 1633 require.NoError(t, err) 1634 1635 senderPubKey, err := keyio.ExtractPrimaryPublicKey(pubKH) 1636 require.NoError(t, err) 1637 1638 mSenderPubKey, err := json.Marshal(senderPubKey) 1639 require.NoError(t, err) 1640 1641 mockStoreMap[skid] = mockstorage.DBEntry{Value: mSenderPubKey} 1642 1643 mockStore := &mockstorage.MockStore{ 1644 Store: mockStoreMap, 1645 } 1646 1647 localJWE, err := ariesjose.Deserialize(testJWE) 1648 require.NoError(t, err) 1649 require.NotEmpty(t, localJWE) 1650 1651 dec := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.StoreResolver{Store: mockStore}}, c, k) 1652 require.NotEmpty(t, dec) 1653 1654 pt, err := dec.Decrypt(localJWE) 1655 require.NoError(t, err) 1656 require.EqualValues(t, []byte("Three is a magic number."), pt) 1657 } 1658 1659 func trimSpace(s string) string { 1660 s = strings.ReplaceAll(s, " ", "") 1661 s = strings.ReplaceAll(s, "\n", "") 1662 1663 return s 1664 } 1665 1666 func convertX25519ToKH(t *testing.T, keys, kids []string) map[string]*keyset.Handle { 1667 t.Helper() 1668 1669 var err error 1670 1671 khs := make(map[string]*keyset.Handle) 1672 1673 for i, k := range keys { 1674 delim := ",\"d\"" 1675 idx := strings.Index(k, delim) 1676 mPubKey := k[:idx] + "}" 1677 pubKey := &jwk.JWK{} 1678 err = json.Unmarshal([]byte(mPubKey), pubKey) 1679 require.NoError(t, err) 1680 1681 var d []byte 1682 1683 dVal := k[idx+len(delim)+2 : len(k)-2] 1684 d, err = base64.RawURLEncoding.DecodeString(dVal) 1685 require.NoError(t, err) 1686 1687 privKey := &cryptoapi.PrivateKey{ 1688 PublicKey: cryptoapi.PublicKey{ 1689 X: pubKey.Key.([]byte), 1690 Curve: pubKey.Crv, 1691 Type: pubKey.Kty, 1692 }, 1693 D: d, 1694 } 1695 1696 var kh *keyset.Handle 1697 1698 kh, err = keyio.PrivateKeyToKeysetHandle(privKey, ecdh.XC20P) 1699 require.NoError(t, err) 1700 1701 khs[kids[i]] = kh 1702 } 1703 1704 return khs 1705 }