Skip to content

Commit

Permalink
Allow non-cert public keys
Browse files Browse the repository at this point in the history
Signed-off-by: Evan Cordell <cordell.evan@gmail.com>
  • Loading branch information
ecordell committed Sep 26, 2016
1 parent 6350e8a commit bea9d25
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 15 deletions.
69 changes: 55 additions & 14 deletions trustpinning/certs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,7 @@ func TestValidateRootWithPinnedCert(t *testing.T) {
func TestValidateRootWithPinnedCertAndIntermediates(t *testing.T) {
now := time.Now()
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)

pass := func(keyName, alias string, createNew bool, attempts int) (passphrase string, giveup bool, err error) {
return "password", false, nil
}
memStore := trustmanager.NewKeyMemoryStore(pass)
memStore := trustmanager.NewKeyMemoryStore(passphraseRetriever)
cs := cryptoservice.NewCryptoService(memStore)

// generate CA cert
Expand Down Expand Up @@ -1007,12 +1003,61 @@ func generateExpiredTestingCertificate(rootKey data.PrivateKey, gun string) (*x5
return cryptoservice.GenerateCertificate(rootKey, gun, startTime, startTime.AddDate(1, 0, 0))
}

// Helper function for explicitly generating key IDs and unexported fields for equality testing
func generateRootKeyIDs(r *data.SignedRoot) {
for _, keyID := range r.Signed.Roles[data.CanonicalRootRole].KeyIDs {
if k, ok := r.Signed.Keys[keyID]; ok {
_ = k.ID()
}
}
}

func TestParsePEMPublicKey(t *testing.T) {
gun := "notary"
memStore := trustmanager.NewKeyMemoryStore(passphraseRetriever)
cs := cryptoservice.NewCryptoService(memStore)

// can parse ECDSA PEM
ecdsaPubKey, err := cs.Create("root", "docker.io/notary/test", data.ECDSAKey)
require.NoError(t, err)
ecdsaPemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Headers: nil,
Bytes: ecdsaPubKey.Public(),
})

ecdsaParsedPubKey, err := utils.ParsePEMPublicKey(ecdsaPemBytes)
require.NoError(t, err, "no key: %s", ecdsaParsedPubKey.Public())

// can parse certificates
ecdsaPrivKey, _, err := memStore.GetKey(ecdsaPubKey.ID())
require.NoError(t, err)
cert, err := generateTestingCertificate(ecdsaPrivKey, gun, notary.Day*30)
require.NoError(t, err)
ecdsaPubKeyFromCert, err := utils.ParsePEMPublicKey(utils.CertToPEM(cert))
require.NoError(t, err)

thatData := []byte{1, 2, 3, 4}
sig, err := ecdsaPrivKey.Sign(rand.Reader, thatData, nil)
require.NoError(t, err)
err = signed.ECDSAVerifier{}.Verify(ecdsaPubKeyFromCert, sig, thatData)
require.NoError(t, err)

// can parse RSA PEM
rsaPubKey, err := cs.Create("root", "docker.io/notary/test2", data.RSAKey)
require.NoError(t, err)
rsaPemBytes := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Headers: nil,
Bytes: rsaPubKey.Public(),
})
_, err = utils.ParsePEMPublicKey(rsaPemBytes)
require.NoError(t, err)
}

func TestCheckingCertExpiry(t *testing.T) {
gun := "notary"
pass := func(keyName, alias string, createNew bool, attempts int) (passphrase string, giveup bool, err error) {
return "password", false, nil
}
memStore := trustmanager.NewKeyMemoryStore(pass)
memStore := trustmanager.NewKeyMemoryStore(passphraseRetriever)
cs := cryptoservice.NewCryptoService(memStore)
testPubKey, err := cs.Create(data.CanonicalRootRole, gun, data.ECDSAKey)
require.NoError(t, err)
Expand Down Expand Up @@ -1088,11 +1133,7 @@ func TestCheckingCertExpiry(t *testing.T) {
func TestValidateRootWithExpiredIntermediate(t *testing.T) {
now := time.Now()
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)

pass := func(keyName, alias string, createNew bool, attempts int) (passphrase string, giveup bool, err error) {
return "password", false, nil
}
memStore := trustmanager.NewKeyMemoryStore(pass)
memStore := trustmanager.NewKeyMemoryStore(passphraseRetriever)
cs := cryptoservice.NewCryptoService(memStore)

// generate CA cert
Expand Down
22 changes: 21 additions & 1 deletion tuf/utils/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,29 @@ func ParsePEMPublicKey(pubKeyBytes []byte) (data.PublicKey, error) {
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", pemBlock.Type)
return nil, fmt.Errorf("unsupported PEM block type %q, expected CERTIFICATE or PUBLIC KEY", pemBlock.Type)
}
}

func keyTypeForPublicKey(pubKeyBytes []byte) (string, error) {
pub, err := x509.ParsePKIXPublicKey(pubKeyBytes)
if err != nil {
return "", fmt.Errorf("unable to parse pem encoded public key: %v", err)
}
switch pub.(type) {
case *ecdsa.PublicKey:
return data.ECDSAKey, nil
case *rsa.PublicKey:
return data.RSAKey, nil
}
return "", fmt.Errorf("unknown public key format")
}

// ValidateCertificate returns an error if the certificate is not valid for notary
Expand Down

0 comments on commit bea9d25

Please sign in to comment.