github.com/trustbloc/kms-go@v1.1.2/kms/localkms/localkms_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package localkms 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/ed25519" 12 "crypto/elliptic" 13 "crypto/rand" 14 "crypto/sha256" 15 "crypto/x509" 16 "encoding/base64" 17 "encoding/json" 18 "errors" 19 "fmt" 20 "io/ioutil" 21 "os" 22 "strings" 23 "testing" 24 25 "github.com/btcsuite/btcd/btcec/v2" 26 "github.com/google/tink/go/keyset" 27 "github.com/google/tink/go/subtle/random" 28 "github.com/stretchr/testify/require" 29 "github.com/trustbloc/bbs-signature-go/bbs12381g2pub" 30 31 "github.com/trustbloc/kms-go/spi/crypto" 32 kmsapi "github.com/trustbloc/kms-go/spi/kms" 33 "github.com/trustbloc/kms-go/spi/secretlock" 34 35 "github.com/trustbloc/kms-go/crypto/tinkcrypto" 36 "github.com/trustbloc/kms-go/kms" 37 "github.com/trustbloc/kms-go/kms/localkms/internal/keywrapper" 38 mocksecretlock "github.com/trustbloc/kms-go/mock/secretlock" 39 "github.com/trustbloc/kms-go/secretlock/local" 40 "github.com/trustbloc/kms-go/secretlock/local/masterlock/hkdf" 41 "github.com/trustbloc/kms-go/secretlock/noop" 42 ) 43 44 const testMasterKeyURI = keywrapper.LocalKeyURIPrefix + "test/key/uri" 45 46 type inMemoryKMSStore struct { 47 keys map[string][]byte 48 } 49 50 func newInMemoryKMSStore() *inMemoryKMSStore { 51 return &inMemoryKMSStore{keys: make(map[string][]byte)} 52 } 53 54 func (i *inMemoryKMSStore) Put(keysetID string, key []byte) error { 55 i.keys[keysetID] = key 56 57 return nil 58 } 59 60 func (i *inMemoryKMSStore) Get(keysetID string) ([]byte, error) { 61 key, found := i.keys[keysetID] 62 if !found { 63 return nil, kms.ErrKeyNotFound 64 } 65 66 return key, nil 67 } 68 69 func (i *inMemoryKMSStore) Delete(keysetID string) error { 70 delete(i.keys, keysetID) 71 72 return nil 73 } 74 75 type mockStore struct { 76 errPut error 77 errGet error 78 } 79 80 func (m *mockStore) Put(string, []byte) error { 81 return m.errPut 82 } 83 84 func (m *mockStore) Get(string) ([]byte, error) { 85 return nil, m.errGet 86 } 87 88 func (m *mockStore) Delete(string) error { 89 return nil 90 } 91 92 func TestNewKMS_Failure(t *testing.T) { 93 t.Run("test New() fail without masterkeyURI", func(t *testing.T) { 94 kmsStorage, err := New("", &mockProvider{ 95 storage: newInMemoryKMSStore(), 96 secretLock: &mocksecretlock.MockSecretLock{ 97 ValEncrypt: "", 98 ValDecrypt: "", 99 }, 100 }) 101 require.Error(t, err) 102 require.Empty(t, kmsStorage) 103 }) 104 105 t.Run("test New() error creating new KMS client with bad master key prefix", func(t *testing.T) { 106 badKeyURI := "://test/key/uri" 107 108 kmsStorage, err := New(badKeyURI, &mockProvider{ 109 storage: newInMemoryKMSStore(), 110 secretLock: &mocksecretlock.MockSecretLock{ 111 ValEncrypt: "", 112 ValDecrypt: "", 113 }, 114 }) 115 require.Error(t, err) 116 require.Empty(t, kmsStorage) 117 }) 118 } 119 120 func TestCreateGetRotateKey_Failure(t *testing.T) { 121 t.Run("test failure Create() and Rotate() calls with bad key template string", func(t *testing.T) { 122 kmsStorage, err := New(testMasterKeyURI, &mockProvider{ 123 storage: newInMemoryKMSStore(), 124 secretLock: &mocksecretlock.MockSecretLock{ 125 ValEncrypt: "", 126 ValDecrypt: "", 127 }, 128 }) 129 require.NoError(t, err) 130 require.NotEmpty(t, kmsStorage) 131 132 id, kh, err := kmsStorage.Create("") 133 require.Error(t, err) 134 require.Empty(t, kh) 135 require.Empty(t, id) 136 137 id, kh, err = kmsStorage.Create("unsupported") 138 require.Error(t, err) 139 require.Empty(t, kh) 140 require.Empty(t, id) 141 142 // create a valid key to test Rotate() 143 id, kh, err = kmsStorage.Create(kmsapi.AES128GCMType) 144 require.NoError(t, err) 145 require.NotEmpty(t, kh) 146 require.NotEmpty(t, id) 147 148 newID, kh, err := kmsStorage.Rotate("", id) 149 require.Error(t, err) 150 require.Empty(t, kh) 151 require.Empty(t, newID) 152 153 newID, kh, err = kmsStorage.Rotate("unsupported", id) 154 require.Error(t, err) 155 require.Empty(t, kh) 156 require.Empty(t, newID) 157 }) 158 159 t.Run("test Create() with failure to store key", func(t *testing.T) { 160 putErr := fmt.Errorf("failed to put data") 161 errGet := kms.ErrKeyNotFound 162 mockStore := &mockStore{ 163 errPut: putErr, 164 errGet: errGet, 165 } 166 167 kmsStorage, err := New(testMasterKeyURI, &mockProvider{ 168 storage: mockStore, 169 secretLock: &mocksecretlock.MockSecretLock{ 170 ValEncrypt: "", 171 ValDecrypt: "", 172 }, 173 }) 174 require.NoError(t, err) 175 176 id, kh, err := kmsStorage.Create(kmsapi.AES128GCMType) 177 require.True(t, errors.Is(err, putErr)) 178 require.Empty(t, kh) 179 require.Empty(t, id) 180 }) 181 182 t.Run("test Create() success to store key but fail to get key from store", func(t *testing.T) { 183 kmsStorage, err := New(testMasterKeyURI, &mockProvider{ 184 storage: newInMemoryKMSStore(), 185 secretLock: &mocksecretlock.MockSecretLock{ 186 ValEncrypt: "", 187 ValDecrypt: "", 188 }, 189 }) 190 require.NoError(t, err) 191 192 id, kh, err := kmsStorage.Create(kmsapi.AES128GCMType) 193 require.NoError(t, err) 194 require.NotEmpty(t, kh) 195 require.NotEmpty(t, id) 196 197 // new create a new client with a store throwing an error during a Get() 198 errGet := errors.New("failed to get data") 199 mockStore := &mockStore{ 200 errGet: errGet, 201 } 202 203 kmsStorage3, err := New(testMasterKeyURI, &mockProvider{ 204 storage: mockStore, 205 secretLock: &mocksecretlock.MockSecretLock{ 206 ValEncrypt: "", 207 ValDecrypt: "", 208 }, 209 }) 210 require.NoError(t, err) 211 212 kh, err = kmsStorage3.Get(id) 213 require.Contains(t, err.Error(), "failed to get data") 214 require.Empty(t, kh) 215 216 newID, kh, err := kmsStorage3.Rotate(kmsapi.AES128GCMType, id) 217 require.Contains(t, err.Error(), "failed to get data") 218 require.Empty(t, kh) 219 require.Empty(t, newID) 220 }) 221 222 t.Run("create valid key but not available for Export", func(t *testing.T) { 223 kmsStorage, err := New(testMasterKeyURI, &mockProvider{ 224 storage: newInMemoryKMSStore(), 225 secretLock: &noop.NoLock{}, 226 }) 227 require.NoError(t, err) 228 229 kid, _, err := kmsStorage.Create(kmsapi.AES128GCM) 230 require.NoError(t, err) 231 232 _, _, err = kmsStorage.ExportPubKeyBytes(kid) 233 require.EqualError(t, err, "exportPubKeyBytes: failed to export marshalled key: exportPubKeyBytes: "+ 234 "failed to get public keyset handle: keyset.Handle: keyset.Handle: keyset contains a non-private key") 235 }) 236 237 t.Run("create And Export invalid key", func(t *testing.T) { 238 kmsStorage, err := New(testMasterKeyURI, &mockProvider{ 239 storage: newInMemoryKMSStore(), 240 secretLock: &noop.NoLock{}, 241 }) 242 require.NoError(t, err) 243 244 // try to create and export an unsupported key type. 245 _, _, err = kmsStorage.CreateAndExportPubKeyBytes("unsupported") 246 require.EqualError(t, err, "createAndExportPubKeyBytes: failed to create new key: create: failed to "+ 247 "getKeyTemplate: getKeyTemplate: key type 'unsupported' unrecognized") 248 249 // try to create and export a supported key type, but does not support export. 250 _, _, err = kmsStorage.CreateAndExportPubKeyBytes(kmsapi.HMACSHA256Tag256) 251 require.EqualError(t, err, "createAndExportPubKeyBytes: failed to export new public key bytes: "+ 252 "exportPubKeyBytes: failed to export marshalled key: exportPubKeyBytes: failed to get public keyset "+ 253 "handle: keyset.Handle: keyset.Handle: keyset contains a non-private key") 254 }) 255 } 256 257 func TestEncryptRotateDecrypt_Success(t *testing.T) { 258 // create a real (not mocked) master key and secret lock to test the KMS end to end 259 sl := createMasterKeyAndSecretLock(t) 260 261 // test New() 262 kmsService, err := New(testMasterKeyURI, &mockProvider{ 263 storage: newInMemoryKMSStore(), 264 secretLock: sl, 265 }) 266 require.NoError(t, err) 267 require.NotEmpty(t, kmsService) 268 269 keyTemplates := []kmsapi.KeyType{ 270 kmsapi.AES128GCMType, 271 kmsapi.AES256GCMNoPrefixType, 272 kmsapi.AES256GCMType, 273 kmsapi.ChaCha20Poly1305, 274 kmsapi.XChaCha20Poly1305, 275 } 276 277 for _, v := range keyTemplates { 278 // test Create() a new key 279 keyID, keyHandle, e := kmsService.Create(v) 280 require.NoError(t, e, "failed on template %v", v) 281 require.NotEmpty(t, keyHandle) 282 require.NotEmpty(t, keyID) 283 284 c := tinkcrypto.Crypto{} 285 msg := []byte("Test Rotation Message") 286 aad := []byte("some additional data") 287 288 cipherText, nonce, e := c.Encrypt(msg, aad, keyHandle) 289 require.NoError(t, e) 290 291 newKeyID, rotatedKeyHandle, e := kmsService.Rotate(v, keyID) 292 require.NoError(t, e) 293 require.NotEmpty(t, rotatedKeyHandle) 294 require.NotEqual(t, newKeyID, keyID) 295 296 decryptedMsg, e := c.Decrypt(cipherText, aad, nonce, rotatedKeyHandle) 297 require.NoError(t, e) 298 require.Equal(t, msg, decryptedMsg) 299 } 300 } 301 302 func TestLocalKMS_Success(t *testing.T) { 303 // create a real (not mocked) master key and secret lock to test the KMS end to end 304 sl := createMasterKeyAndSecretLock(t) 305 306 keys := make(map[string][]byte) 307 308 testStore := newInMemoryKMSStore() 309 310 testStore.keys = keys 311 312 // test New() 313 kmsService, err := New(testMasterKeyURI, &mockProvider{ 314 storage: testStore, 315 secretLock: sl, 316 }) 317 require.NoError(t, err) 318 require.NotEmpty(t, kmsService) 319 320 keyTemplates := []kmsapi.KeyType{ 321 kmsapi.AES128GCMType, 322 kmsapi.AES256GCMNoPrefixType, 323 kmsapi.AES256GCMType, 324 kmsapi.ChaCha20Poly1305Type, 325 kmsapi.XChaCha20Poly1305Type, 326 kmsapi.ECDSAP256TypeDER, 327 kmsapi.ECDSAP384TypeDER, 328 kmsapi.ECDSAP521TypeDER, 329 kmsapi.ECDSAP256TypeIEEEP1363, 330 kmsapi.ECDSAP384TypeIEEEP1363, 331 kmsapi.ECDSAP521TypeIEEEP1363, 332 kmsapi.ED25519Type, 333 kmsapi.NISTP256ECDHKWType, 334 kmsapi.NISTP384ECDHKWType, 335 kmsapi.NISTP521ECDHKWType, 336 kmsapi.X25519ECDHKWType, 337 kmsapi.BLS12381G2Type, 338 kmsapi.ECDSASecp256k1DER, 339 kmsapi.ECDSASecp256k1IEEEP1363, 340 } 341 342 for _, v := range keyTemplates { 343 if v == kmsapi.ECDSASecp256k1DER { 344 t.Logf("testing create for %s", v) 345 _, _, e := kmsService.Create(v) 346 require.EqualError(t, e, "create: Unable to create kms key: Secp256K1 is not supported by DER format") 347 348 continue 349 } 350 351 // test Create() a new key 352 keyID, newKeyHandle, e := kmsService.Create(v) 353 require.NoError(t, e, "failed on template %v", v) 354 require.NotEmpty(t, newKeyHandle) 355 require.NotEmpty(t, keyID) 356 357 ks, ok := keys[keyID] 358 require.True(t, ok) 359 require.NotEmpty(t, ks) 360 361 // get key handle primitives 362 newKHPrimitives, e := newKeyHandle.(*keyset.Handle).Primitives() 363 require.NoError(t, e) 364 require.NotEmpty(t, newKHPrimitives) 365 366 // test Get() an existing keyhandle (it should match newKeyHandle above) 367 loadedKeyHandle, e := kmsService.Get(keyID) 368 require.NoError(t, e) 369 require.NotEmpty(t, loadedKeyHandle) 370 371 readKHPrimitives, e := loadedKeyHandle.(*keyset.Handle).Primitives() 372 require.NoError(t, e) 373 require.NotEmpty(t, newKHPrimitives) 374 375 require.Equal(t, len(newKHPrimitives.Entries), len(readKHPrimitives.Entries)) 376 377 // finally test Rotate() 378 // with unsupported key type - should fail 379 newKeyID, rotatedKeyHandle, e := kmsService.Rotate("unsupported", keyID) 380 require.Error(t, e) 381 require.Empty(t, rotatedKeyHandle) 382 require.Empty(t, newKeyID) 383 384 // with valid key type - should succeed 385 newKeyID, rotatedKeyHandle, e = kmsService.Rotate(v, keyID) 386 require.NoError(t, e) 387 require.NotEmpty(t, rotatedKeyHandle) 388 require.NotEqual(t, newKeyID, keyID) 389 390 rotatedKHPrimitives, e := loadedKeyHandle.(*keyset.Handle).Primitives() 391 require.NoError(t, e) 392 require.NotEmpty(t, newKHPrimitives) 393 require.Equal(t, len(newKHPrimitives.Entries), len(rotatedKHPrimitives.Entries)) 394 require.Equal(t, len(readKHPrimitives.Entries), len(rotatedKHPrimitives.Entries)) 395 396 if strings.Contains(string(v), "ECDSA") || v == kmsapi.ED25519Type || v == kmsapi.BLS12381G2Type { 397 pubKeyBytes, kt, e := kmsService.ExportPubKeyBytes(keyID) 398 require.Errorf(t, e, "KeyID has been rotated. An error must be returned") 399 require.Empty(t, pubKeyBytes) 400 require.Empty(t, kt) 401 402 pubKeyBytes, kt, e = kmsService.ExportPubKeyBytes(newKeyID) 403 require.NoError(t, e) 404 require.NotEmpty(t, pubKeyBytes) 405 require.Equal(t, v, kt) 406 407 kh, e := kmsService.PubKeyBytesToHandle(pubKeyBytes, v) 408 require.NoError(t, e) 409 require.NotEmpty(t, kh) 410 411 // test create and export key in one function 412 _, _, e = kmsService.CreateAndExportPubKeyBytes(v) 413 require.NoError(t, e) 414 } 415 } 416 } 417 418 func TestLocalKMS_ImportPrivateKey(t *testing.T) { // nolint:gocyclo 419 // create a real (not mocked) master key and secret lock to test the KMS end to end 420 sl := createMasterKeyAndSecretLock(t) 421 422 // test New() 423 kmsService, e := New(testMasterKeyURI, &mockProvider{ 424 storage: newInMemoryKMSStore(), 425 secretLock: sl, 426 }) 427 require.NoError(t, e) 428 require.NotEmpty(t, kmsService) 429 430 // test import with nil key 431 _, _, err := kmsService.ImportPrivateKey(nil, kmsapi.ECDSAP256TypeDER) 432 require.EqualError(t, err, "import private key does not support this key type or key is public") 433 434 flagTests := []struct { 435 tcName string 436 keyType kmsapi.KeyType 437 curve elliptic.Curve 438 setID bool 439 ksID string 440 }{ 441 { 442 tcName: "import private key using ECDSAP256DER type", 443 keyType: kmsapi.ECDSAP256TypeDER, 444 curve: elliptic.P256(), 445 }, 446 { 447 tcName: "import private key using ECDSAP384TypeDER type", 448 keyType: kmsapi.ECDSAP384TypeDER, 449 curve: elliptic.P384(), 450 }, 451 { 452 tcName: "import private key using ECDSAP521TypeDER type", 453 keyType: kmsapi.ECDSAP521TypeDER, 454 curve: elliptic.P521(), 455 }, 456 { 457 tcName: "import private key using NISTP256ECDHKW type", 458 keyType: kmsapi.NISTP256ECDHKWType, 459 curve: elliptic.P256(), 460 }, 461 { 462 tcName: "import private key using NISTP384ECDHKW type", 463 keyType: kmsapi.NISTP384ECDHKWType, 464 curve: elliptic.P384(), 465 }, 466 { 467 tcName: "import private key using NISTP521ECDHKW type", 468 keyType: kmsapi.NISTP521ECDHKWType, 469 curve: elliptic.P521(), 470 }, 471 { 472 tcName: "import private key using ECDSAP256TypeIEEEP1363 type", 473 keyType: kmsapi.ECDSAP256TypeIEEEP1363, 474 curve: elliptic.P256(), 475 }, 476 { 477 tcName: "import private key using ECDSAP384TypeIEEEP1363 type", 478 keyType: kmsapi.ECDSAP384TypeIEEEP1363, 479 curve: elliptic.P384(), 480 }, 481 { 482 tcName: "import private key using ECDSAP521TypeIEEEP1363 type", 483 keyType: kmsapi.ECDSAP521TypeIEEEP1363, 484 curve: elliptic.P521(), 485 }, 486 /*{ 487 tcName: "import private key using ECDSAP256DER type", 488 keyType: kms.ECDSASecp256k1DER, 489 curve: btcec.S256(), 490 },*/ 491 { 492 tcName: "import private key using ECDSAP256IEEEP1363 type", 493 keyType: kmsapi.ECDSASecp256k1IEEEP1363, 494 curve: btcec.S256(), 495 }, 496 { 497 tcName: "import private key using ED25519Type type", 498 keyType: kmsapi.ED25519Type, 499 }, 500 { 501 tcName: "import private key using BLS12381G2Type type", 502 keyType: kmsapi.BLS12381G2Type, 503 }, 504 { 505 tcName: "import private key using ECDSAP256DER type and a set empty KeyID", 506 keyType: kmsapi.ECDSAP256TypeDER, 507 curve: elliptic.P256(), 508 setID: true, 509 ksID: "", 510 }, 511 { 512 tcName: "import private key using ECDSAP256DER type and a set non empty KeyID", 513 keyType: kmsapi.ECDSAP256TypeDER, 514 curve: elliptic.P256(), 515 setID: true, 516 ksID: base64.RawURLEncoding.EncodeToString(random.GetRandomBytes( 517 uint32(base64.RawURLEncoding.DecodedLen(maxKeyIDLen)))), 518 }, 519 { 520 tcName: "import private key using ECDSAP256DER type and a set non KeyID larger than maxKeyIDLen", 521 keyType: kmsapi.ECDSAP256TypeDER, 522 curve: elliptic.P256(), 523 setID: true, 524 ksID: base64.RawURLEncoding.EncodeToString(random.GetRandomBytes( 525 uint32(base64.RawURLEncoding.DecodedLen(30)))), 526 }, 527 } 528 529 for _, tc := range flagTests { 530 tt := tc 531 t.Run(tt.tcName, func(t *testing.T) { 532 if tt.keyType == kmsapi.ED25519Type { 533 pubKey, privKey, err := ed25519.GenerateKey(rand.Reader) 534 require.NoError(t, err) 535 536 ksID, _, err := kmsService.ImportPrivateKey(privKey, tt.keyType) 537 require.NoError(t, err) 538 539 pubKeyBytes, kt, err := kmsService.ExportPubKeyBytes(ksID) 540 require.NoError(t, err) 541 require.EqualValues(t, pubKey, pubKeyBytes) 542 require.Equal(t, tt.keyType, kt) 543 return 544 } 545 546 if tt.keyType == kmsapi.BLS12381G2Type { 547 seed := make([]byte, 32) 548 549 _, err := rand.Read(seed) 550 require.NoError(t, err) 551 552 pubKey, privKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, seed) 553 require.NoError(t, err) 554 555 ksID, _, err := kmsService.ImportPrivateKey(privKey, tt.keyType) 556 require.NoError(t, err) 557 558 pubKeyBytes, kt, err := kmsService.ExportPubKeyBytes(ksID) 559 require.NoError(t, err) 560 require.Equal(t, tt.keyType, kt) 561 562 expectedPubKeyBytes, err := pubKey.Marshal() 563 require.NoError(t, err) 564 require.EqualValues(t, expectedPubKeyBytes, pubKeyBytes) 565 return 566 } 567 568 privKey, err := ecdsa.GenerateKey(tt.curve, rand.Reader) 569 require.NoError(t, err) 570 571 var ksID string 572 573 // test ImportPrivateKey 574 if tt.setID { 575 // with set keyset ID 576 ksID, _, err = kmsService.ImportPrivateKey(privKey, tt.keyType, kmsapi.WithKeyID(tt.ksID)) 577 require.NoError(t, err) 578 // calling ImportPrivatekeyt and WithKeyID("") will ignore the set KeyID and generate a new one 579 if tt.ksID != "" { 580 require.Equal(t, tt.ksID, ksID) 581 } 582 } else { 583 // generate a new keyset ID 584 ksID, _, err = kmsService.ImportPrivateKey(privKey, tt.keyType) 585 require.NoError(t, err) 586 } 587 588 // export marshaled public key to verify it against the original public key (marshalled) 589 actualPubKey, kt, err := kmsService.ExportPubKeyBytes(ksID) 590 require.NoError(t, err) 591 require.Equal(t, tt.keyType, kt) 592 593 var expectedPubKey []byte 594 595 switch tt.keyType { 596 case kmsapi.ECDSAP256TypeDER, kmsapi.ECDSAP384TypeDER, kmsapi.ECDSAP521TypeDER, kmsapi.ECDSASecp256k1TypeDER: 597 expectedPubKey, err = x509.MarshalPKIXPublicKey(privKey.Public()) 598 require.NoError(t, err) 599 case kmsapi.ECDSAP256TypeIEEEP1363, kmsapi.ECDSAP384TypeIEEEP1363, kmsapi.ECDSAP521TypeIEEEP1363, 600 kmsapi.ECDSASecp256k1TypeIEEEP1363: 601 expectedPubKey = elliptic.Marshal(tt.curve, privKey.X, privKey.Y) 602 case kmsapi.NISTP256ECDHKWType, kmsapi.NISTP384ECDHKWType, kmsapi.NISTP521ECDHKWType: 603 var curveName string 604 605 switch tt.curve.Params().Name { 606 case "P-256": 607 curveName = "NIST_P256" 608 case "P-384": 609 curveName = "NIST_P384" 610 case "P-521": 611 curveName = "NIST_P521" 612 case "secp256k1": 613 curveName = "SECP256K1" 614 } 615 616 cryptoKey := &crypto.PublicKey{ 617 KID: ksID, 618 X: privKey.PublicKey.X.Bytes(), 619 Y: privKey.PublicKey.Y.Bytes(), 620 Curve: curveName, 621 Type: "EC", 622 } 623 624 expectedPubKey, err = json.Marshal(cryptoKey) 625 require.NoError(t, err) 626 } 627 628 require.EqualValues(t, expectedPubKey, actualPubKey) 629 }) 630 } 631 } 632 633 func TestLocalKMS_getKeyTemplate(t *testing.T) { 634 keyTemplate, err := getKeyTemplate(kmsapi.HMACSHA256Tag256Type) 635 require.NoError(t, err) 636 require.NotNil(t, keyTemplate) 637 require.Equal(t, "type.googleapis.com/google.crypto.tink.HmacKey", keyTemplate.TypeUrl) 638 } 639 640 func createMasterKeyAndSecretLock(t *testing.T) secretlock.Service { 641 t.Helper() 642 643 masterKeyFilePath := "masterKey_file.txt" 644 tmpfile, err := ioutil.TempFile("", masterKeyFilePath) 645 require.NoError(t, err) 646 647 defer func() { 648 // close file 649 require.NoError(t, tmpfile.Close()) 650 // clean up file 651 require.NoError(t, os.Remove(tmpfile.Name())) 652 }() 653 654 masterKeyContent := random.GetRandomBytes(uint32(32)) 655 require.NotEmpty(t, masterKeyContent) 656 657 // first create a master lock to use in our secret lock and encrypt the master key 658 passphrase := "secretPassphrase" 659 keySize := sha256.Size 660 // salt is optional, it can be nil 661 salt := make([]byte, keySize) 662 _, err = rand.Read(salt) 663 require.NoError(t, err) 664 665 masterLocker, err := hkdf.NewMasterLock(passphrase, sha256.New, salt) 666 require.NoError(t, err) 667 require.NotEmpty(t, masterLocker) 668 669 // now encrypt masterKeyContent 670 masterLockEnc, err := masterLocker.Encrypt("", &secretlock.EncryptRequest{ 671 Plaintext: string(masterKeyContent), 672 }) 673 require.NoError(t, err) 674 require.NotEmpty(t, masterLockEnc) 675 676 // and write it to tmpfile 677 n, err := tmpfile.Write([]byte(masterLockEnc.Ciphertext)) 678 require.NoError(t, err) 679 require.Equal(t, len(masterLockEnc.Ciphertext), n) 680 681 // now get a reader from path 682 r, err := local.MasterKeyFromPath(tmpfile.Name()) 683 require.NoError(t, err) 684 require.NotEmpty(t, r) 685 686 // finally create lock service with the master lock created above to encrypt decrypt keys using 687 // a protected (encrypted) master key 688 s, err := local.NewService(r, masterLocker) 689 require.NoError(t, err) 690 require.NotEmpty(t, s) 691 692 return s 693 } 694 695 // mockProvider mocks a provider for KMS storage. 696 type mockProvider struct { 697 storage kmsapi.Store 698 secretLock secretlock.Service 699 } 700 701 func (m *mockProvider) StorageProvider() kmsapi.Store { 702 return m.storage 703 } 704 705 func (m *mockProvider) SecretLock() secretlock.Service { 706 return m.secretLock 707 }