コード例 #1
0
ファイル: timestamp.go プロジェクト: rogaha/notary
// GetOrCreateTimestampKey returns the timestamp key for the gun. It uses the store to
// lookup an existing timestamp key and the crypto to generate a new one if none is
// found. It attempts to handle the race condition that may occur if 2 servers try to
// create the key at the same time by simply querying the store a second time if it
// receives a conflict when writing.
func GetOrCreateTimestampKey(gun string, store storage.MetaStore, crypto signed.CryptoService, fallBackAlgorithm string) (data.PublicKey, error) {
	keyAlgorithm, public, err := store.GetTimestampKey(gun)
	if err == nil {
		return data.NewPublicKey(keyAlgorithm, public), nil
	}

	if _, ok := err.(*storage.ErrNoKey); ok {
		key, err := crypto.Create("timestamp", fallBackAlgorithm)
		if err != nil {
			return nil, err
		}
		logrus.Debug("Creating new timestamp key for ", gun, ". With algo: ", key.Algorithm())
		err = store.SetTimestampKey(gun, key.Algorithm(), key.Public())
		if err == nil {
			return key, nil
		}

		if _, ok := err.(*storage.ErrTimestampKeyExists); ok {
			keyAlgorithm, public, err = store.GetTimestampKey(gun)
			if err != nil {
				return nil, err
			}
			return data.NewPublicKey(keyAlgorithm, public), nil
		}
		return nil, err
	}
	return nil, err
}
コード例 #2
0
ファイル: snapshot.go プロジェクト: NathanMcCauley/notary
// GetOrCreateSnapshotKey either creates a new snapshot key, or returns
// the existing one. Only the PublicKey is returned. The private part
// is held by the CryptoService.
func GetOrCreateSnapshotKey(gun string, store storage.KeyStore, crypto signed.CryptoService, createAlgorithm string) (data.PublicKey, error) {
	keyAlgorithm, public, err := store.GetKey(gun, data.CanonicalSnapshotRole)
	if err == nil {
		return data.NewPublicKey(keyAlgorithm, public), nil
	}

	if _, ok := err.(*storage.ErrNoKey); ok {
		key, err := crypto.Create("snapshot", createAlgorithm)
		if err != nil {
			return nil, err
		}
		logrus.Debug("Creating new snapshot key for ", gun, ". With algo: ", key.Algorithm())
		err = store.SetKey(gun, data.CanonicalSnapshotRole, key.Algorithm(), key.Public())
		if err == nil {
			return key, nil
		}

		if _, ok := err.(*storage.ErrKeyExists); ok {
			keyAlgorithm, public, err = store.GetKey(gun, data.CanonicalSnapshotRole)
			if err != nil {
				return nil, err
			}
			return data.NewPublicKey(keyAlgorithm, public), nil
		}
		return nil, err
	}
	return nil, err
}
コード例 #3
0
ファイル: keystoremanager_test.go プロジェクト: rogaha/notary
func testValidateSuccessfulRootRotation(t *testing.T, keyAlg, rootKeyType string) {
	// The gun to test
	gun := "docker.com/notary"

	tempBaseDir, keyStoreManager, certs := filestoreWithTwoCerts(t, gun, keyAlg)
	defer os.RemoveAll(tempBaseDir)
	origRootCert := certs[0]
	replRootCert := certs[1]

	// Add the old root cert part of trustedCertificates
	keyStoreManager.AddTrustedCert(origRootCert)

	// We need the PEM representation of the replacement key to put it into the TUF data
	origRootPEMCert := trustmanager.CertToPEM(origRootCert)
	replRootPEMCert := trustmanager.CertToPEM(replRootCert)

	// Tuf key with PEM-encoded x509 certificate
	origRootKey := data.NewPublicKey(rootKeyType, origRootPEMCert)
	replRootKey := data.NewPublicKey(rootKeyType, replRootPEMCert)

	rootRole, err := data.NewRole("root", 1, []string{replRootKey.ID()}, nil, nil)
	assert.NoError(t, err)

	testRoot, err := data.NewRoot(
		map[string]data.PublicKey{replRootKey.ID(): replRootKey},
		map[string]*data.RootRole{"root": &rootRole.RootRole},
		false,
	)
	assert.NoError(t, err, "Failed to create new root")

	signedTestRoot, err := testRoot.ToSigned()
	assert.NoError(t, err)

	cs := cryptoservice.NewCryptoService(gun, keyStoreManager.KeyStore)

	err = signed.Sign(cs, signedTestRoot, replRootKey)
	assert.NoError(t, err)

	err = signed.Sign(cs, signedTestRoot, origRootKey)
	assert.NoError(t, err)

	//
	// This call to ValidateRoot will succeed since we are using a valid PEM
	// encoded certificate, and have no other certificates for this CN
	//
	err = keyStoreManager.ValidateRoot(signedTestRoot, gun)
	assert.NoError(t, err)

	// Finally, validate the only trusted certificate that exists is the new one
	certs = keyStoreManager.trustedCertificateStore.GetCertificates()
	assert.Len(t, certs, 1)
	assert.Equal(t, certs[0], replRootCert)
}
コード例 #4
0
ファイル: certs_test.go プロジェクト: NathanMcCauley/notary
func testValidateRootRotationMissingNewSig(t *testing.T, keyAlg, rootKeyType string) {
	gun := "docker.com/notary"

	tempBaseDir, certStore, cryptoService, certificates := filestoreWithTwoCerts(
		t, gun, keyAlg)
	defer os.RemoveAll(tempBaseDir)
	origRootCert := certificates[0]
	replRootCert := certificates[1]

	// Add the old root cert part of trustedCertificates
	certStore.AddCert(origRootCert)

	// We need the PEM representation of the replacement key to put it into the TUF data
	origRootPEMCert := trustmanager.CertToPEM(origRootCert)
	replRootPEMCert := trustmanager.CertToPEM(replRootCert)

	// Tuf key with PEM-encoded x509 certificate
	origRootKey := data.NewPublicKey(rootKeyType, origRootPEMCert)
	replRootKey := data.NewPublicKey(rootKeyType, replRootPEMCert)

	rootRole, err := data.NewRole(data.CanonicalRootRole, 1, []string{replRootKey.ID()}, nil)
	assert.NoError(t, err)

	testRoot, err := data.NewRoot(
		map[string]data.PublicKey{replRootKey.ID(): replRootKey},
		map[string]*data.RootRole{data.CanonicalRootRole: &rootRole.RootRole},
		false,
	)
	assert.NoError(t, err, "Failed to create new root")

	signedTestRoot, err := testRoot.ToSigned()
	assert.NoError(t, err)

	// We only sign with the old key, and not with the new one
	err = signed.Sign(cryptoService, signedTestRoot, origRootKey)
	assert.NoError(t, err)

	// This call to ValidateRoot will succeed since we are using a valid PEM
	// encoded certificate, and have no other certificates for this CN
	err = ValidateRoot(certStore, signedTestRoot, gun)
	assert.Error(t, err, "insuficient signatures on root")

	// Finally, validate the only trusted certificate that exists is still
	// the old one
	certificates = certStore.GetCertificates()
	assert.Len(t, certificates, 1)
	assert.Equal(t, certificates[0], origRootCert)
}
コード例 #5
0
ファイル: keys.go プロジェクト: rogaha/notary
// ID implements a method of the data.Key interface
func (rsa *HSMRSAKey) ID() string {
	if rsa.id == "" {
		pubK := data.NewPublicKey(rsa.Algorithm(), rsa.Public())
		rsa.id = pubK.ID()
	}
	return rsa.id
}
コード例 #6
0
// Create will attempt to first re-use an inactive key for the same role, gun, and algorithm.
// If one isn't found, it will create a private key and add it to the DB as an inactive key
func (rdb RethinkDBKeyStore) Create(role, gun, algorithm string) (data.PublicKey, error) {
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName).Table(dbPrivateKey.TableName()).
		Filter(gorethink.Row.Field("gun").Eq(gun)).
		Filter(gorethink.Row.Field("role").Eq(role)).
		Filter(gorethink.Row.Field("algorithm").Eq(algorithm)).
		Filter(gorethink.Row.Field("last_used").Eq(time.Time{})).
		OrderBy(gorethink.Row.Field("key_id")).
		Run(rdb.sess)
	if err != nil {
		return nil, err
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err == nil {
		return data.NewPublicKey(dbPrivateKey.Algorithm, dbPrivateKey.Public), nil
	}

	privKey, err := generatePrivateKey(algorithm)
	if err != nil {
		return nil, err
	}
	if err = rdb.AddKey(role, gun, privKey); err != nil {
		return nil, fmt.Errorf("failed to store key: %v", err)
	}

	return privKey, nil
}
コード例 #7
0
ファイル: timestamp.go プロジェクト: useidel/notary
// CreateTimestamp creates a new timestamp. If a prev timestamp is provided, it
// is assumed this is the immediately previous one, and the new one will have a
// version number one higher than prev. The store is used to lookup the current
// snapshot, this function does not save the newly generated timestamp.
func CreateTimestamp(gun string, prev *data.SignedTimestamp, snapshot []byte, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) {
	algorithm, public, err := store.GetKey(gun, data.CanonicalTimestampRole)
	if err != nil {
		// owner of gun must have generated a timestamp key otherwise
		// we won't proceed with generating everything.
		return nil, 0, err
	}
	key := data.NewPublicKey(algorithm, public)
	sn := &data.Signed{}
	err = json.Unmarshal(snapshot, sn)
	if err != nil {
		// couldn't parse snapshot
		return nil, 0, err
	}
	ts, err := data.NewTimestamp(sn)
	if err != nil {
		return nil, 0, err
	}
	if prev != nil {
		ts.Signed.Version = prev.Signed.Version + 1
	}
	sgndTs, err := json.MarshalCanonical(ts.Signed)
	if err != nil {
		return nil, 0, err
	}
	out := &data.Signed{
		Signatures: ts.Signatures,
		Signed:     sgndTs,
	}
	err = signed.Sign(cryptoService, out, key)
	if err != nil {
		return nil, 0, err
	}
	return out, ts.Signed.Version, nil
}
コード例 #8
0
ファイル: signer_trust.go プロジェクト: runcom/notary
// GetKey retrieves a key
func (trust *NotarySigner) GetKey(keyid string) data.PublicKey {
	publicKey, err := trust.kmClient.GetKeyInfo(context.Background(), &pb.KeyID{ID: keyid})
	if err != nil {
		return nil
	}
	return data.NewPublicKey(publicKey.KeyInfo.Algorithm.Algorithm, publicKey.PublicKey)
}
コード例 #9
0
ファイル: verifiers_test.go プロジェクト: useidel/notary
func TestRSAPyCryptoVerifierInvalidKeyType(t *testing.T) {
	key := data.NewPublicKey("bad_type", nil)
	v := RSAPyCryptoVerifier{}
	err := v.Verify(key, nil, nil)
	assert.Error(t, err)
	assert.IsType(t, ErrInvalidKeyType{}, err)
}
コード例 #10
0
ファイル: verifiers_test.go プロジェクト: mbentley/notary
func TestED25519VerifierInvalidKeyType(t *testing.T) {
	key := data.NewPublicKey("bad_type", nil)
	v := Ed25519Verifier{}
	err := v.Verify(key, nil, nil)
	require.Error(t, err)
	require.IsType(t, ErrInvalidKeyType{}, err)
}
コード例 #11
0
ファイル: sql_keydbstore.go プロジェクト: jfrazelle/notary
// GetKey performs the same get as GetPrivateKey, but does not mark the as active and only returns the public bytes
func (s *SQLKeyDBStore) GetKey(keyID string) data.PublicKey {
	privKey, _, err := s.getKey(keyID, false)
	if err != nil {
		return nil
	}
	return data.NewPublicKey(privKey.Algorithm, []byte(privKey.Public))
}
コード例 #12
0
ファイル: signer_trust.go プロジェクト: jfrazelle/notary
func (trust *NotarySigner) getKeyInfo(keyid string) (data.PublicKey, string, error) {
	keyInfo, err := trust.kmClient.GetKeyInfo(context.Background(), &pb.KeyID{ID: keyid})
	if err != nil {
		return nil, "", err
	}
	return data.NewPublicKey(keyInfo.KeyInfo.Algorithm.Algorithm, keyInfo.PublicKey), keyInfo.Role, nil
}
コード例 #13
0
ファイル: x509.go プロジェクト: jfrazelle/notary
// ParsePEMPublicKey returns a data.PublicKey from a PEM encoded public key or certificate.
func ParsePEMPublicKey(pubKeyBytes []byte) (data.PublicKey, error) {
	pemBlock, _ := pem.Decode(pubKeyBytes)
	if pemBlock == nil {
		return nil, errors.New("no valid public key found")
	}

	switch pemBlock.Type {
	case "CERTIFICATE":
		cert, err := x509.ParseCertificate(pemBlock.Bytes)
		if err != nil {
			return nil, fmt.Errorf("could not parse provided certificate: %v", err)
		}
		err = ValidateCertificate(cert, true)
		if err != nil {
			return nil, fmt.Errorf("invalid certificate: %v", err)
		}
		return CertToKey(cert), nil
	case "PUBLIC KEY":
		keyType, err := keyTypeForPublicKey(pemBlock.Bytes)
		if err != nil {
			return nil, err
		}
		return data.NewPublicKey(keyType, pemBlock.Bytes), nil
	default:
		return nil, fmt.Errorf("unsupported PEM block type %q, expected CERTIFICATE or PUBLIC KEY", pemBlock.Type)
	}
}
コード例 #14
0
// GetKey returns the PublicKey given a KeyID, and does not activate the key
func (rdb *RethinkDBKeyStore) GetKey(keyID string) data.PublicKey {
	dbPrivateKey, _, err := rdb.getKey(keyID)
	if err != nil {
		return nil
	}

	return data.NewPublicKey(dbPrivateKey.Algorithm, dbPrivateKey.Public)
}
コード例 #15
0
ファイル: signer_trust.go プロジェクト: runcom/notary
// Create creates a remote key and returns the PublicKey associated with the remote private key
func (trust *NotarySigner) Create(role, algorithm string) (data.PublicKey, error) {
	publicKey, err := trust.kmClient.CreateKey(context.Background(), &pb.Algorithm{Algorithm: algorithm})
	if err != nil {
		return nil, err
	}
	public := data.NewPublicKey(publicKey.KeyInfo.Algorithm.Algorithm, publicKey.PublicKey)
	return public, nil
}
コード例 #16
0
ファイル: httpstore_test.go プロジェクト: useidel/notary
func TestHTTPStoreGetMeta(t *testing.T) {
	handler := func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(testRoot))
	}
	server := httptest.NewServer(http.HandlerFunc(handler))
	defer server.Close()
	store, err := NewHTTPStore(
		server.URL,
		"metadata",
		"txt",
		"targets",
		"key",
		&http.Transport{},
	)
	if err != nil {
		t.Fatal(err)
	}
	j, err := store.GetMeta("root", 4801)
	if err != nil {
		t.Fatal(err)
	}
	p := &data.Signed{}
	err = json.Unmarshal(j, p)
	if err != nil {
		t.Fatal(err)
	}
	rootKey, err := base64.StdEncoding.DecodeString(testRootKey)
	assert.NoError(t, err)
	k := data.NewPublicKey("ecdsa-x509", rootKey)

	sigBytes := p.Signatures[0].Signature
	if err != nil {
		t.Fatal(err)
	}
	var decoded map[string]interface{}
	if err := json.Unmarshal(p.Signed, &decoded); err != nil {
		t.Fatal(err)
	}
	msg, err := json.MarshalCanonical(decoded)
	if err != nil {
		t.Fatal(err)
	}
	method := p.Signatures[0].Method
	err = signed.Verifiers[method].Verify(k, sigBytes, msg)
	if err != nil {
		t.Fatal(err)
	}

}
コード例 #17
0
ファイル: verifiers_test.go プロジェクト: jfrazelle/notary
func TestPyNaCled25519Compat(t *testing.T) {
	pubHex := "846612b43cef909a0e4ea9c818379bca4723a2020619f95e7a0ccc6f0850b7dc"
	testStr := "The quick brown fox jumps over the lazy dog."
	sigHex := "166e7013e48f26dccb4e68fe4cf558d1cd3af902f8395534336a7f8b4c56588694aa3ac671767246298a59d5ef4224f02c854f41bfcfe70241db4be1546d6a00"

	pub, _ := hex.DecodeString(pubHex)
	k := data.NewPublicKey(data.ED25519Key, pub)

	sigBytes, _ := hex.DecodeString(sigHex)

	err := Verifiers[data.EDDSASignature].Verify(k, sigBytes, []byte(testStr))
	if err != nil {
		t.Fatal(err)
	}
}
コード例 #18
0
ファイル: verifiers_test.go プロジェクト: jfrazelle/notary
func TestPyCryptoRSAPSSCompat(t *testing.T) {
	pubPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnKuXZeefa2LmgxaL5NsM\nzKOHNe+x/nL6ik+lDBCTV6OdcwAhHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5\nVSCuRJ53UronENl6lsa5mFKP8StYLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDf\nBEPIRp28ev/NViwGOEkBu2UAbwCIdnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK\n6pdzJXlhr9yap3UpgQ/iO9JtoEYB2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq\n3xmN4p+R4VGzfdQN+8Kl/IPjqWB535twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrM\nBI8ztvPiogz+MvXb8WvarZ6TMTh8ifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X\n7sXoaqszEtXdq5ef5zKVxkiyIQZcbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj\n1ANMFPxDQpHudCLxwCzjCb+sVa20HBRPTnzo8LSZkI6jAgMBAAE=\n-----END PUBLIC KEY-----"
	testStr := "The quick brown fox jumps over the lazy dog."
	sigHex := "4e05ee9e435653549ac4eddbc43e1a6868636e8ea6dbec2564435afcb0de47e0824cddbd88776ddb20728c53ecc90b5d543d5c37575fda8bd0317025fc07de62ee8084b1a75203b1a23d1ef4ac285da3d1fc63317d5b2cf1aafa3e522acedd366ccd5fe4a7f02a42922237426ca3dc154c57408638b9bfaf0d0213855d4e9ee621db204151bcb13d4dbb18f930ec601469c992c84b14e9e0b6f91ac9517bb3b749dd117e1cbac2e4acb0e549f44558a2005898a226d5b6c8b9291d7abae0d9e0a16858b89662a085f74a202deb867acab792bdbd2c36731217caea8b17bd210c29b890472f11e5afdd1dd7b69004db070e04201778f2c49f5758643881403d45a58d08f51b5c63910c6185892f0b590f191d760b669eff2464456f130239bba94acf54a0cb98f6939ff84ae26a37f9b890be259d9b5d636f6eb367b53e895227d7d79a3a88afd6d28c198ee80f6527437c5fbf63accb81709925c4e03d1c9eaee86f58e4bd1c669d6af042dbd412de0d13b98b1111e2fadbe34b45de52125e9a"
	k := data.NewPublicKey(data.RSAKey, []byte(pubPem))

	sigBytes, err := hex.DecodeString(sigHex)
	if err != nil {
		t.Fatal(err)
	}
	v := RSAPyCryptoVerifier{}
	err = v.Verify(k, sigBytes, []byte(testStr))
	if err != nil {
		t.Fatal(err)
	}
}
コード例 #19
0
ファイル: sql_keydbstore.go プロジェクト: jfrazelle/notary
// GetPrivateKey returns the PrivateKey given a KeyID
func (s *SQLKeyDBStore) GetPrivateKey(keyID string) (data.PrivateKey, string, error) {
	// Retrieve the GORM private key from the database
	dbPrivateKey, decryptedPrivKey, err := s.getKey(keyID, true)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	return activatingPrivateKey{PrivateKey: privKey, activationFunc: s.markActive}, dbPrivateKey.Role, nil
}
コード例 #20
0
// GetPrivateKey returns the PrivateKey given a KeyID
func (rdb *RethinkDBKeyStore) GetPrivateKey(keyID string) (data.PrivateKey, string, error) {
	dbPrivateKey, decryptedPrivKey, err := rdb.getKey(keyID)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, dbPrivateKey.Public)

	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	return activatingPrivateKey{PrivateKey: privKey, activationFunc: rdb.markActive}, dbPrivateKey.Role, nil
}
コード例 #21
0
ファイル: httpstore_test.go プロジェクト: mbentley/notary
func TestPyCryptoRSAPSSCompat(t *testing.T) {
	pubPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnKuXZeefa2LmgxaL5NsM\nzKOHNe+x/nL6ik+lDBCTV6OdcwAhHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5\nVSCuRJ53UronENl6lsa5mFKP8StYLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDf\nBEPIRp28ev/NViwGOEkBu2UAbwCIdnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK\n6pdzJXlhr9yap3UpgQ/iO9JtoEYB2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq\n3xmN4p+R4VGzfdQN+8Kl/IPjqWB535twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrM\nBI8ztvPiogz+MvXb8WvarZ6TMTh8ifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X\n7sXoaqszEtXdq5ef5zKVxkiyIQZcbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj\n1ANMFPxDQpHudCLxwCzjCb+sVa20HBRPTnzo8LSZkI6jAgMBAAE=\n-----END PUBLIC KEY-----"
	//privPem := "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----"
	testStr := "The quick brown fox jumps over the lazy dog."
	sigHex := "4e05ee9e435653549ac4eddbc43e1a6868636e8ea6dbec2564435afcb0de47e0824cddbd88776ddb20728c53ecc90b5d543d5c37575fda8bd0317025fc07de62ee8084b1a75203b1a23d1ef4ac285da3d1fc63317d5b2cf1aafa3e522acedd366ccd5fe4a7f02a42922237426ca3dc154c57408638b9bfaf0d0213855d4e9ee621db204151bcb13d4dbb18f930ec601469c992c84b14e9e0b6f91ac9517bb3b749dd117e1cbac2e4acb0e549f44558a2005898a226d5b6c8b9291d7abae0d9e0a16858b89662a085f74a202deb867acab792bdbd2c36731217caea8b17bd210c29b890472f11e5afdd1dd7b69004db070e04201778f2c49f5758643881403d45a58d08f51b5c63910c6185892f0b590f191d760b669eff2464456f130239bba94acf54a0cb98f6939ff84ae26a37f9b890be259d9b5d636f6eb367b53e895227d7d79a3a88afd6d28c198ee80f6527437c5fbf63accb81709925c4e03d1c9eaee86f58e4bd1c669d6af042dbd412de0d13b98b1111e2fadbe34b45de52125e9a"
	k := data.NewPublicKey(data.RSAKey, []byte(pubPem))

	sigBytes, err := hex.DecodeString(sigHex)
	if err != nil {
		t.Fatal(err)
	}
	v := signed.RSAPyCryptoVerifier{}
	err = v.Verify(k, sigBytes, []byte(testStr))
	if err != nil {
		t.Fatal(err)
	}
}
コード例 #22
0
ファイル: rethink_keydbstore.go プロジェクト: mbentley/notary
// GetKey returns the PrivateKey given a KeyID
func (rdb *RethinkDBKeyStore) GetKey(name string) (data.PrivateKey, string, error) {
	rdb.lock.Lock()
	defer rdb.lock.Unlock()
	cachedKeyEntry, ok := rdb.cachedKeys[name]
	if ok {
		return cachedKeyEntry, "", nil
	}

	// Retrieve the RethinkDB private key from the database
	dbPrivateKey := RDBPrivateKey{}
	res, err := gorethink.DB(rdb.dbName).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("key_id").Eq(name)).Run(rdb.sess)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}
	defer res.Close()

	err = res.One(&dbPrivateKey)
	if err != nil {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}

	// Get the passphrase to use for this key
	passphrase, _, err := rdb.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return nil, "", err
	}

	// Decrypt private bytes from the gorm key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	// Add the key to cache
	rdb.cachedKeys[privKey.ID()] = privKey

	return privKey, "", nil
}
コード例 #23
0
ファイル: sql_keydbstore.go プロジェクト: jfrazelle/notary
// Create will attempt to first re-use an inactive key for the same role, gun, and algorithm.
// If one isn't found, it will create a private key and add it to the DB as an inactive key
func (s *SQLKeyDBStore) Create(role, gun, algorithm string) (data.PublicKey, error) {
	// If an unused key exists, simply return it.  Else, error because SQL can't make keys
	dbPrivateKey := GormPrivateKey{}
	if !s.db.Model(GormPrivateKey{}).Where("role = ? AND gun = ? AND algorithm = ? AND last_used IS NULL", role, gun, algorithm).Order("key_id").First(&dbPrivateKey).RecordNotFound() {
		// Just return the public key component if we found one
		return data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public)), nil
	}

	privKey, err := generatePrivateKey(algorithm)
	if err != nil {
		return nil, err
	}

	if err = s.AddKey(role, gun, privKey); err != nil {
		return nil, fmt.Errorf("failed to store key: %v", err)
	}

	return privKey, nil
}
コード例 #24
0
ファイル: validation.go プロジェクト: NathanMcCauley/notary
func validateRoot(gun string, oldRoot, newRoot []byte, store storage.MetaStore) (
	*data.SignedRoot, error) {

	var parsedOldRoot *data.SignedRoot
	parsedNewRoot := &data.SignedRoot{}

	if oldRoot != nil {
		parsedOldRoot = &data.SignedRoot{}
		err := json.Unmarshal(oldRoot, parsedOldRoot)
		if err != nil {
			// TODO(david): if we can't read the old root should we continue
			//             here to check new root self referential integrity?
			//             This would permit recovery of a repo with a corrupted
			//             root.
			logrus.Warn("Old root could not be parsed.")
		}
	}
	err := json.Unmarshal(newRoot, parsedNewRoot)
	if err != nil {
		return nil, err
	}

	// Don't update if a timestamp key doesn't exist.
	algo, keyBytes, err := store.GetKey(gun, data.CanonicalTimestampRole)
	if err != nil || algo == "" || keyBytes == nil {
		return nil, fmt.Errorf("no timestamp key for %s", gun)
	}
	timestampKey := data.NewPublicKey(algo, keyBytes)

	if err := checkRoot(parsedOldRoot, parsedNewRoot, timestampKey); err != nil {
		// TODO(david): how strict do we want to be here about old signatures
		//              for rotations? Should the user have to provide a flag
		//              which gets transmitted to force a root update without
		//              correct old key signatures.
		return nil, err
	}

	if !data.ValidTUFType(parsedNewRoot.Signed.Type, data.CanonicalRootRole) {
		return nil, fmt.Errorf("root has wrong type")
	}
	return parsedNewRoot, nil
}
コード例 #25
0
ファイル: x509utils_test.go プロジェクト: mbentley/notary
// X509PublickeyID returns the public key ID of a RSA X509 key rather than the
// cert ID
func TestRSAX509PublickeyID(t *testing.T) {
	fileBytes, err := ioutil.ReadFile("../fixtures/notary-server.key")
	require.NoError(t, err)

	privKey, err := ParsePEMPrivateKey(fileBytes, "")
	require.NoError(t, err)
	expectedTUFID := privKey.ID()

	cert, err := LoadCertFromFile("../fixtures/notary-server.crt")
	require.NoError(t, err)

	rsaKeyBytes, err := x509.MarshalPKIXPublicKey(cert.PublicKey)
	require.NoError(t, err)

	sameWayTUFID := data.NewPublicKey(data.RSAKey, rsaKeyBytes).ID()

	actualTUFKey := CertToKey(cert)
	actualTUFID, err := X509PublicKeyID(actualTUFKey)
	require.NoError(t, err)
	require.Equal(t, sameWayTUFID, actualTUFID)
	require.Equal(t, expectedTUFID, actualTUFID)
}
コード例 #26
0
ファイル: keydbstore.go プロジェクト: useidel/notary
// GetKey returns the PrivateKey given a KeyID
func (s *KeyDBStore) GetKey(name string) (data.PrivateKey, string, error) {
	s.Lock()
	defer s.Unlock()
	cachedKeyEntry, ok := s.cachedKeys[name]
	if ok {
		return cachedKeyEntry, "", nil
	}

	// Retrieve the GORM private key from the database
	dbPrivateKey := GormPrivateKey{}
	if s.db.Where(&GormPrivateKey{KeyID: name}).First(&dbPrivateKey).RecordNotFound() {
		return nil, "", trustmanager.ErrKeyNotFound{}
	}

	// Get the passphrase to use for this key
	passphrase, _, err := s.retriever(dbPrivateKey.KeyID, dbPrivateKey.PassphraseAlias, false, 1)
	if err != nil {
		return nil, "", err
	}

	// Decrypt private bytes from the gorm key
	decryptedPrivKey, _, err := jose.Decode(dbPrivateKey.Private, passphrase)
	if err != nil {
		return nil, "", err
	}

	pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public))
	// Create a new PrivateKey with unencrypted bytes
	privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey))
	if err != nil {
		return nil, "", err
	}

	// Add the key to cache
	s.cachedKeys[privKey.ID()] = privKey

	return privKey, "", nil
}
コード例 #27
0
ファイル: snapshot.go プロジェクト: NathanMcCauley/notary
// createSnapshot uses an existing snapshot to create a new one.
// Important things to be aware of:
//   - It requires that a snapshot already exists. We create snapshots
//     on upload so there should always be an existing snapshot if this
//     gets called.
//   - It doesn't update what roles are present in the snapshot, as those
//     were validated during upload.
func createSnapshot(gun string, sn *data.SignedSnapshot, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) {
	algorithm, public, err := store.GetKey(gun, data.CanonicalSnapshotRole)
	if err != nil {
		// owner of gun must have generated a snapshot key otherwise
		// we won't proceed with generating everything.
		return nil, 0, err
	}
	key := data.NewPublicKey(algorithm, public)

	// update version and expiry
	sn.Signed.Version = sn.Signed.Version + 1
	sn.Signed.Expires = data.DefaultExpires(data.CanonicalSnapshotRole)

	out, err := sn.ToSigned()
	if err != nil {
		return nil, 0, err
	}
	err = signed.Sign(cryptoService, out, key)
	if err != nil {
		return nil, 0, err
	}
	return out, sn.Signed.Version, nil
}
コード例 #28
0
ファイル: validation.go プロジェクト: NathanMcCauley/notary
func generateSnapshot(gun string, repo *tuf.Repo, store storage.MetaStore) (*storage.MetaUpdate, error) {
	role, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
	if err != nil {
		return nil, validation.ErrBadRoot{Msg: "root did not include snapshot role"}
	}

	algo, keyBytes, err := store.GetKey(gun, data.CanonicalSnapshotRole)
	if err != nil {
		return nil, validation.ErrBadHierarchy{Msg: "could not retrieve snapshot key. client must provide snapshot"}
	}
	foundK := data.NewPublicKey(algo, keyBytes)

	validKey := false
	for _, id := range role.ListKeyIDs() {
		if id == foundK.ID() {
			validKey = true
			break
		}
	}
	if !validKey {
		return nil, validation.ErrBadHierarchy{
			Missing: data.CanonicalSnapshotRole,
			Msg:     "no snapshot was included in update and server does not hold current snapshot key for repository"}
	}

	currentJSON, err := store.GetCurrent(gun, data.CanonicalSnapshotRole)
	if err != nil {
		if _, ok := err.(storage.ErrNotFound); !ok {
			return nil, validation.ErrValidation{Msg: err.Error()}
		}
	}
	var sn *data.SignedSnapshot
	if currentJSON != nil {
		sn = new(data.SignedSnapshot)
		err := json.Unmarshal(currentJSON, sn)
		if err != nil {
			return nil, validation.ErrValidation{Msg: err.Error()}
		}
		err = repo.SetSnapshot(sn)
		if err != nil {
			return nil, validation.ErrValidation{Msg: err.Error()}
		}
	} else {
		// this will only occurr if no snapshot has ever been created for the repository
		err := repo.InitSnapshot()
		if err != nil {
			return nil, validation.ErrBadSnapshot{Msg: err.Error()}
		}
	}
	sgnd, err := repo.SignSnapshot(data.DefaultExpires(data.CanonicalSnapshotRole))
	if err != nil {
		return nil, validation.ErrBadSnapshot{Msg: err.Error()}
	}
	sgndJSON, err := json.Marshal(sgnd)
	if err != nil {
		return nil, validation.ErrBadSnapshot{Msg: err.Error()}
	}
	return &storage.MetaUpdate{
		Role:    data.CanonicalSnapshotRole,
		Version: repo.Snapshot.Signed.Version,
		Data:    sgndJSON,
	}, nil
}
コード例 #29
0
ファイル: validation.go プロジェクト: rogaha/notary
// checkRoot returns true if no rotation, or a valid
// rotation has taken place, and the threshold number of signatures
// are valid.
func checkRoot(oldRoot, newRoot *data.SignedRoot) error {
	rootRole := data.RoleName(data.CanonicalRootRole)
	targetsRole := data.RoleName(data.CanonicalTargetsRole)
	snapshotRole := data.RoleName(data.CanonicalSnapshotRole)
	timestampRole := data.RoleName(data.CanonicalTimestampRole)

	var oldRootRole *data.RootRole
	newRootRole, ok := newRoot.Signed.Roles[rootRole]
	if !ok {
		return errors.New("new root is missing role entry for root role")
	}

	oldThreshold := 1
	rotation := false
	oldKeys := map[string]data.PublicKey{}
	newKeys := map[string]data.PublicKey{}
	if oldRoot != nil {
		// check for matching root key IDs
		oldRootRole = oldRoot.Signed.Roles[rootRole]
		oldThreshold = oldRootRole.Threshold

		for _, kid := range oldRootRole.KeyIDs {
			k, ok := oldRoot.Signed.Keys[kid]
			if !ok {
				// if the key itself wasn't contained in the root
				// we're skipping it because it could never have
				// been used to validate this root.
				continue
			}
			oldKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public())
		}

		// super simple check for possible rotation
		rotation = len(oldKeys) != len(newRootRole.KeyIDs)
	}
	// if old and new had the same number of keys, iterate
	// to see if there's a difference.
	for _, kid := range newRootRole.KeyIDs {
		k, ok := newRoot.Signed.Keys[kid]
		if !ok {
			// if the key itself wasn't contained in the root
			// we're skipping it because it could never have
			// been used to validate this root.
			continue
		}
		newKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public())

		if oldRoot != nil {
			if _, ok := oldKeys[kid]; !ok {
				// if there is any difference in keys, a key rotation may have
				// occurred.
				rotation = true
			}
		}
	}
	newSigned, err := newRoot.ToSigned()
	if err != nil {
		return err
	}
	if rotation {
		err = signed.VerifyRoot(newSigned, oldThreshold, oldKeys)
		if err != nil {
			return fmt.Errorf("rotation detected and new root was not signed with at least %d old keys", oldThreshold)
		}
	}
	err = signed.VerifyRoot(newSigned, newRootRole.Threshold, newKeys)
	if err != nil {
		return err
	}
	root, err := data.RootFromSigned(newSigned)
	if err != nil {
		return err
	}
	// at a minimum, check the 4 required roles are present
	for _, r := range []string{rootRole, targetsRole, snapshotRole, timestampRole} {
		role, ok := root.Signed.Roles[r]
		if !ok {
			return fmt.Errorf("missing required %s role from root", r)
		}
		if role.Threshold < 1 {
			return fmt.Errorf("%s role has invalid threshold", r)
		}
		if len(role.KeyIDs) < role.Threshold {
			return fmt.Errorf("%s role has insufficient number of keys", r)
		}
	}
	return nil
}
コード例 #30
0
ファイル: validation.go プロジェクト: NathanMcCauley/notary
// checkRoot errors if an invalid rotation has taken place, if the
// threshold number of signatures is invalid, if there are an invalid
// number of roles and keys, or if the timestamp keys are invalid
func checkRoot(oldRoot, newRoot *data.SignedRoot, timestampKey data.PublicKey) error {
	rootRole := data.CanonicalRootRole
	targetsRole := data.CanonicalTargetsRole
	snapshotRole := data.CanonicalSnapshotRole
	timestampRole := data.CanonicalTimestampRole

	var oldRootRole *data.RootRole
	newRootRole, ok := newRoot.Signed.Roles[rootRole]
	if !ok {
		return errors.New("new root is missing role entry for root role")
	}

	oldThreshold := 1
	rotation := false
	oldKeys := map[string]data.PublicKey{}
	newKeys := map[string]data.PublicKey{}
	if oldRoot != nil {
		// check for matching root key IDs
		oldRootRole = oldRoot.Signed.Roles[rootRole]
		oldThreshold = oldRootRole.Threshold

		for _, kid := range oldRootRole.KeyIDs {
			k, ok := oldRoot.Signed.Keys[kid]
			if !ok {
				// if the key itself wasn't contained in the root
				// we're skipping it because it could never have
				// been used to validate this root.
				continue
			}
			oldKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public())
		}

		// super simple check for possible rotation
		rotation = len(oldKeys) != len(newRootRole.KeyIDs)
	}
	// if old and new had the same number of keys, iterate
	// to see if there's a difference.
	for _, kid := range newRootRole.KeyIDs {
		k, ok := newRoot.Signed.Keys[kid]
		if !ok {
			// if the key itself wasn't contained in the root
			// we're skipping it because it could never have
			// been used to validate this root.
			continue
		}
		newKeys[kid] = data.NewPublicKey(k.Algorithm(), k.Public())

		if oldRoot != nil {
			if _, ok := oldKeys[kid]; !ok {
				// if there is any difference in keys, a key rotation may have
				// occurred.
				rotation = true
			}
		}
	}
	newSigned, err := newRoot.ToSigned()
	if err != nil {
		return err
	}
	if rotation {
		err = signed.VerifyRoot(newSigned, oldThreshold, oldKeys)
		if err != nil {
			return fmt.Errorf("rotation detected and new root was not signed with at least %d old keys", oldThreshold)
		}
	}
	err = signed.VerifyRoot(newSigned, newRootRole.Threshold, newKeys)
	if err != nil {
		return err
	}
	root, err := data.RootFromSigned(newSigned)
	if err != nil {
		return err
	}

	var timestampKeyIDs []string

	// at a minimum, check the 4 required roles are present
	for _, r := range []string{rootRole, targetsRole, snapshotRole, timestampRole} {
		role, ok := root.Signed.Roles[r]
		if !ok {
			return fmt.Errorf("missing required %s role from root", r)
		}
		// According to the TUF spec, any role may have more than one signing
		// key and require a threshold signature.  However, notary-server
		// creates the timestamp, and there is only ever one, so a threshold
		// greater than one would just always fail validation
		if (r == timestampRole && role.Threshold != 1) || role.Threshold < 1 {
			return fmt.Errorf("%s role has invalid threshold", r)
		}
		if len(role.KeyIDs) < role.Threshold {
			return fmt.Errorf("%s role has insufficient number of keys", r)
		}

		if r == timestampRole {
			timestampKeyIDs = role.KeyIDs
		}
	}

	// ensure that at least one of the timestamp keys specified in the role
	// actually exists

	for _, keyID := range timestampKeyIDs {
		if timestampKey.ID() == keyID {
			return nil
		}
	}
	return fmt.Errorf("none of the following timestamp keys exist: %s",
		strings.Join(timestampKeyIDs, ", "))
}