github.com/trustbloc/kms-go@v1.1.2/crypto/webkms/remotecrypto_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package webkms 8 9 import ( 10 "bytes" 11 "crypto/rand" 12 "crypto/tls" 13 "crypto/x509" 14 "encoding/json" 15 "encoding/pem" 16 "errors" 17 "fmt" 18 "io/ioutil" 19 "net" 20 "net/http" 21 "path/filepath" 22 "runtime" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/google/tink/go/aead" 28 aeadsubtle "github.com/google/tink/go/aead/subtle" 29 "github.com/google/tink/go/core/primitiveset" 30 "github.com/google/tink/go/keyset" 31 "github.com/google/tink/go/mac" 32 "github.com/google/tink/go/signature" 33 "github.com/google/tink/go/subtle/random" 34 "github.com/stretchr/testify/require" 35 "golang.org/x/crypto/chacha20poly1305" 36 37 cryptoapi "github.com/trustbloc/kms-go/spi/crypto" 38 39 "github.com/trustbloc/kms-go/crypto/tinkcrypto" 40 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs" 41 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/ecdh" 42 "github.com/trustbloc/kms-go/kms/localkms" 43 webkmsimpl "github.com/trustbloc/kms-go/kms/webkms" 44 ) 45 46 const ( 47 certPrefix = "../../kms/webkms/testdata/" 48 clientTimeout = 5 * time.Second 49 defaultKeyStoreID = "12345" 50 defaultKID = "99999" 51 ) 52 53 func TestEncryptDecrypt(t *testing.T) { 54 kh, err := keyset.NewHandle(aead.XChaCha20Poly1305KeyTemplate()) 55 require.NoError(t, err) 56 57 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 58 err = processPOSTEncRequest(w, r, kh) 59 require.NoError(t, err) 60 }) 61 62 server, url, client := CreateMockHTTPServerAndClient(t, hf) 63 64 defer func() { 65 e := server.Close() 66 require.NoError(t, e) 67 }() 68 69 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 70 "{serverEndpoint}", url), defaultKeyStoreID) 71 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 72 rCrypto := New(defaultKeystoreURL, client) 73 plaintext := []byte("lorem ipsum") 74 aad := []byte("dolor sit") 75 76 // test successful Encrypt/Decrypt 77 ciphertext, nonce, err := rCrypto.Encrypt(plaintext, aad, defaultKeyURL) 78 require.NoError(t, err) 79 80 decrypted, err := rCrypto.Decrypt(ciphertext, aad, nonce, defaultKeyURL) 81 require.NoError(t, err) 82 require.EqualValues(t, plaintext, decrypted) 83 84 t.Run("Encrypt Post request failure", func(t *testing.T) { 85 blankClient := &http.Client{} 86 tmpCrypto := New(defaultKeystoreURL, blankClient) 87 88 _, _, err = tmpCrypto.Encrypt(plaintext, aad, defaultKeyURL) 89 require.Contains(t, err.Error(), fmt.Sprintf("posting Encrypt plaintext failed [%s, Post \"%s\": %s", 90 defaultKeyURL+encryptURI, defaultKeyURL+encryptURI, getCertsErrorSubText())) 91 92 badURL := "``#$%" 93 _, _, err = tmpCrypto.Encrypt(plaintext, aad, badURL) 94 require.Contains(t, err.Error(), "posting Encrypt plaintext failed") 95 require.EqualError(t, err, fmt.Errorf("posting Encrypt plaintext failed [%s, build request error:"+ 96 " parse \"%s\": invalid URL escape \"%s\"]", badURL+encryptURI, badURL+encryptURI, "%/e").Error()) 97 }) 98 99 t.Run("Decrypt Post request failure", func(t *testing.T) { 100 blankClient := &http.Client{} 101 tmpCrypto := New(defaultKeystoreURL, blankClient) 102 103 _, err = tmpCrypto.Decrypt(nil, aad, nil, defaultKeyURL) 104 require.Contains(t, err.Error(), fmt.Sprintf("posting Decrypt ciphertext failed [%s, Post \"%s\": %s", 105 defaultKeyURL+decryptURI, defaultKeyURL+decryptURI, getCertsErrorSubText())) 106 }) 107 108 t.Run("Encrypt json marshal failure", func(t *testing.T) { 109 remoteCrypto2 := New(defaultKeystoreURL, client) 110 111 remoteCrypto2.marshalFunc = failingMarshal 112 _, _, err = remoteCrypto2.Encrypt(plaintext, aad, defaultKeyURL) 113 require.EqualError(t, err, fmt.Errorf("marshal encryption request for Encrypt failed [%s, %w]", 114 defaultKeyURL+encryptURI, errFailingMarshal).Error()) 115 }) 116 117 t.Run("Encrypt json unmarshal failure", func(t *testing.T) { 118 remoteCrypto2 := New(defaultKeystoreURL, client) 119 120 remoteCrypto2.unmarshalFunc = failingUnmarshal 121 _, _, err = remoteCrypto2.Encrypt(plaintext, aad, defaultKeyURL) 122 require.EqualError(t, err, fmt.Errorf("unmarshal encryption for Encrypt failed [%s, %w]", 123 defaultKeyURL+encryptURI, errFailingUnmarshal).Error()) 124 }) 125 126 t.Run("Decrypt json marshal failure", func(t *testing.T) { 127 remoteCrypto2 := New(defaultKeystoreURL, client) 128 129 remoteCrypto2.marshalFunc = failingMarshal 130 _, err = remoteCrypto2.Decrypt(ciphertext, aad, nonce, defaultKeyURL) 131 require.EqualError(t, err, fmt.Errorf("marshal decryption request for Decrypt failed [%s, %w]", 132 defaultKeyURL+decryptURI, errFailingMarshal).Error()) 133 }) 134 135 t.Run("Decrypt json unmarshal failure", func(t *testing.T) { 136 remoteCrypto2 := New(defaultKeystoreURL, client) 137 138 remoteCrypto2.unmarshalFunc = failingUnmarshal 139 _, err = remoteCrypto2.Decrypt(ciphertext, aad, nonce, defaultKeyURL) 140 require.EqualError(t, err, fmt.Errorf("unmarshal decryption for Decrypt failed [%s, %w]", 141 defaultKeyURL+decryptURI, errFailingUnmarshal).Error()) 142 }) 143 } 144 145 func processPOSTEncRequest(w http.ResponseWriter, r *http.Request, encKH *keyset.Handle) error { 146 if valid := validateHTTPMethod(w, r); !valid { 147 return errors.New("http method invalid") 148 } 149 150 if valid := validatePostPayload(r, w); !valid { 151 return errors.New("http request body invalid") 152 } 153 154 reqBody, err := ioutil.ReadAll(r.Body) 155 if err != nil { 156 return err 157 } 158 159 if matchPath(r, encryptURI) { 160 err = encryptPOSTHandle(w, reqBody, encKH) 161 if err != nil { 162 return err 163 } 164 } 165 166 if matchPath(r, decryptURI) { 167 err = decryptPOSTHandle(w, reqBody, encKH) 168 if err != nil { 169 return err 170 } 171 } 172 173 return nil 174 } 175 176 func encryptPOSTHandle(w http.ResponseWriter, reqBody []byte, encKH *keyset.Handle) error { 177 encReq := &encryptReq{} 178 179 err := json.Unmarshal(reqBody, encReq) 180 if err != nil { 181 return err 182 } 183 184 ps, err := encKH.Primitives() 185 if err != nil { 186 return err 187 } 188 189 a, err := aead.New(encKH) 190 if err != nil { 191 return err 192 } 193 194 ct, err := a.Encrypt(encReq.Message, encReq.AssociatedData) 195 if err != nil { 196 return fmt.Errorf("encrypt msg: %w", err) 197 } 198 199 ivSize := nonceSize(ps) 200 prefixLength := len(ps.Primary.Prefix) 201 cipherText := ct[prefixLength+ivSize:] 202 nonce := ct[prefixLength : prefixLength+ivSize] 203 204 resp := &encryptResp{ 205 Ciphertext: cipherText, 206 Nonce: nonce, 207 } 208 209 mResp, err := json.Marshal(resp) 210 if err != nil { 211 return err 212 } 213 214 _, err = w.Write(mResp) 215 if err != nil { 216 return err 217 } 218 219 return nil 220 } 221 222 func decryptPOSTHandle(w http.ResponseWriter, reqBody []byte, encKH *keyset.Handle) error { 223 decReq := &decryptReq{} 224 225 err := json.Unmarshal(reqBody, decReq) 226 if err != nil { 227 return err 228 } 229 230 ps, err := encKH.Primitives() 231 if err != nil { 232 return err 233 } 234 235 a, err := aead.New(encKH) 236 if err != nil { 237 return err 238 } 239 240 cipher := decReq.Ciphertext 241 nonce := decReq.Nonce 242 243 ct := make([]byte, 0, len(ps.Primary.Prefix)+len(nonce)+len(cipher)) 244 ct = append(ct, ps.Primary.Prefix...) 245 ct = append(ct, nonce...) 246 ct = append(ct, cipher...) 247 248 plaintext, err := a.Decrypt(ct, decReq.AssociatedData) 249 if err != nil { 250 return fmt.Errorf("decrypt cipher: %w", err) 251 } 252 253 resp := &decryptResp{ 254 Plaintext: plaintext, 255 } 256 257 mResp, err := json.Marshal(resp) 258 if err != nil { 259 return err 260 } 261 262 _, err = w.Write(mResp) 263 if err != nil { 264 return err 265 } 266 267 return nil 268 } 269 270 func TestSignVerify(t *testing.T) { 271 kh, err := keyset.NewHandle(signature.ECDSAP384KeyTemplate()) 272 require.NoError(t, err) 273 274 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 275 err = processPOSTSigRequest(w, r, kh) 276 require.NoError(t, err) 277 }) 278 279 server, url, client := CreateMockHTTPServerAndClient(t, hf) 280 281 defer func() { 282 e := server.Close() 283 require.NoError(t, e) 284 }() 285 286 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 287 "{serverEndpoint}", url), defaultKeyStoreID) 288 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 289 rCrypto := New(defaultKeystoreURL, client) 290 msg := []byte("lorem ipsum") 291 292 // test successful Sign/Verify 293 sig, err := rCrypto.Sign(msg, defaultKeyURL) 294 require.NoError(t, err) 295 296 err = rCrypto.Verify(sig, msg, defaultKeyURL) 297 require.NoError(t, err) 298 299 t.Run("Sign Post request failure", func(t *testing.T) { 300 blankClient := &http.Client{} 301 tmpCrypto := New(defaultKeystoreURL, blankClient) 302 303 _, err = tmpCrypto.Sign(nil, defaultKeyURL) 304 require.Contains(t, err.Error(), fmt.Sprintf("posting Sign message failed [%s, Post \"%s\": %s", 305 defaultKeyURL+signURI, defaultKeyURL+signURI, getCertsErrorSubText())) 306 }) 307 308 t.Run("Verify Post request failure", func(t *testing.T) { 309 blankClient := &http.Client{} 310 tmpCrypto := New(defaultKeystoreURL, blankClient) 311 312 err = tmpCrypto.Verify(nil, nil, defaultKeyURL) 313 require.Contains(t, err.Error(), fmt.Sprintf("posting Verify signature failed [%s, Post \"%s\": %s", 314 defaultKeyURL+verifyURI, defaultKeyURL+verifyURI, getCertsErrorSubText())) 315 }) 316 317 t.Run("Sign json marshal failure", func(t *testing.T) { 318 remoteCrypto2 := New(defaultKeystoreURL, client) 319 320 remoteCrypto2.marshalFunc = failingMarshal 321 _, err = remoteCrypto2.Sign(msg, defaultKeyURL) 322 require.EqualError(t, err, fmt.Errorf("marshal signature request for Sign failed [%s, %w]", 323 defaultKeyURL+signURI, errFailingMarshal).Error()) 324 }) 325 326 t.Run("Sign json unmarshal failure", func(t *testing.T) { 327 remoteCrypto2 := New(defaultKeystoreURL, client) 328 329 remoteCrypto2.unmarshalFunc = failingUnmarshal 330 _, err = remoteCrypto2.Sign(msg, defaultKeyURL) 331 require.EqualError(t, err, fmt.Errorf("unmarshal signature for Sign failed [%s, %w]", 332 defaultKeyURL+signURI, errFailingUnmarshal).Error()) 333 }) 334 335 t.Run("Verify json marshal failure", func(t *testing.T) { 336 remoteCrypto2 := New(defaultKeystoreURL, client) 337 338 remoteCrypto2.marshalFunc = failingMarshal 339 err = remoteCrypto2.Verify(sig, msg, defaultKeyURL) 340 require.EqualError(t, err, fmt.Errorf("marshal verify request for Verify failed [%s, %w]", 341 defaultKeyURL+verifyURI, errFailingMarshal).Error()) 342 }) 343 } 344 345 func processPOSTSigRequest(w http.ResponseWriter, r *http.Request, sigKH *keyset.Handle) error { 346 if valid := validateHTTPMethod(w, r); !valid { 347 return errors.New("http method invalid") 348 } 349 350 if valid := validatePostPayload(r, w); !valid { 351 return errors.New("http request body invalid") 352 } 353 354 reqBody, err := ioutil.ReadAll(r.Body) 355 if err != nil { 356 return err 357 } 358 359 if matchPath(r, signURI) { 360 err = signPOSTHandle(w, reqBody, sigKH) 361 if err != nil { 362 return err 363 } 364 } 365 366 if matchPath(r, verifyURI) { 367 err = verifyPOSTHandle(reqBody, sigKH) 368 if err != nil { 369 return err 370 } 371 } 372 373 return nil 374 } 375 376 func signPOSTHandle(w http.ResponseWriter, reqBody []byte, sigKH *keyset.Handle) error { 377 sigReq := &signReq{} 378 379 err := json.Unmarshal(reqBody, sigReq) 380 if err != nil { 381 return err 382 } 383 384 signer, err := signature.NewSigner(sigKH) 385 if err != nil { 386 return fmt.Errorf("create new signer: %w", err) 387 } 388 389 s, err := signer.Sign(sigReq.Message) 390 if err != nil { 391 return fmt.Errorf("sign msg: %w", err) 392 } 393 394 resp := &signResp{ 395 Signature: s, 396 } 397 398 mResp, err := json.Marshal(resp) 399 if err != nil { 400 return err 401 } 402 403 _, err = w.Write(mResp) 404 if err != nil { 405 return err 406 } 407 408 return nil 409 } 410 411 func verifyPOSTHandle(reqBody []byte, sigKH *keyset.Handle) error { 412 verReq := &verifyReq{} 413 414 err := json.Unmarshal(reqBody, verReq) 415 if err != nil { 416 return err 417 } 418 419 pubKH, err := sigKH.Public() 420 if err != nil { 421 return err 422 } 423 424 verifier, err := signature.NewVerifier(pubKH) 425 if err != nil { 426 return fmt.Errorf("create new verifier: %w", err) 427 } 428 429 err = verifier.Verify(verReq.Signature, verReq.Message) 430 if err != nil { 431 return fmt.Errorf("verify msg: %w", err) 432 } 433 434 return nil 435 } 436 437 func TestComputeVerifyMAC(t *testing.T) { 438 kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate()) 439 require.NoError(t, err) 440 441 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 442 err = processPOSTMACRequest(w, r, kh) 443 require.NoError(t, err) 444 }) 445 446 server, url, client := CreateMockHTTPServerAndClient(t, hf) 447 448 defer func() { 449 e := server.Close() 450 require.NoError(t, e) 451 }() 452 453 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 454 "{serverEndpoint}", url), defaultKeyStoreID) 455 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 456 rCrypto := New(defaultKeystoreURL, client, webkmsimpl.WithCache(2)) 457 data := []byte("lorem ipsum") 458 459 // test successful ComputeMAC/VerifyMAC 460 dataMAC, err := rCrypto.ComputeMAC(data, defaultKeyURL) 461 require.NoError(t, err) 462 463 err = rCrypto.VerifyMAC(dataMAC, data, defaultKeyURL) 464 require.NoError(t, err) 465 466 dataMAC, err = rCrypto.ComputeMAC(data, defaultKeyURL) 467 require.NoError(t, err) 468 469 err = rCrypto.VerifyMAC(dataMAC, data, defaultKeyURL) 470 require.NoError(t, err) 471 472 t.Run("ComputeMAC Post request failure", func(t *testing.T) { 473 blankClient := &http.Client{} 474 tmpCrypto := New(defaultKeystoreURL, blankClient) 475 476 _, err = tmpCrypto.ComputeMAC(nil, defaultKeyURL) 477 require.Contains(t, err.Error(), fmt.Sprintf("posting ComputeMAC request failed [%s, Post \"%s\": %s", 478 defaultKeyURL+computeMACURI, defaultKeyURL+computeMACURI, getCertsErrorSubText())) 479 }) 480 481 t.Run("VerifyMAC Post request failure", func(t *testing.T) { 482 blankClient := &http.Client{} 483 tmpCrypto := New(defaultKeystoreURL, blankClient) 484 485 err = tmpCrypto.VerifyMAC(nil, nil, defaultKeyURL) 486 require.Contains(t, err.Error(), fmt.Sprintf("posting VerifyMAC request failed [%s, Post \"%s\": %s", 487 defaultKeyURL+verifyMACURI, defaultKeyURL+verifyMACURI, getCertsErrorSubText())) 488 }) 489 490 t.Run("ComputeMAC json marshal failure", func(t *testing.T) { 491 remoteCrypto2 := New(defaultKeystoreURL, client) 492 493 remoteCrypto2.marshalFunc = failingMarshal 494 _, err = remoteCrypto2.ComputeMAC(data, defaultKeyURL) 495 require.EqualError(t, err, fmt.Errorf("marshal request for ComputeMAC failed [%s, %w]", 496 defaultKeyURL+computeMACURI, errFailingMarshal).Error()) 497 }) 498 499 t.Run("ComputeMAC json unmarshal failure", func(t *testing.T) { 500 remoteCrypto2 := New(defaultKeystoreURL, client) 501 502 remoteCrypto2.unmarshalFunc = failingUnmarshal 503 _, err = remoteCrypto2.ComputeMAC(data, defaultKeyURL) 504 require.EqualError(t, err, fmt.Errorf("unmarshal ComputeMAC response failed [%s, %w]", 505 defaultKeyURL+computeMACURI, errFailingUnmarshal).Error()) 506 }) 507 508 t.Run("VerifyMAC json marshal failure", func(t *testing.T) { 509 remoteCrypto2 := New(defaultKeystoreURL, client) 510 511 remoteCrypto2.marshalFunc = failingMarshal 512 err = remoteCrypto2.VerifyMAC(dataMAC, data, defaultKeyURL) 513 require.EqualError(t, err, fmt.Errorf("marshal request for VerifyMAC failed [%s, %w]", 514 defaultKeyURL+verifyMACURI, errFailingMarshal).Error()) 515 }) 516 } 517 518 func processPOSTMACRequest(w http.ResponseWriter, r *http.Request, macKH *keyset.Handle) error { 519 if valid := validateHTTPMethod(w, r); !valid { 520 return errors.New("http method invalid") 521 } 522 523 if valid := validatePostPayload(r, w); !valid { 524 return errors.New("http request body invalid") 525 } 526 527 reqBody, err := ioutil.ReadAll(r.Body) 528 if err != nil { 529 return err 530 } 531 532 if matchPath(r, computeMACURI) { 533 err = computeMACPOSTHandle(w, reqBody, macKH) 534 if err != nil { 535 return err 536 } 537 } 538 539 if matchPath(r, verifyMACURI) { 540 err = verifyMACPOSTHandle(reqBody, macKH) 541 if err != nil { 542 return err 543 } 544 } 545 546 return nil 547 } 548 549 func computeMACPOSTHandle(w http.ResponseWriter, reqBody []byte, macKH *keyset.Handle) error { 550 macReq := &computeMACReq{} 551 552 err := json.Unmarshal(reqBody, macReq) 553 if err != nil { 554 return err 555 } 556 557 macPrimitive, err := mac.New(macKH) 558 if err != nil { 559 return err 560 } 561 562 dataMAC, err := macPrimitive.ComputeMAC(macReq.Data) 563 if err != nil { 564 return err 565 } 566 567 resp := &computeMACResp{ 568 MAC: dataMAC, 569 } 570 571 mResp, err := json.Marshal(resp) 572 if err != nil { 573 return err 574 } 575 576 _, err = w.Write(mResp) 577 if err != nil { 578 return err 579 } 580 581 return nil 582 } 583 584 func verifyMACPOSTHandle(reqBody []byte, macKH *keyset.Handle) error { 585 verReq := &verifyMACReq{} 586 587 err := json.Unmarshal(reqBody, verReq) 588 if err != nil { 589 return err 590 } 591 592 macPrimitive, err := mac.New(macKH) 593 if err != nil { 594 return err 595 } 596 597 err = macPrimitive.VerifyMAC(verReq.MAC, verReq.Data) 598 if err != nil { 599 return fmt.Errorf("verify mac: %w", err) 600 } 601 602 return nil 603 } 604 605 func TestWrapUnWrapKey(t *testing.T) { 606 senderKID := "11111" 607 608 recipientKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 609 require.NoError(t, err) 610 611 recipentPubKey, err := exportPubKey(recipientKH) 612 require.NoError(t, err) 613 614 senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 615 require.NoError(t, err) 616 617 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 618 err = processPOSTWrapRequest(w, r, senderKH, recipientKH) 619 require.NoError(t, err) 620 }) 621 622 server, url, client := CreateMockHTTPServerAndClient(t, hf) 623 624 defer func() { 625 e := server.Close() 626 require.NoError(t, e) 627 }() 628 629 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 630 "{serverEndpoint}", url), defaultKeyStoreID) 631 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 632 rCrypto := New(defaultKeystoreURL, client) 633 cek := random.GetRandomBytes(uint32(32)) 634 apu := []byte("bob") 635 apv := []byte("alice") 636 637 // Test successful WrapKey/UnwrapKey 638 wKey, err := rCrypto.WrapKey(cek, apu, apv, recipentPubKey) 639 require.NoError(t, err) 640 641 decryptedCEK, err := rCrypto.UnwrapKey(wKey, defaultKeyURL) 642 require.NoError(t, err) 643 require.EqualValues(t, cek, decryptedCEK) 644 645 t.Run("WrapKey Post request failure", func(t *testing.T) { 646 blankClient := &http.Client{} 647 tmpCrypto := New(defaultKeystoreURL, blankClient) 648 649 _, err = tmpCrypto.WrapKey(cek, apu, apv, recipentPubKey) 650 require.Contains(t, err.Error(), fmt.Sprintf("posting WrapKey failed [%s, Post \"%s\": %s", 651 defaultKeystoreURL+wrapURI, defaultKeystoreURL+wrapURI, getCertsErrorSubText())) 652 }) 653 654 t.Run("UnwrapKey Post request failure", func(t *testing.T) { 655 blankClient := &http.Client{} 656 tmpCrypto := New(defaultKeystoreURL, blankClient) 657 658 _, err = tmpCrypto.UnwrapKey(wKey, defaultKeyURL) 659 require.Contains(t, err.Error(), fmt.Sprintf("posting UnwrapKey failed [%s, Post \"%s\": %s", 660 defaultKeyURL+unwrapURI, defaultKeyURL+unwrapURI, getCertsErrorSubText())) 661 }) 662 663 t.Run("WrapKey json marshal failure", func(t *testing.T) { 664 remoteCrypto2 := New(defaultKeystoreURL, client) 665 666 remoteCrypto2.marshalFunc = failingMarshal 667 _, err = remoteCrypto2.WrapKey(cek, apu, apv, recipentPubKey) 668 require.EqualError(t, err, fmt.Errorf("marshal wrapKeyReq for WrapKey failed [%s, %w]", 669 defaultKeystoreURL+wrapURI, errFailingMarshal).Error()) 670 }) 671 672 t.Run("WrapKey json unmarshal failure", func(t *testing.T) { 673 remoteCrypto2 := New(defaultKeystoreURL, client) 674 675 remoteCrypto2.unmarshalFunc = failingUnmarshal 676 _, err = remoteCrypto2.WrapKey(cek, apu, apv, recipentPubKey) 677 require.EqualError(t, err, fmt.Errorf("unmarshal wrapKeyResp for WrapKey failed [%s, %w]", 678 defaultKeystoreURL+wrapURI, errFailingUnmarshal).Error()) 679 }) 680 681 t.Run("UnwrapKey json unmarshal failure", func(t *testing.T) { 682 remoteCrypto2 := New(defaultKeystoreURL, client) 683 684 remoteCrypto2.unmarshalFunc = failingUnmarshal 685 _, err = remoteCrypto2.UnwrapKey(wKey, defaultKeyURL) 686 require.EqualError(t, err, fmt.Errorf("unmarshal unwrapKeyResp for UnwrapKey failed [%s, %w]", 687 defaultKeyURL+unwrapURI, errFailingUnmarshal).Error()) 688 }) 689 690 t.Run("Unwrap json marshal failure", func(t *testing.T) { 691 remoteCrypto2 := New(defaultKeystoreURL, client) 692 693 remoteCrypto2.marshalFunc = failingMarshal 694 _, err = remoteCrypto2.UnwrapKey(wKey, defaultKeyURL) 695 require.EqualError(t, err, fmt.Errorf("marshal unwrapKeyReq for UnwrapKey failed [%s, %w]", 696 defaultKeyURL+unwrapURI, errFailingMarshal).Error()) 697 }) 698 699 t.Run("Wrap/Unwrap successful with Sender key (authcrypt)", func(t *testing.T) { 700 wrappedKey, err := rCrypto.WrapKey(cek, apu, apv, recipentPubKey, cryptoapi.WithSender(senderKID)) 701 require.NoError(t, err) 702 703 dCEK, err := rCrypto.UnwrapKey(wrappedKey, defaultKeyURL, cryptoapi.WithSender(&cryptoapi.PublicKey{})) 704 require.NoError(t, err) 705 require.EqualValues(t, cek, dCEK) 706 }) 707 708 t.Run("Wrap/Unwrap with Sender key option containing empty key", func(t *testing.T) { 709 wrappedKey, err := rCrypto.WrapKey(cek, apu, apv, recipentPubKey, cryptoapi.WithSender("")) 710 require.NoError(t, err) 711 712 dCEK, err := rCrypto.UnwrapKey(wrappedKey, defaultKeyURL) 713 require.NoError(t, err) 714 require.EqualValues(t, cek, dCEK) 715 }) 716 717 t.Run("Wrap/Unwrap with Sender key option containing nil key", func(t *testing.T) { 718 wrappedKey, err := rCrypto.WrapKey(cek, apu, apv, recipentPubKey, cryptoapi.WithSender(nil)) 719 require.NoError(t, err) 720 721 dCEK, err := rCrypto.UnwrapKey(wrappedKey, defaultKeyURL, cryptoapi.WithSender(nil)) 722 require.NoError(t, err) 723 require.EqualValues(t, cek, dCEK) 724 }) 725 } 726 727 func TestRemoteCryptoWithHeadersFunc(t *testing.T) { 728 recipientKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 729 require.NoError(t, err) 730 731 recipentPubKey, err := exportPubKey(recipientKH) 732 require.NoError(t, err) 733 734 senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate()) 735 require.NoError(t, err) 736 737 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 738 err = processPOSTWrapRequest(w, r, senderKH, recipientKH) 739 require.NoError(t, err) 740 }) 741 742 server, url, client := CreateMockHTTPServerAndClient(t, hf) 743 744 defer func() { 745 e := server.Close() 746 require.NoError(t, e) 747 }() 748 749 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 750 "{serverEndpoint}", url), defaultKeyStoreID) 751 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 752 753 t.Run("New remote crypto using WithHeaders with success function", func(t *testing.T) { 754 rCrypto := New(defaultKeystoreURL, client, webkmsimpl.WithHeaders(mockAddHeadersFuncSuccess)) 755 cek := random.GetRandomBytes(uint32(32)) 756 apu := []byte("bob") 757 apv := []byte("alice") 758 759 // Test successful WrapKey/UnwrapKey 760 wKey, e := rCrypto.WrapKey(cek, apu, apv, recipentPubKey) 761 require.NoError(t, e) 762 763 decryptedCEK, e := rCrypto.UnwrapKey(wKey, defaultKeyURL) 764 require.NoError(t, e) 765 require.EqualValues(t, cek, decryptedCEK) 766 }) 767 768 t.Run("New remote crypto using WithHeaders with error function", func(t *testing.T) { 769 rCrypto := New(defaultKeystoreURL, client, webkmsimpl.WithHeaders(mockAddHeadersFuncError)) 770 cek := random.GetRandomBytes(uint32(32)) 771 apu := []byte("bob") 772 apv := []byte("alice") 773 774 // Test successful WrapKey/UnwrapKey 775 _, err = rCrypto.WrapKey(cek, apu, apv, recipentPubKey) 776 require.EqualError(t, err, fmt.Errorf("posting WrapKey failed [%s%s, add optional request "+ 777 "headers error: %w]", defaultKeystoreURL, wrapURI, errAddHeadersFunc).Error()) 778 779 wKey := &cryptoapi.RecipientWrappedKey{ 780 KID: "1", 781 EncryptedCEK: []byte("111"), 782 EPK: cryptoapi.PublicKey{}, 783 Alg: "zlg", 784 APU: []byte("bob"), 785 APV: []byte("Alice"), 786 } 787 788 _, err = rCrypto.UnwrapKey(wKey, defaultKeyURL) 789 require.EqualError(t, err, fmt.Errorf("posting UnwrapKey failed [%s%s, add optional request "+ 790 "headers error: %w]", defaultKeyURL, unwrapURI, errAddHeadersFunc).Error()) 791 }) 792 } 793 794 func exportPubKey(kh *keyset.Handle) (*cryptoapi.PublicKey, error) { 795 pubKH, err := kh.Public() 796 if err != nil { 797 return nil, fmt.Errorf("exportPubKey: failed to get public keyset handle: %w", err) 798 } 799 800 buf := new(bytes.Buffer) 801 pubKeyWriter := localkms.NewWriter(buf) 802 803 err = pubKH.WriteWithNoSecrets(pubKeyWriter) 804 if err != nil { 805 return nil, fmt.Errorf("exportPubKey: failed to create keyset with no secrets (public "+ 806 "key material): %w", err) 807 } 808 809 recPubKey := &cryptoapi.PublicKey{} 810 811 err = json.Unmarshal(buf.Bytes(), recPubKey) 812 if err != nil { 813 return nil, fmt.Errorf("exportPubKey: failed to unmarshal public key: %w", err) 814 } 815 816 return recPubKey, nil 817 } 818 819 func processPOSTWrapRequest(w http.ResponseWriter, r *http.Request, senderKH, recKH *keyset.Handle) error { 820 if valid := validateHTTPMethod(w, r); !valid { 821 return errors.New("http method invalid") 822 } 823 824 if valid := validatePostPayload(r, w); !valid { 825 return errors.New("http request body invalid") 826 } 827 828 reqBody, err := ioutil.ReadAll(r.Body) 829 if err != nil { 830 return err 831 } 832 833 cr, err := tinkcrypto.New() 834 if err != nil { 835 return err 836 } 837 838 if matchPath(r, wrapURI) { 839 if strings.Contains(r.URL.Path, keysURI+"/") { 840 // URL contains sender key id and has form "keystorepath/keys/{senderKeyId}/wrap" 841 err = wrapKeyPostHandle(w, reqBody, senderKH, cr) 842 } else { 843 err = wrapKeyPostHandle(w, reqBody, nil, cr) 844 } 845 846 if err != nil { 847 return err 848 } 849 } 850 851 if matchPath(r, unwrapURI) { 852 err = unwrapKeyPostHandle(w, reqBody, senderKH, recKH, cr) 853 if err != nil { 854 return err 855 } 856 } 857 858 return nil 859 } 860 861 func wrapKeyPostHandle(w http.ResponseWriter, reqBody []byte, senderKH *keyset.Handle, cr cryptoapi.Crypto) error { 862 wrapReq := &wrapKeyReq{} 863 864 err := json.Unmarshal(reqBody, wrapReq) 865 if err != nil { 866 return err 867 } 868 869 wk, err := buildRecipientWK(wrapReq.CEK, wrapReq.APU, wrapReq.APV, senderKH, wrapReq, cr) 870 if err != nil { 871 return err 872 } 873 874 resp := &wrapKeyResp{ 875 RecipientWrappedKey: *wk, 876 } 877 878 mResp, err := json.Marshal(resp) 879 if err != nil { 880 return err 881 } 882 883 _, err = w.Write(mResp) 884 if err != nil { 885 return err 886 } 887 888 return nil 889 } 890 891 func buildRecipientWK(cek, apu, apv []byte, senderKH *keyset.Handle, wrapReq *wrapKeyReq, 892 cr cryptoapi.Crypto) (*cryptoapi.RecipientWrappedKey, error) { 893 var ( 894 wk *cryptoapi.RecipientWrappedKey 895 opt cryptoapi.WrapKeyOpts 896 err error 897 ) 898 899 if senderKH != nil { 900 opt = cryptoapi.WithSender(senderKH) 901 902 wk, err = cr.WrapKey(cek, apu, apv, wrapReq.RecipientPubKey, opt) 903 if err != nil { 904 return nil, err 905 } 906 } else { 907 wk, err = cr.WrapKey(cek, apu, apv, wrapReq.RecipientPubKey) 908 if err != nil { 909 return nil, err 910 } 911 } 912 913 return wk, nil 914 } 915 916 func unwrapKeyPostHandle(w http.ResponseWriter, reqBody []byte, senderKH, recKH *keyset.Handle, 917 cr cryptoapi.Crypto) error { 918 unwrapReq := &unwrapKeyReq{} 919 920 err := json.Unmarshal(reqBody, unwrapReq) 921 if err != nil { 922 return err 923 } 924 925 var opt cryptoapi.WrapKeyOpts 926 927 var cek []byte 928 929 if unwrapReq.SenderPubKey != nil { 930 opt = cryptoapi.WithSender(senderKH) 931 932 cek, err = cr.UnwrapKey(&unwrapReq.WrappedKey, recKH, opt) 933 if err != nil { 934 return err 935 } 936 } else { 937 cek, err = cr.UnwrapKey(&unwrapReq.WrappedKey, recKH) 938 if err != nil { 939 return err 940 } 941 } 942 943 resp := &unwrapKeyResp{ 944 Key: cek, 945 } 946 947 mResp, err := json.Marshal(resp) 948 if err != nil { 949 return err 950 } 951 952 _, err = w.Write(mResp) 953 if err != nil { 954 return err 955 } 956 957 return nil 958 } 959 960 func TestBBSSignVerify_DeriveProofVerifyProof(t *testing.T) { 961 kh, err := keyset.NewHandle(bbs.BLS12381G2KeyTemplate()) 962 require.NoError(t, err) 963 964 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 965 err = processBBSPOSTRequest(w, r, kh) 966 require.NoError(t, err) 967 }) 968 969 server, url, client := CreateMockHTTPServerAndClient(t, hf) 970 971 defer func() { 972 e := server.Close() 973 require.NoError(t, e) 974 }() 975 976 defaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 977 "{serverEndpoint}", url), defaultKeyStoreID) 978 defaultKeyURL := defaultKeystoreURL + "/keys/" + defaultKID 979 rCrypto := New(defaultKeystoreURL, client) 980 msg := [][]byte{[]byte("lorem ipsum"), []byte("dolor sit amet,"), []byte("consectetur adipiscing elit,")} 981 982 nonce := make([]byte, 32) 983 984 _, err = rand.Read(nonce) 985 require.NoError(t, err) 986 987 // test successful BBS+ Sign/Verify/DeriveProof/VerifyProof 988 sig, err := rCrypto.SignMulti(msg, defaultKeyURL) 989 require.NoError(t, err) 990 991 err = rCrypto.VerifyMulti(msg, sig, defaultKeyURL) 992 require.NoError(t, err) 993 994 proof, err := rCrypto.DeriveProof(msg, sig, nonce, []int{1, 2}, defaultKeyURL) 995 require.NoError(t, err) 996 997 err = rCrypto.VerifyProof([][]byte{msg[1], msg[2]}, proof, nonce, defaultKeyURL) 998 require.NoError(t, err) 999 1000 t.Run("BBS+ Sign Post request failure", func(t *testing.T) { 1001 blankClient := &http.Client{} 1002 tmpCrypto := New(defaultKeystoreURL, blankClient) 1003 1004 _, err = tmpCrypto.SignMulti(nil, defaultKeyURL) 1005 require.Contains(t, err.Error(), fmt.Sprintf("posting BBS+ Sign message failed [%s, Post \"%s\": %s", 1006 defaultKeyURL+signMultiURI, defaultKeyURL+signMultiURI, getCertsErrorSubText())) 1007 }) 1008 1009 t.Run("BBS+ Verify Post request failure", func(t *testing.T) { 1010 blankClient := &http.Client{} 1011 tmpCrypto := New(defaultKeystoreURL, blankClient) 1012 1013 err = tmpCrypto.VerifyMulti(nil, nil, defaultKeyURL) 1014 require.Contains(t, err.Error(), fmt.Sprintf("posting BBS+ Verify signature failed [%s, Post \"%s\": %s", 1015 defaultKeyURL+verifyMultiURI, defaultKeyURL+verifyMultiURI, getCertsErrorSubText())) 1016 }) 1017 1018 t.Run("BBS+ Derive Proof Post request failure", func(t *testing.T) { 1019 blankClient := &http.Client{} 1020 tmpCrypto := New(defaultKeystoreURL, blankClient) 1021 1022 _, err = tmpCrypto.DeriveProof(nil, nil, nil, nil, defaultKeyURL) 1023 require.Contains(t, err.Error(), fmt.Sprintf("posting BBS+ Derive proof message failed [%s, Post \"%s\": %s", 1024 defaultKeyURL+deriveProofURI, defaultKeyURL+deriveProofURI, getCertsErrorSubText())) 1025 }) 1026 1027 t.Run("BBS+ Verify Proof Post request failure", func(t *testing.T) { 1028 blankClient := &http.Client{} 1029 tmpCrypto := New(defaultKeystoreURL, blankClient) 1030 1031 err = tmpCrypto.VerifyProof(nil, nil, nil, defaultKeyURL) 1032 require.Contains(t, err.Error(), fmt.Sprintf("posting BBS+ Verify proof failed [%s, Post \"%s\": %s", 1033 defaultKeyURL+verifyProofURI, defaultKeyURL+verifyProofURI, getCertsErrorSubText())) 1034 }) 1035 1036 t.Run("BBS+ Sign json marshal failure", func(t *testing.T) { 1037 remoteCrypto2 := New(defaultKeystoreURL, client) 1038 1039 remoteCrypto2.marshalFunc = failingMarshal 1040 _, err = remoteCrypto2.SignMulti(msg, defaultKeyURL) 1041 require.EqualError(t, err, fmt.Errorf("marshal signature request for BBS+ Sign failed [%s, %w]", 1042 defaultKeyURL+signMultiURI, errFailingMarshal).Error()) 1043 }) 1044 1045 t.Run("BBS+ Sign json unmarshal failure", func(t *testing.T) { 1046 remoteCrypto2 := New(defaultKeystoreURL, client) 1047 1048 remoteCrypto2.unmarshalFunc = failingUnmarshal 1049 _, err = remoteCrypto2.SignMulti(msg, defaultKeyURL) 1050 require.EqualError(t, err, fmt.Errorf("unmarshal signature for BBS+ Sign failed [%s, %w]", 1051 defaultKeyURL+signMultiURI, errFailingUnmarshal).Error()) 1052 }) 1053 1054 t.Run("BBS+ Verify json marshal failure", func(t *testing.T) { 1055 remoteCrypto2 := New(defaultKeystoreURL, client) 1056 1057 remoteCrypto2.marshalFunc = failingMarshal 1058 err = remoteCrypto2.VerifyMulti(msg, sig, defaultKeyURL) 1059 require.EqualError(t, err, fmt.Errorf("marshal verify request for BBS+ Verify failed [%s, %w]", 1060 defaultKeyURL+verifyMultiURI, errFailingMarshal).Error()) 1061 }) 1062 1063 t.Run("BBS+ Derive Proof json marshal failure", func(t *testing.T) { 1064 remoteCrypto2 := New(defaultKeystoreURL, client) 1065 1066 remoteCrypto2.marshalFunc = failingMarshal 1067 _, err = remoteCrypto2.DeriveProof(msg, sig, nonce, []int{0}, defaultKeyURL) 1068 require.EqualError(t, err, fmt.Errorf("marshal request for BBS+ Derive proof failed [%s, %w]", 1069 defaultKeyURL+deriveProofURI, errFailingMarshal).Error()) 1070 }) 1071 1072 t.Run("BBS+ Derive Proof json unmarshal failure", func(t *testing.T) { 1073 remoteCrypto2 := New(defaultKeystoreURL, client) 1074 1075 remoteCrypto2.unmarshalFunc = failingUnmarshal 1076 _, err = remoteCrypto2.DeriveProof(msg, sig, nonce, []int{0}, defaultKeyURL) 1077 require.EqualError(t, err, fmt.Errorf("unmarshal request for BBS+ Derive proof failed [%s, %w]", 1078 defaultKeyURL+deriveProofURI, errFailingUnmarshal).Error()) 1079 }) 1080 1081 t.Run("BBS+ Verify Proof json marshal failure", func(t *testing.T) { 1082 remoteCrypto2 := New(defaultKeystoreURL, client) 1083 1084 remoteCrypto2.marshalFunc = failingMarshal 1085 err = remoteCrypto2.VerifyProof([][]byte{msg[1], msg[2]}, proof, nonce, defaultKeyURL) 1086 require.EqualError(t, err, fmt.Errorf("marshal request for BBS+ Verify proof failed [%s, %w]", 1087 defaultKeyURL+verifyProofURI, errFailingMarshal).Error()) 1088 }) 1089 } 1090 1091 func TestNonOKStatusCode(t *testing.T) { 1092 aad := []byte("dolor sit") 1093 1094 nonOKServer, nonOkURL, nonOKClient := CreateMockHTTPServerAndClientNotOKStatusCode(t) 1095 1096 defer func() { 1097 e := nonOKServer.Close() 1098 require.NoError(t, e) 1099 }() 1100 1101 nonOKDefaultKeystoreURL := fmt.Sprintf("%s/%s", strings.ReplaceAll(webkmsimpl.KeystoreEndpoint, 1102 "{serverEndpoint}", nonOkURL), defaultKeyStoreID) 1103 nonOKDefaultKeyURL := nonOKDefaultKeystoreURL + "/keys/" + defaultKID 1104 1105 t.Run("Encrypt Post request failure 501", func(t *testing.T) { 1106 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1107 1108 _, _, err := tmpCrypto.Encrypt(nil, aad, nonOKDefaultKeyURL) 1109 require.Contains(t, err.Error(), "501") 1110 }) 1111 1112 t.Run("Decrypt Post request failure 501", func(t *testing.T) { 1113 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1114 1115 _, err := tmpCrypto.Decrypt(nil, aad, nil, nonOKDefaultKeyURL) 1116 require.Contains(t, err.Error(), "501") 1117 }) 1118 1119 t.Run("Sign Post request failure 501", func(t *testing.T) { 1120 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1121 1122 _, err := tmpCrypto.Sign([]byte("Test message"), nonOKDefaultKeyURL) 1123 require.Contains(t, err.Error(), "501") 1124 }) 1125 1126 t.Run("Verify Post request failure 501", func(t *testing.T) { 1127 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1128 1129 err := tmpCrypto.Verify([]byte{}, []byte("Test message"), nonOKDefaultKeyURL) 1130 require.Contains(t, err.Error(), "501") 1131 }) 1132 1133 t.Run("ComputeMAC Post request failure 501", func(t *testing.T) { 1134 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1135 1136 _, err := tmpCrypto.ComputeMAC([]byte("Test message"), nonOKDefaultKeyURL) 1137 require.Contains(t, err.Error(), "501") 1138 }) 1139 1140 t.Run("VerifyMAC Post request failure 501", func(t *testing.T) { 1141 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1142 1143 err := tmpCrypto.VerifyMAC([]byte{}, []byte("Test message"), nonOKDefaultKeyURL) 1144 require.Contains(t, err.Error(), "501") 1145 }) 1146 1147 t.Run("SignMulti Post request failure 501", func(t *testing.T) { 1148 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1149 1150 _, err := tmpCrypto.SignMulti([][]byte{ 1151 []byte("Test message 1"), 1152 []byte("Test message 2"), 1153 }, nonOKDefaultKeyURL) 1154 require.Contains(t, err.Error(), "501") 1155 }) 1156 1157 t.Run("VerifyMAC Post request failure 501", func(t *testing.T) { 1158 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1159 1160 err := tmpCrypto.VerifyMulti([][]byte{ 1161 []byte("Test message 1"), 1162 []byte("Test message 2"), 1163 }, []byte{}, nonOKDefaultKeyURL) 1164 require.Contains(t, err.Error(), "501") 1165 }) 1166 1167 t.Run("WrapKey Post request failure 501", func(t *testing.T) { 1168 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1169 1170 _, err := tmpCrypto.WrapKey([]byte{}, []byte{}, []byte{}, nil) 1171 require.Contains(t, err.Error(), "501") 1172 }) 1173 1174 t.Run("UnwrapKey Post request failure 501", func(t *testing.T) { 1175 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1176 1177 _, err := tmpCrypto.UnwrapKey(&cryptoapi.RecipientWrappedKey{}, nonOKDefaultKeyURL) 1178 require.Contains(t, err.Error(), "501") 1179 }) 1180 1181 t.Run("DeriveProof Post request failure 501", func(t *testing.T) { 1182 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1183 1184 _, err := tmpCrypto.DeriveProof([][]byte{ 1185 []byte("Test message 1"), 1186 []byte("Test message 2"), 1187 }, []byte{}, []byte{}, []int{}, nonOKDefaultKeyURL) 1188 require.Contains(t, err.Error(), "501") 1189 }) 1190 1191 t.Run("VerifyProof Post request failure 501", func(t *testing.T) { 1192 tmpCrypto := New(nonOKDefaultKeyURL, nonOKClient) 1193 1194 err := tmpCrypto.VerifyProof([][]byte{ 1195 []byte("Test message 1"), 1196 []byte("Test message 2"), 1197 }, []byte{}, []byte{}, nonOKDefaultKeyURL) 1198 require.Contains(t, err.Error(), "501") 1199 }) 1200 } 1201 1202 // nolint:gocyclo 1203 func processBBSPOSTRequest(w http.ResponseWriter, r *http.Request, sigKH *keyset.Handle) error { 1204 if valid := validateHTTPMethod(w, r); !valid { 1205 return errors.New("http method invalid") 1206 } 1207 1208 if valid := validatePostPayload(r, w); !valid { 1209 return errors.New("http request body invalid") 1210 } 1211 1212 reqBody, err := ioutil.ReadAll(r.Body) 1213 if err != nil { 1214 return err 1215 } 1216 1217 if matchPath(r, signMultiURI) { 1218 err = bbsSignPOSTHandle(w, reqBody, sigKH) 1219 if err != nil { 1220 return err 1221 } 1222 } 1223 1224 if matchPath(r, verifyMultiURI) { 1225 err = bbsVerifyPOSTHandle(reqBody, sigKH) 1226 if err != nil { 1227 return err 1228 } 1229 } 1230 1231 if matchPath(r, deriveProofURI) { 1232 err = bbsDeriveProofPOSTHandle(w, reqBody, sigKH) 1233 if err != nil { 1234 return err 1235 } 1236 } 1237 1238 if matchPath(r, verifyProofURI) { 1239 err = bbsVerifyProofPOSTHandle(reqBody, sigKH) 1240 if err != nil { 1241 return err 1242 } 1243 } 1244 1245 return nil 1246 } 1247 1248 func bbsSignPOSTHandle(w http.ResponseWriter, reqBody []byte, sigKH *keyset.Handle) error { 1249 sigReq := &signMultiReq{} 1250 1251 err := json.Unmarshal(reqBody, sigReq) 1252 if err != nil { 1253 return err 1254 } 1255 1256 signer, err := bbs.NewSigner(sigKH) 1257 if err != nil { 1258 return fmt.Errorf("create new signer: %w", err) 1259 } 1260 1261 s, err := signer.Sign(sigReq.Messages) 1262 if err != nil { 1263 return fmt.Errorf("sign msg: %w", err) 1264 } 1265 1266 resp := &signResp{ 1267 Signature: s, 1268 } 1269 1270 mResp, err := json.Marshal(resp) 1271 if err != nil { 1272 return err 1273 } 1274 1275 _, err = w.Write(mResp) 1276 if err != nil { 1277 return err 1278 } 1279 1280 return nil 1281 } 1282 1283 func bbsVerifyPOSTHandle(reqBody []byte, sigKH *keyset.Handle) error { 1284 verReq := &verifyMultiReq{} 1285 1286 err := json.Unmarshal(reqBody, verReq) 1287 if err != nil { 1288 return err 1289 } 1290 1291 pubKH, err := sigKH.Public() 1292 if err != nil { 1293 return err 1294 } 1295 1296 verifier, err := bbs.NewVerifier(pubKH) 1297 if err != nil { 1298 return fmt.Errorf("create new BBS+ verifier: %w", err) 1299 } 1300 1301 err = verifier.Verify(verReq.Messages, verReq.Signature) 1302 if err != nil { 1303 return fmt.Errorf("BBS+ verify msg: %w", err) 1304 } 1305 1306 return nil 1307 } 1308 1309 func bbsDeriveProofPOSTHandle(w http.ResponseWriter, reqBody []byte, sigKH *keyset.Handle) error { 1310 deriveProofReq := &deriveProofReq{} 1311 1312 err := json.Unmarshal(reqBody, deriveProofReq) 1313 if err != nil { 1314 return err 1315 } 1316 1317 pubKH, err := sigKH.Public() 1318 if err != nil { 1319 return err 1320 } 1321 1322 verifier, err := bbs.NewVerifier(pubKH) 1323 if err != nil { 1324 return fmt.Errorf("create new BBS+ verifier: %w", err) 1325 } 1326 1327 proof, err := verifier.DeriveProof(deriveProofReq.Messages, 1328 deriveProofReq.Signature, 1329 deriveProofReq.Nonce, 1330 deriveProofReq.RevealedIndexes) 1331 if err != nil { 1332 return fmt.Errorf("BBS+ derive proof msg: %w", err) 1333 } 1334 1335 resp := &deriveProofResp{ 1336 Proof: proof, 1337 } 1338 1339 mResp, err := json.Marshal(resp) 1340 if err != nil { 1341 return err 1342 } 1343 1344 _, err = w.Write(mResp) 1345 if err != nil { 1346 return err 1347 } 1348 1349 return nil 1350 } 1351 1352 func bbsVerifyProofPOSTHandle(reqBody []byte, sigKH *keyset.Handle) error { 1353 verifyProofReq := &verifyProofReq{} 1354 1355 err := json.Unmarshal(reqBody, verifyProofReq) 1356 if err != nil { 1357 return err 1358 } 1359 1360 pubKH, err := sigKH.Public() 1361 if err != nil { 1362 return err 1363 } 1364 1365 verifier, err := bbs.NewVerifier(pubKH) 1366 if err != nil { 1367 return fmt.Errorf("create new BBS+ verifier: %w", err) 1368 } 1369 1370 err = verifier.VerifyProof(verifyProofReq.Messages, verifyProofReq.Proof, verifyProofReq.Nonce) 1371 if err != nil { 1372 return fmt.Errorf("BBS+ verify proof msg: %w", err) 1373 } 1374 1375 return nil 1376 } 1377 1378 func TestCloseResponseBody(t *testing.T) { 1379 closeResponseBody(&errFailingCloser{}, "testing close fail should log: errFailingCloser always fails") 1380 } 1381 1382 func nonceSize(ps *primitiveset.PrimitiveSet) int { 1383 var ivSize int 1384 // AES256GCM and XChacha20Poly1305 nonce sizes supported only for now 1385 switch ps.Primary.Primitive.(type) { 1386 case *aeadsubtle.XChaCha20Poly1305: 1387 ivSize = chacha20poly1305.NonceSizeX 1388 case *aeadsubtle.AESGCM: 1389 ivSize = aeadsubtle.AESGCMIVSize 1390 default: 1391 ivSize = aeadsubtle.AESGCMIVSize 1392 } 1393 1394 return ivSize 1395 } 1396 1397 // validateHTTPMethod validate HTTP method and content-type. 1398 func validateHTTPMethod(w http.ResponseWriter, r *http.Request) bool { 1399 switch r.Method { 1400 case http.MethodPost, http.MethodGet: 1401 default: 1402 http.Error(w, "HTTP Method not allowed", http.StatusMethodNotAllowed) 1403 return false 1404 } 1405 1406 ct := r.Header.Get("Content-type") 1407 if ct != webkmsimpl.ContentType && r.Method == http.MethodPost { 1408 http.Error(w, fmt.Sprintf("Unsupported Content-type \"%s\"", ct), http.StatusUnsupportedMediaType) 1409 return false 1410 } 1411 1412 return true 1413 } 1414 1415 // validatePayload validate and get the payload from the request. 1416 func validatePostPayload(r *http.Request, w http.ResponseWriter) bool { 1417 if r.ContentLength == 0 && r.Method == http.MethodPost { // empty payload should not be accepted for POST request 1418 http.Error(w, "Empty payload", http.StatusBadRequest) 1419 return false 1420 } 1421 1422 return true 1423 } 1424 1425 // CreateMockHTTPServerAndClient creates mock http server and client using tls and returns them. 1426 func CreateMockHTTPServerAndClient(t *testing.T, inHandler http.Handler) (net.Listener, string, *http.Client) { 1427 server := startMockServer(inHandler) 1428 port := getServerPort(server) 1429 serverURL := fmt.Sprintf("https://localhost:%d", port) 1430 1431 // build a mock cert pool 1432 cp := x509.NewCertPool() 1433 err := addCertsToCertPool(cp) 1434 require.NoError(t, err) 1435 1436 // build a tls.Config instance to be used by the outbound transport 1437 tlsConfig := &tls.Config{ //nolint:gosec 1438 RootCAs: cp, 1439 Certificates: nil, 1440 } 1441 1442 // create an http client to communicate with the server that has our inbound handlers set above 1443 client := &http.Client{ 1444 Timeout: clientTimeout, 1445 Transport: &http.Transport{ 1446 TLSClientConfig: tlsConfig, 1447 }, 1448 } 1449 1450 return server, serverURL, client 1451 } 1452 1453 func CreateMockHTTPServerAndClientNotOKStatusCode(t *testing.T) (net.Listener, string, *http.Client) { 1454 hf := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1455 w.WriteHeader(501) 1456 }) 1457 1458 return CreateMockHTTPServerAndClient(t, hf) 1459 } 1460 1461 func startMockServer(handler http.Handler) net.Listener { 1462 // ":0" will make the listener auto assign a free port 1463 listener, err := net.Listen("tcp", "127.0.0.1:0") 1464 if err != nil { 1465 errorLogger.Fatalf("HTTP listener failed to start: %s", err) 1466 } 1467 1468 go func() { 1469 err := http.ServeTLS(listener, handler, certPrefix+"ec-pubCert1.pem", certPrefix+"ec-key1.pem") 1470 if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { 1471 errorLogger.Fatalf("HTTP server failed to start: %s", err) 1472 } 1473 }() 1474 1475 return listener 1476 } 1477 1478 func getServerPort(server net.Listener) int { 1479 // read dynamic port assigned to the server to be used by the client 1480 return server.Addr().(*net.TCPAddr).Port 1481 } 1482 1483 func addCertsToCertPool(pool *x509.CertPool) error { 1484 var rawCerts []string 1485 1486 // add contents of ec-pubCert(1, 2 and 3).pem to rawCerts 1487 for i := 1; i <= 3; i++ { 1488 certPath := fmt.Sprintf("%sec-pubCert%d.pem", certPrefix, i) 1489 // Create a pool with server certificates 1490 1491 path := filepath.Clean(certPath) 1492 1493 cert, e := ioutil.ReadFile(path) 1494 if e != nil { 1495 return fmt.Errorf("reading certificate failed: %w", e) 1496 } 1497 1498 rawCerts = append(rawCerts, string(cert)) 1499 } 1500 1501 certs := decodeCerts(rawCerts) 1502 for i := range certs { 1503 pool.AddCert(certs[i]) 1504 } 1505 1506 return nil 1507 } 1508 1509 // decodeCerts will decode a list of pemCertsList (string) into a list of x509 certificates. 1510 func decodeCerts(pemCertsList []string) []*x509.Certificate { 1511 var certs []*x509.Certificate 1512 1513 for _, pemCertsString := range pemCertsList { 1514 pemCerts := []byte(pemCertsString) 1515 for len(pemCerts) > 0 { 1516 var block *pem.Block 1517 1518 block, pemCerts = pem.Decode(pemCerts) 1519 if block == nil { 1520 break 1521 } 1522 1523 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 1524 continue 1525 } 1526 1527 cert, err := x509.ParseCertificate(block.Bytes) 1528 if err != nil { 1529 continue 1530 } 1531 1532 certs = append(certs, cert) 1533 } 1534 } 1535 1536 return certs 1537 } 1538 1539 var errFailingMarshal = errors.New("failingMarshal always fails") 1540 1541 func failingMarshal(interface{}) ([]byte, error) { 1542 return nil, errFailingMarshal 1543 } 1544 1545 var errFailingUnmarshal = errors.New("failingUnmarshal always fails") 1546 1547 func failingUnmarshal([]byte, interface{}) error { 1548 return errFailingUnmarshal 1549 } 1550 1551 type errFailingCloser struct{} 1552 1553 func (c *errFailingCloser) Close() error { 1554 return errors.New("errFailingCloser always fails") 1555 } 1556 1557 func mockAddHeadersFuncSuccess(req *http.Request) (*http.Header, error) { 1558 // mocking a call to an auth server to get necessary credentials. 1559 // It only sets mock http.Header entries for testing purposes. 1560 req.Header.Set("controller", "mockController") 1561 req.Header.Set("authServerURL", "mockAuthServerURL") 1562 req.Header.Set("secret", "mockSecret") 1563 1564 return &req.Header, nil 1565 } 1566 1567 var errAddHeadersFunc = errors.New("mockAddHeadersFuncError always fails") 1568 1569 func mockAddHeadersFuncError(_ *http.Request) (*http.Header, error) { 1570 return nil, errAddHeadersFunc 1571 } 1572 1573 func matchPath(r *http.Request, uri string) bool { 1574 return strings.LastIndex(r.URL.Path, uri) == len(r.URL.Path)-len(uri) 1575 } 1576 1577 func getCertsErrorSubText() string { 1578 sharedPrefix := "tls: failed to verify certificate: " 1579 1580 if runtime.GOOS == "darwin" { 1581 return sharedPrefix + "x509: “*.example.com” certificate is not trusted" 1582 } 1583 1584 return sharedPrefix + "x509: certificate signed by unknown authority" 1585 }