예제 #1
0
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)
}
예제 #2
0
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)
}
예제 #3
0
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")
}
예제 #4
0
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
}
예제 #5
0
// 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()
}
예제 #6
0
// 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)
}
예제 #7
0
// 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)
}
예제 #8
0
// 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
}
예제 #9
0
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
}
예제 #10
0
// 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
}
예제 #11
0
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)
}
예제 #12
0
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)
}
예제 #13
0
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:")
}
예제 #14
0
// 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())
}
예제 #15
0
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
}
예제 #16
0
// 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"))
}
예제 #17
0
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
}
예제 #18
0
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
}
예제 #19
0
// 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)
}
예제 #20
0
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()
}
예제 #21
0
// 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")

}
예제 #22
0
// 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"))
}
예제 #23
0
// 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)
	}
}
예제 #24
0
// 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)
}
예제 #25
0
// 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)
}
예제 #26
0
// 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())
	}
}
예제 #27
0
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)
}
예제 #28
0
// 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")
}
예제 #29
0
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")
}
예제 #30
0
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)
}