func TestDoubleCreate(t *testing.T) { tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) anotherTestKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) // We are using SQLite for the tests db, err := sql.Open("sqlite3", tempBaseDir+"test_db") assert.NoError(t, err) // Create a new KeyDB store dbStore, err := NewKeyDBStore(retriever, "", "sqlite3", db) assert.NoError(t, err) // Ensure that the private_key table exists dbStore.db.CreateTable(&GormPrivateKey{}) // Test writing new key in database/cache err = dbStore.AddKey("", "", testKey) assert.NoError(t, err) // Test writing the same key in the database. Should fail. err = dbStore.AddKey("", "", testKey) assert.Error(t, err, "failed to add private key to database:") // Test writing new key succeeds err = dbStore.AddKey("", "", anotherTestKey) assert.NoError(t, err) }
func TestDoubleCreate(t *testing.T) { testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) anotherTestKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) tmpFilename := initializeDB(t) defer os.Remove(tmpFilename) // Create a new KeyDB store and add a key dbStore, err := NewKeyDBStore(retriever, "ignoredalias", "sqlite3", tmpFilename) assert.NoError(t, err) // Test writing new key in database/cache err = dbStore.AddKey("gun/ignored", data.CanonicalTimestampRole, testKey) assert.NoError(t, err) // Test writing the same key in the database. Should fail. err = dbStore.AddKey("gun/ignored", data.CanonicalTimestampRole, testKey) assert.Error(t, err, "failed to add private key to database:") // Test writing new key succeeds err = dbStore.AddKey("gun/ignored", data.CanonicalTimestampRole, anotherTestKey) assert.NoError(t, err) }
func TestKeyRotation(t *testing.T) { tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) // We are using SQLite for the tests db, err := sql.Open("sqlite3", tempBaseDir+"test_db") assert.NoError(t, err) // Create a new KeyDB store dbStore, err := NewKeyDBStore(anotherRetriever, "alias_1", "sqlite3", db) assert.NoError(t, err) // Ensure that the private_key table exists dbStore.db.CreateTable(&GormPrivateKey{}) // Test writing new key in database/cache err = dbStore.AddKey("", "", testKey) assert.NoError(t, err) // Try rotating the key to alias-2 err = dbStore.RotateKeyPassphrase(testKey.ID(), "alias_2") assert.NoError(t, err) // Try rotating the key to alias-3 err = dbStore.RotateKeyPassphrase(testKey.ID(), "alias_3") assert.Error(t, err, "password alias no found") }
func testAddKey(t *testing.T, store trustmanager.KeyStore) (data.PrivateKey, error) { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) require.NoError(t, err) err = store.AddKey(trustmanager.KeyInfo{Role: data.CanonicalRootRole, Gun: ""}, privKey) return privKey, err }
// initialize a repo with keys, so they can be rotated func setUpRepo(t *testing.T, tempBaseDir, gun string, ret passphrase.Retriever) ( *httptest.Server, map[string]string) { // server that always returns 200 (and a key) key, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pubKey := data.PublicKeyFromPrivate(key) jsonBytes, err := json.MarshalCanonical(&pubKey) assert.NoError(t, err) keyJSON := string(jsonBytes) ts := httptest.NewServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, keyJSON) })) repo, err := client.NewNotaryRepository( tempBaseDir, gun, ts.URL, http.DefaultTransport, ret) assert.NoError(t, err, "error creating repo: %s", err) rootPubKey, err := repo.CryptoService.Create("root", data.ECDSAKey) assert.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize(rootPubKey.ID()) assert.NoError(t, err) return ts, repo.CryptoService.ListAllKeys() }
// AddGetKeyCryptoServiceInterfaceBehaviorTests tests expected behavior for // adding keys in a signed.CryptoService and other read operations on the // crypto service after keys are present // 1. Adding a key succeeds // 2. Getting the key should return the same key, without error // 3. Removing the key succeeds func AddGetKeyCryptoServiceInterfaceBehaviorTests(t *testing.T, cs signed.CryptoService, algo string) { expectedRolesToKeys := make(map[string]string) for i := 0; i < 2; i++ { var ( addedPrivKey data.PrivateKey err error ) role := data.BaseRoles[i+1] switch algo { case data.RSAKey: addedPrivKey, err = trustmanager.GenerateRSAKey(rand.Reader, 2048) case data.ECDSAKey: addedPrivKey, err = trustmanager.GenerateECDSAKey(rand.Reader) case data.ED25519Key: addedPrivKey, err = trustmanager.GenerateED25519Key(rand.Reader) default: require.FailNow(t, "invalid algorithm %s", algo) } require.NoError(t, err) require.NotNil(t, addedPrivKey) require.NoError(t, cs.AddKey(role, "docker.io/notary", addedPrivKey)) expectedRolesToKeys[role] = addedPrivKey.ID() } testGetKey(t, cs, expectedRolesToKeys, algo, true) }
// Importing a key not as root fails, and it is not added to the backup store func TestYubiImportNonRootKey(t *testing.T) { if !YubikeyAccessible() { t.Skip("Must have Yubikey access.") } clearAllKeys(t) SetYubikeyKeyMode(KeymodeNone) defer func() { SetYubikeyKeyMode(KeymodeTouch | KeymodePinOnce) }() backup := trustmanager.NewKeyMemoryStore(ret) store, err := NewYubiKeyStore(backup, ret) assert.NoError(t, err) // generate key and import it privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pemBytes, err := trustmanager.EncryptPrivateKey(privKey, "passphrase") assert.NoError(t, err) err = store.ImportKey(pemBytes, privKey.ID()) assert.Error(t, err) // key is not in backup store _, _, err = backup.GetKey(privKey.ID()) assert.Error(t, err) }
// GenRootKey generates a new root key protected by a given passphrase // TODO(diogo): show not create keys manually, should use a cryptoservice instead func (km *KeyStoreManager) GenRootKey(algorithm, passphrase string) (string, error) { var err error var privKey *data.PrivateKey // We don't want external API callers to rely on internal TUF data types, so // the API here should continue to receive a string algorithm, and ensure // that it is downcased switch data.KeyAlgorithm(strings.ToLower(algorithm)) { case data.RSAKey: privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize) case data.ECDSAKey: privKey, err = trustmanager.GenerateECDSAKey(rand.Reader) default: return "", fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", algorithm) } if err != nil { return "", fmt.Errorf("failed to generate private key: %v", err) } // Changing the root km.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase) return privKey.ID(), nil }
func testAddKey(t *testing.T, store trustmanager.KeyStore) (data.PrivateKey, error) { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) err = store.AddKey(privKey.ID(), data.CanonicalRootRole, privKey) return privKey, err }
// Create is used to generate keys for targets, snapshots and timestamps func (ccs *CryptoService) Create(role string, algorithm data.KeyAlgorithm) (data.PublicKey, error) { var privKey data.PrivateKey var err error switch algorithm { case data.RSAKey: privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaKeySize) if err != nil { return nil, fmt.Errorf("failed to generate RSA key: %v", err) } case data.ECDSAKey: privKey, err = trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate EC key: %v", err) } case data.ED25519Key: privKey, err = trustmanager.GenerateED25519Key(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate ED25519 key: %v", err) } default: return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) } logrus.Debugf("generated new %s key for role: %s and keyID: %s", algorithm, role, privKey.ID()) // Store the private key into our keystore with the name being: /GUN/ID.key with an alias of role err = ccs.keyStore.AddKey(filepath.Join(ccs.gun, privKey.ID()), role, privKey) if err != nil { return nil, fmt.Errorf("failed to add key to filestore: %v", err) } return data.PublicKeyFromPrivate(privKey), nil }
func TestUnlockedSigner(t *testing.T) { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err, "could not generate key") keyStore := trustmanager.NewKeyMemoryStore(passphraseRetriever) err = keyStore.AddKey(privKey.ID(), "root", privKey) assert.NoError(t, err, "could not add key to store") cryptoService := NewCryptoService("", keyStore) uCryptoService := NewUnlockedCryptoService(privKey, cryptoService) // Check ID method assert.Equal(t, privKey.ID(), uCryptoService.ID()) // Check Public method assert.Equal(t, privKey.Public(), uCryptoService.PublicKey().Public()) assert.Equal(t, privKey.ID(), uCryptoService.PublicKey().ID()) // Check GenerateCertificate method gun := "docker.com/notary" cert, err := uCryptoService.GenerateCertificate(gun) assert.NoError(t, err, "could not generate certificate") // Check public key ecdsaPrivateKey, err := x509.ParseECPrivateKey(privKey.Private()) assert.NoError(t, err) ecdsaPublicKey := ecdsaPrivateKey.Public() assert.Equal(t, ecdsaPublicKey, cert.PublicKey) // Check CommonName assert.Equal(t, cert.Subject.CommonName, gun) }
func TestYubiImportKeyCleansUpOnError(t *testing.T) { if !YubikeyAccessible() { t.Skip("Must have Yubikey access.") } clearAllKeys(t) SetYubikeyKeyMode(KeymodeNone) defer func() { SetYubikeyKeyMode(KeymodeTouch | KeymodePinOnce) }() store, err := NewYubiKeyStore(trustmanager.NewKeyMemoryStore(ret), ret) assert.NoError(t, err) privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pemBytes, err := trustmanager.EncryptPrivateKey(privKey, "passphrase") assert.NoError(t, err) var _importkey = func() error { return store.ImportKey(pemBytes, "root") } testYubiFunctionCleansUpOnLoginError(t, store, _importkey) // all the PKCS11 functions ImportKey depends on that aren't the login/logout testYubiFunctionCleansUpOnSpecifiedErrors(t, store, _importkey, append( setupErrors, "FindObjectsInit", "FindObjects", "FindObjectsFinal", "CreateObject", ), true) // given that everything should have errored, there should be no keys on // the yubikey assert.Len(t, cleanListKeys(t), 0) // Logout should not cause a function failure - it s a cleanup failure, // which shouldn't break anything, and it should clean up after itself. // The key should be added to both stores testYubiFunctionCleansUpOnSpecifiedErrors(t, store, _importkey, []string{"Logout"}, false) listedKeys := cleanListKeys(t) assert.Len(t, listedKeys, 1) // Currently, if GetAttributeValue fails, the function succeeds, because if // we can't get the attribute value of an object, we don't know what slot // it's in, we assume its occupied slot is free (hence this failure will // cause the previous key to be overwritten). This behavior may need to // be revisited. for k := range listedKeys { err := store.RemoveKey(k) assert.NoError(t, err) } testYubiFunctionCleansUpOnSpecifiedErrors(t, store, _importkey, []string{"GetAttributeValue"}, false) assert.Len(t, cleanListKeys(t), 1) }
func TestCreateDelete(t *testing.T) { tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) // We are using SQLite for the tests db, err := sql.Open("sqlite3", tempBaseDir+"test_db") assert.NoError(t, err) // Create a new KeyDB store dbStore, err := NewKeyDBStore(retriever, "", "sqlite3", db) assert.NoError(t, err) // Ensure that the private_key table exists dbStore.db.CreateTable(&GormPrivateKey{}) // Test writing new key in database/cache err = dbStore.AddKey("", "", testKey) assert.NoError(t, err) // Test deleting the key from the db err = dbStore.RemoveKey(testKey.ID()) assert.NoError(t, err) // This should fail _, _, err = dbStore.GetKey(testKey.ID()) assert.Error(t, err, "signing key not found:") }
// Tests import/export root key only func TestClientKeyImportExportRootOnly(t *testing.T) { // -- setup -- cleanup := setUp(t) defer cleanup() tempDir := tempDirWithConfig(t, "{}") defer os.RemoveAll(tempDir) server := setupServer() defer server.Close() var ( target = "sdgkadga" rootKeyID string ) tempFile, err := ioutil.TempFile("/tmp", "pemfile") assert.NoError(t, err) // close later, because we might need to write to it defer os.Remove(tempFile.Name()) // -- tests -- if rootOnHardware() { t.Log("Cannot export a key from hardware. Will generate one to import.") privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pemBytes, err := trustmanager.EncryptPrivateKey(privKey, "root", testPassphrase) assert.NoError(t, err) nBytes, err := tempFile.Write(pemBytes) assert.NoError(t, err) tempFile.Close() assert.Equal(t, len(pemBytes), nBytes) rootKeyID = privKey.ID() } else { tempFile.Close() rootKeyID = exportRoot(t, tempFile.Name()) } // import the key _, err = runCommand(t, tempDir, "key", "import", tempFile.Name()) assert.NoError(t, err) // if there is hardware available, root will only be on hardware, and not // on disk newRoot, _ := assertNumKeys(t, tempDir, 1, 0, !rootOnHardware()) assert.Equal(t, rootKeyID, newRoot[0]) // Just to make sure, init a repo and publish _, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun") assert.NoError(t, err) assertNumKeys(t, tempDir, 1, 2, !rootOnHardware()) assertSuccessfullyPublish( t, tempDir, server.URL, "gun", target, tempFile.Name()) }
func generateCertificate(t *testing.T, gun string, expireInHours int64) *x509.Certificate { ecdsaPrivKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) startTime := time.Now() endTime := startTime.Add(time.Hour * time.Duration(expireInHours)) cert, err := cryptoservice.GenerateCertificate(ecdsaPrivKey, gun, startTime, endTime) assert.NoError(t, err) return cert }
// asserts that signing, if there are no matching keys, produces no signatures func (c CryptoServiceTester) TestSignNoMatchingKeys(t *testing.T) { cryptoService := c.cryptoServiceFactory() content := []byte("this is a secret") privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err, c.errorMsg("error creating key")) // Test Sign with key that is not in the cryptoservice signatures, err := cryptoService.Sign([]string{privKey.ID()}, content) assert.NoError(t, err, c.errorMsg("signing failed")) assert.Len(t, signatures, 0, c.errorMsg("wrong number of signatures")) }
func generateValidTestCert() (*x509.Certificate, string, error) { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return nil, "", err } keyID := privKey.ID() startTime := time.Now() endTime := startTime.AddDate(10, 0, 0) cert, err := cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime) if err != nil { return nil, "", err } return cert, keyID, nil }
func generateExpiredTestCert() (*x509.Certificate, string, error) { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return nil, "", err } keyID := privKey.ID() // Set to Unix time 0 start time, valid for one more day startTime := time.Unix(0, 0) endTime := startTime.AddDate(0, 0, 1) cert, err := cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime) if err != nil { return nil, "", err } return cert, keyID, nil }
// Creating a key, on succcess, populates the cache. func TestCreateSuccessPopulatesCache(t *testing.T) { testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) tmpFilename := initializeDB(t) defer os.Remove(tmpFilename) // Create a new KeyDB store dbStore, err := NewKeyDBStore(retriever, "ignoredalias", "sqlite3", tmpFilename) assert.NoError(t, err) // Test writing new key in database err = dbStore.AddKey("gun/ignored", data.CanonicalTimestampRole, testKey) assert.NoError(t, err) testGetSuccessFromCache(t, dbStore, testKey) }
func generateTempTestKeyFile(t *testing.T, role string) string { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return "" } keyBytes, err := trustmanager.KeyToPEM(privKey, role) assert.NoError(t, err) tempPrivFile, err := ioutil.TempFile("/tmp", "privfile") assert.NoError(t, err) // Write the private key to a file so we can import it _, err = tempPrivFile.Write(keyBytes) assert.NoError(t, err) tempPrivFile.Close() return tempPrivFile.Name() }
// Create is used to generate keys for targets, snapshots and timestamps func (cs *CryptoService) Create(role, algorithm string) (data.PublicKey, error) { var privKey data.PrivateKey var err error switch algorithm { case data.RSAKey: privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaKeySize) if err != nil { return nil, fmt.Errorf("failed to generate RSA key: %v", err) } case data.ECDSAKey: privKey, err = trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate EC key: %v", err) } case data.ED25519Key: privKey, err = trustmanager.GenerateED25519Key(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate ED25519 key: %v", err) } default: return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) } logrus.Debugf("generated new %s key for role: %s and keyID: %s", algorithm, role, privKey.ID()) // Store the private key into our keystore with the name being: /GUN/ID.key with an alias of role var keyPath string if role == data.CanonicalRootRole { keyPath = privKey.ID() } else { keyPath = filepath.Join(cs.gun, privKey.ID()) } for _, ks := range cs.keyStores { err = ks.AddKey(keyPath, role, privKey) if err == nil { return data.PublicKeyFromPrivate(privKey), nil } } if err != nil { return nil, fmt.Errorf("failed to add key to filestore: %v", err) } return nil, fmt.Errorf("keystores would not accept new private keys for unknown reasons") }
// If there are multiple keystores, even if all of them have the same key, // only one signature is returned. func (c CryptoServiceTester) TestSignWhenMultipleKeystores(t *testing.T) { cryptoService := c.cryptoServiceFactory() cryptoService.keyStores = append(cryptoService.keyStores, trustmanager.NewKeyMemoryStore(passphraseRetriever)) content := []byte("this is a secret") privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err, c.errorMsg("error creating key")) for _, store := range cryptoService.keyStores { err := store.AddKey(privKey.ID(), "root", privKey) assert.NoError(t, err) } signatures, err := cryptoService.Sign([]string{privKey.ID()}, content) assert.NoError(t, err, c.errorMsg("signing failed")) assert.Len(t, signatures, 1, c.errorMsg("wrong number of signatures")) }
// asserts that listing keys works with multiple keystores, and that the // same keys are deduplicated func (c CryptoServiceTester) TestListFromMultipleKeystores(t *testing.T) { cryptoService := c.cryptoServiceFactory() cryptoService.keyStores = append(cryptoService.keyStores, trustmanager.NewKeyMemoryStore(passphraseRetriever)) expectedKeysIDs := make(map[string]bool) // just want to be able to index by key for i := 0; i < 3; i++ { privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err, c.errorMsg("error creating key")) expectedKeysIDs[privKey.ID()] = true // adds one different key to each keystore, and then one key to // both keystores for j, store := range cryptoService.keyStores { if i == j || i == 2 { store.AddKey(privKey.ID(), "root", privKey) } } } // sanity check - each should have 2 for _, store := range cryptoService.keyStores { assert.Len(t, store.ListKeys(), 2, c.errorMsg("added keys wrong")) } keyList := cryptoService.ListKeys("root") assert.Len(t, keyList, 4, c.errorMsg( "ListKeys should have 4 keys (not necesarily unique) but does not: %v", keyList)) for _, k := range keyList { _, ok := expectedKeysIDs[k] assert.True(t, ok, c.errorMsg("Unexpected key %s", k)) } keyMap := cryptoService.ListAllKeys() assert.Len(t, keyMap, 3, c.errorMsg("ListAllKeys should have 3 unique keys but does not: %v", keyMap)) for k, role := range keyMap { _, ok := expectedKeysIDs[k] assert.True(t, ok) assert.Equal(t, "root", role) } }
// Getting a key, on succcess, populates the cache. func TestGetSuccessPopulatesCache(t *testing.T) { testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) tmpFilename := initializeDB(t) defer os.Remove(tmpFilename) // Create a new KeyDB store and add a key dbStore, err := NewKeyDBStore(retriever, "ignoredalias", "sqlite3", tmpFilename) assert.NoError(t, err) err = dbStore.AddKey("gun/ignored", data.CanonicalTimestampRole, testKey) assert.NoError(t, err) // delete the cache dbStore.cachedKeys = make(map[string]data.PrivateKey) testGetSuccess(t, dbStore, testKey) testGetSuccessFromCache(t, dbStore, testKey) }
// If the timestamp key in the store does not match the timestamp key in // the root.json, validation fails. This could happen if pushing an existing // repository from one server to another that had already initialized the same // repo. func TestValidateRootInvalidTimestampKey(t *testing.T) { _, oldRepo, cs := testutils.EmptyRepo() r, tg, sn, ts, err := testutils.Sign(oldRepo) assert.NoError(t, err) root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts) assert.NoError(t, err) store := storage.NewMemStorage() updates := []storage.MetaUpdate{root, targets, snapshot} key, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) err = store.SetKey("testGUN", data.CanonicalRootRole, key.Algorithm(), key.Public()) assert.NoError(t, err) _, err = validateUpdate(cs, "testGUN", updates, store) assert.Error(t, err) assert.IsType(t, validation.ErrBadRoot{}, err) }
// ImportKey imports a key as root without adding it to the backup store func TestYubiImportNewKey(t *testing.T) { if !YubikeyAccessible() { t.Skip("Must have Yubikey access.") } clearAllKeys(t) SetYubikeyKeyMode(KeymodeNone) defer func() { SetYubikeyKeyMode(KeymodeTouch | KeymodePinOnce) }() backup := trustmanager.NewKeyMemoryStore(ret) store, err := NewYubiKeyStore(backup, ret) assert.NoError(t, err) // generate key and import it privKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pemBytes, err := trustmanager.EncryptPrivateKey(privKey, "passphrase") assert.NoError(t, err) err = store.ImportKey(pemBytes, "root") assert.NoError(t, err) // key is not in backup store _, _, err = backup.GetKey(privKey.ID()) assert.Error(t, err) // create a new store, since we want to be sure the original store's cache // is not masking any issues cleanStore, err := NewYubiKeyStore(trustmanager.NewKeyMemoryStore(ret), ret) assert.NoError(t, err) for _, store := range []*YubiKeyStore{store, cleanStore} { gottenKey, role, err := store.GetKey(privKey.ID()) assert.NoError(t, err) assert.Equal(t, data.CanonicalRootRole, role) assert.Equal(t, privKey.Public(), gottenKey.Public()) } }
func TestCreateRead(t *testing.T) { tempBaseDir, err := ioutil.TempDir("", "notary-test-") defer os.RemoveAll(tempBaseDir) testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) // We are using SQLite for the tests db, err := sql.Open("sqlite3", tempBaseDir+"test_db") assert.NoError(t, err) // Create a new KeyDB store dbStore, err := NewKeyDBStore(retriever, "", "sqlite3", db) assert.NoError(t, err) // Ensure that the private_key table exists dbStore.db.CreateTable(&GormPrivateKey{}) // Test writing new key in database/cache err = dbStore.AddKey("", "", testKey) assert.NoError(t, err) // Test retrieval of key from DB delete(dbStore.cachedKeys, testKey.ID()) retrKey, _, err := dbStore.GetKey(testKey.ID()) assert.NoError(t, err) assert.Equal(t, retrKey, testKey) // Tests retrieval of key from Cache // Close database connection err = dbStore.db.Close() assert.NoError(t, err) retrKey, _, err = dbStore.GetKey(testKey.ID()) assert.NoError(t, err) assert.Equal(t, retrKey, testKey) }
// Create is used to generate keys for targets, snapshots and timestamps func (cs *CryptoService) Create(role, gun, algorithm string) (data.PublicKey, error) { var privKey data.PrivateKey var err error switch algorithm { case data.RSAKey: privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaKeySize) if err != nil { return nil, fmt.Errorf("failed to generate RSA key: %v", err) } case data.ECDSAKey: privKey, err = trustmanager.GenerateECDSAKey(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate EC key: %v", err) } case data.ED25519Key: privKey, err = trustmanager.GenerateED25519Key(rand.Reader) if err != nil { return nil, fmt.Errorf("failed to generate ED25519 key: %v", err) } default: return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) } logrus.Debugf("generated new %s key for role: %s and keyID: %s", algorithm, role, privKey.ID()) // Store the private key into our keystore for _, ks := range cs.keyStores { err = ks.AddKey(trustmanager.KeyInfo{Role: role, Gun: gun}, privKey) if err == nil { return data.PublicKeyFromPrivate(privKey), nil } } if err != nil { return nil, fmt.Errorf("failed to add key to filestore: %v", err) } return nil, fmt.Errorf("keystores would not accept new private keys for unknown reasons") }
func TestKeyRotation(t *testing.T) { testKey, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) tmpFilename := initializeDB(t) defer os.Remove(tmpFilename) // Create a new KeyDB store dbStore, err := NewKeyDBStore(anotherRetriever, "alias_1", "sqlite3", tmpFilename) assert.NoError(t, err) // Test writing new key in database/cache err = dbStore.AddKey("gun/ignore", data.CanonicalTimestampRole, testKey) assert.NoError(t, err) // Try rotating the key to alias-2 err = dbStore.RotateKeyPassphrase(testKey.ID(), "alias_2") assert.NoError(t, err) // Try rotating the key to alias-3 err = dbStore.RotateKeyPassphrase(testKey.ID(), "alias_3") assert.Error(t, err, "there should be no password for alias_3") }
func TestGetPrivateKeyAndSignWithExistingKey(t *testing.T) { key, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err, "could not generate key") store := trustmanager.NewKeyMemoryStore(ret) err = store.AddKey(key.ID(), "timestamp", key) assert.NoError(t, err, "could not add key to store") signer := setUpSigner(t, store) privKey, _, err := signer.GetPrivateKey(key.ID()) assert.NoError(t, err) assert.NotNil(t, privKey) msg := []byte("message!") sig, err := privKey.Sign(rand.Reader, msg, nil) assert.NoError(t, err) err = signed.Verifiers[data.ECDSASignature].Verify( data.PublicKeyFromPrivate(key), sig, msg) assert.NoError(t, err) }