mirror of https://github.com/docker/docs.git
Signature/key types are now used correcty and are represented by constants.
Signed-off-by: Diogo Monica <diogo@docker.com>
This commit is contained in:
parent
085c613527
commit
ba94fdd19d
|
@ -9,7 +9,6 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/notary/trustmanager"
|
||||
|
@ -72,7 +71,6 @@ func (ccs *RSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signa
|
|||
|
||||
var privKey *data.PrivateKey
|
||||
var err error
|
||||
var method string
|
||||
|
||||
// Read PrivateKey from file.
|
||||
// TODO(diogo): This assumes both that only root keys are encrypted and
|
||||
|
@ -80,12 +78,8 @@ func (ccs *RSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signa
|
|||
if ccs.passphrase != "" {
|
||||
// This is a root key
|
||||
privKey, err = ccs.keyStore.GetDecryptedKey(keyName, ccs.passphrase)
|
||||
// This method is added to the signature so verifiers can decode
|
||||
// the X509 certificate before trying to parse the public materials
|
||||
method = "RSASSA-PSS-X509"
|
||||
} else {
|
||||
privKey, err = ccs.keyStore.GetKey(keyName)
|
||||
method = "RSASSA-PSS"
|
||||
}
|
||||
if err != nil {
|
||||
// Note that GetDecryptedKey always fails on InitRepo.
|
||||
|
@ -107,12 +101,12 @@ func (ccs *RSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signa
|
|||
continue
|
||||
}
|
||||
|
||||
logrus.Debugf("appending RSA signature with Key ID: %s and method %s", privKey.ID(), method)
|
||||
logrus.Debugf("appending RSA signature with Key ID: %s", privKey.ID())
|
||||
|
||||
// Append signatures to result array
|
||||
signatures = append(signatures, data.Signature{
|
||||
KeyID: keyid,
|
||||
Method: method,
|
||||
Method: data.RSAPSSSignature,
|
||||
Signature: sig[:],
|
||||
})
|
||||
}
|
||||
|
@ -121,7 +115,7 @@ func (ccs *RSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signa
|
|||
}
|
||||
|
||||
func rsaSign(privKey *data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
if strings.ToUpper(privKey.Cipher()) != "RSA" {
|
||||
if privKey.Cipher() != data.RSAKey {
|
||||
return nil, fmt.Errorf("private key type not supported: %s", privKey.Cipher())
|
||||
}
|
||||
|
||||
|
@ -178,7 +172,6 @@ func (ccs *ECDSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Sig
|
|||
|
||||
var privKey *data.PrivateKey
|
||||
var err error
|
||||
var method string
|
||||
|
||||
// Read PrivateKey from file
|
||||
// TODO(diogo): This assumes both that only root keys are encrypted and
|
||||
|
@ -186,12 +179,8 @@ func (ccs *ECDSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Sig
|
|||
if ccs.passphrase != "" {
|
||||
// This is a root key
|
||||
privKey, err = ccs.keyStore.GetDecryptedKey(keyName, ccs.passphrase)
|
||||
// This method is added to the signature so verifiers can decode
|
||||
// the X509 certificate before trying to parse the public materials
|
||||
method = "ECDSA-X509"
|
||||
} else {
|
||||
privKey, err = ccs.keyStore.GetKey(keyName)
|
||||
method = "ECDSA"
|
||||
}
|
||||
if err != nil {
|
||||
// Note that GetDecryptedKey always fails on InitRepo.
|
||||
|
@ -218,12 +207,12 @@ func (ccs *ECDSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Sig
|
|||
continue
|
||||
}
|
||||
|
||||
logrus.Debugf("appending ECDSA signature with Key ID: %s and method: %s", privKey.ID(), method)
|
||||
logrus.Debugf("appending ECDSA signature with Key ID: %s", privKey.ID())
|
||||
|
||||
// Append signatures to result array
|
||||
signatures = append(signatures, data.Signature{
|
||||
KeyID: keyid,
|
||||
Method: method,
|
||||
Method: data.ECDSASignature,
|
||||
Signature: sig[:],
|
||||
})
|
||||
}
|
||||
|
@ -232,7 +221,7 @@ func (ccs *ECDSACryptoService) Sign(keyIDs []string, payload []byte) ([]data.Sig
|
|||
}
|
||||
|
||||
func ecdsaSign(privKey *data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
if strings.ToLower(privKey.Cipher()) != "ecdsa" {
|
||||
if privKey.Cipher() != data.ECDSAKey {
|
||||
return nil, fmt.Errorf("private key type not supported: %s", privKey.Cipher())
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
|
@ -143,14 +144,35 @@ func (r *NotaryRepository) Initialize(uSigner *UnlockedSigner) error {
|
|||
}
|
||||
r.certificateStore.AddCert(rootCert)
|
||||
|
||||
rootKey := data.NewPublicKey(uSigner.privKey.Cipher(), trustmanager.CertToPEM(rootCert))
|
||||
logrus.Debugf("Linking %s to %s.", rootKey.ID(), uSigner.ID())
|
||||
// The root key gets stored in the TUF metadata X509 encoded, linking
|
||||
// the tuf root.json to our X509 PKI.
|
||||
// If the key is RSA, we store it as type RSAx509, if it is ECDSA we store it
|
||||
// as ECDSAx509 to allow the gotuf verifiers to correctly decode the
|
||||
// key on verification of signatures.
|
||||
var cipherType string
|
||||
cipher := uSigner.privKey.Cipher()
|
||||
switch cipher {
|
||||
case data.RSAKey:
|
||||
cipherType = data.RSAx509Key
|
||||
case data.ECDSAKey:
|
||||
cipherType = data.ECDSAx509Key
|
||||
default:
|
||||
return fmt.Errorf("invalid format for root key: %s", cipher)
|
||||
}
|
||||
|
||||
// Generate a x509Key using the rootCert as the public key
|
||||
rootKey := data.NewPublicKey(cipherType, trustmanager.CertToPEM(rootCert))
|
||||
|
||||
// Creates a symlink between the certificate ID and the real public key it
|
||||
// is associated with. This is used to be able to retrieve the root private key
|
||||
// associated with a particular certificate
|
||||
logrus.Debugf("Linking %s to %s.", rootKey.ID(), uSigner.ID())
|
||||
err = r.rootKeyStore.Link(uSigner.ID(), rootKey.ID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// All the timestamp keys are generated by the remote server.
|
||||
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
|
||||
rawTSKey, err := remote.GetKey("timestamp")
|
||||
if err != nil {
|
||||
|
@ -163,10 +185,11 @@ func (r *NotaryRepository) Initialize(uSigner *UnlockedSigner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Turn the JSON timestamp key from the remote server into a TUFKey
|
||||
timestampKey := data.NewPublicKey(parsedKey.Cipher(), parsedKey.Public())
|
||||
logrus.Debugf("got remote %s timestamp key with keyID: %s", parsedKey.Cipher(), timestampKey.ID())
|
||||
logrus.Debugf("timestamp key: %s", rawTSKey)
|
||||
|
||||
// Targets and snapshot keys are always generated locally.
|
||||
targetsKey, err := r.signer.Create("targets")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -634,10 +657,10 @@ func (r *NotaryRepository) GenRootKey(algorithm, passphrase string) (string, err
|
|||
var err error
|
||||
var privKey *data.PrivateKey
|
||||
|
||||
switch algorithm {
|
||||
case "RSA":
|
||||
switch strings.ToLower(algorithm) {
|
||||
case data.RSAKey:
|
||||
privKey, err = trustmanager.GenerateRSAKey(rand.Reader, rsaRootKeySize)
|
||||
case "ECDSA":
|
||||
case data.ECDSAKey:
|
||||
privKey, err = trustmanager.GenerateECDSAKey(rand.Reader)
|
||||
default:
|
||||
return "", fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", algorithm)
|
||||
|
@ -647,6 +670,7 @@ func (r *NotaryRepository) GenRootKey(algorithm, passphrase string) (string, err
|
|||
return "", fmt.Errorf("failed to generate private key: %v", err)
|
||||
}
|
||||
|
||||
// Changing the root
|
||||
r.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase)
|
||||
|
||||
return privKey.ID(), nil
|
||||
|
@ -662,10 +686,10 @@ func (r *NotaryRepository) GetRootSigner(rootKeyID, passphrase string) (*Unlocke
|
|||
var signer *signed.Signer
|
||||
cipher := privKey.Cipher()
|
||||
// Passing an empty GUN because root keys aren't associated with a GUN.
|
||||
switch cipher {
|
||||
case "RSA":
|
||||
switch strings.ToLower(cipher) {
|
||||
case data.RSAKey:
|
||||
signer = signed.NewSigner(NewRSACryptoService("", r.rootKeyStore, passphrase))
|
||||
case "ECDSA":
|
||||
case data.ECDSAKey:
|
||||
signer = signed.NewSigner(NewECDSACryptoService("", r.rootKeyStore, passphrase))
|
||||
default:
|
||||
return nil, fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", cipher)
|
||||
|
@ -731,12 +755,12 @@ func (uk *UnlockedSigner) GenerateCertificate(gun string) (*x509.Certificate, er
|
|||
var privateKey crypto.PrivateKey
|
||||
var err error
|
||||
switch cipher {
|
||||
case "RSA":
|
||||
case data.RSAKey:
|
||||
var rsaPrivateKey *rsa.PrivateKey
|
||||
rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(uk.privKey.Private())
|
||||
privateKey = rsaPrivateKey
|
||||
publicKey = rsaPrivateKey.Public()
|
||||
case "ECDSA":
|
||||
case data.ECDSAKey:
|
||||
var ecdsaPrivateKey *ecdsa.PrivateKey
|
||||
ecdsaPrivateKey, err = x509.ParseECPrivateKey(uk.privKey.Private())
|
||||
privateKey = ecdsaPrivateKey
|
||||
|
|
|
@ -17,9 +17,12 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const timestampKeyJSON = `{"keytype":"RSA","keyval":{"public":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQAB","private":"MIIEpAIBAAKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQABAoIBAHar8FFxrE1gAGTeUpOF8fG8LIQMRwO4U6eVY7V9GpWiv6gOJTHXYFxU/aL0Ty3eQRxwy9tyVRo8EJz5pRex+e6ws1M+jLOviYqW4VocxQ8dZYd+zBvQfWmRfah7XXJ/HPUx2I05zrmR7VbGX6Bu4g5w3KnyIO61gfyQNKF2bm2Q3yblfupx3URvX0bl180R/+QN2Aslr4zxULFE6b+qJqBydrztq+AAP3WmskRxGa6irFnKxkspJqUpQN1mFselj6iQrzAcwkRPoCw0RwCCMq1/OOYvQtgxTJcO4zDVlbw54PvnxPZtcCWw7fO8oZ2Fvo2SDo75CDOATOGaT4Y9iqECgYEAzWZSpFbN9ZHmvq1lJQg//jFAyjsXRNn/nSvyLQILXltz6EHatImnXo3v+SivG91tfzBI1GfDvGUGaJpvKHoomB+qmhd8KIQhO5MBdAKZMf9fZqZofOPTD9xRXECCwdi+XqHBmL+l1OWz+O9Bh+Qobs2as/hQVgHaoXhQpE0NkTcCgYEA/Tjf6JBGl1+WxQDoGZDJrXoejzG9OFW19RjMdmPrg3t4fnbDtqTpZtCzXxPTCSeMrvplKbqAqZglWyq227ksKw4p7O6YfyhdtvC58oJmivlLr6sFaTsER7mDcYce8sQpqm+XQ8IPbnOk0Z1l6g56euTwTnew49uy25M6U1xL0P8CgYEAxEXv2Kw+OVhHV5PX4BBHHj6we88FiDyMfwM8cvfOJ0datekf9X7ImZkmZEAVPJpWBMD+B0J0jzU2b4SLjfFVkzBHVOH2Ob0xCH2MWPAWtekin7OKizUlPbW5ZV8b0+Kq30DQ/4a7D3rEhK8UPqeuX1tHZox1MAqrgbq3zJj4yvcCgYEAktYPKPm4pYCdmgFrlZ+bA0iEPf7Wvbsd91F5BtHsOOM5PQQ7e0bnvWIaEXEad/2CG9lBHlBy2WVLjDEZthILpa/h6e11ao8KwNGY0iKBuebT17rxOVMqqTjPGt8CuD2994IcEgOPFTpkAdUmyvG4XlkxbB8F6St17NPUB5DGuhsCgYA//Lfytk0FflXEeRQ16LT1YXgV7pcR2jsha4+4O5pxSFw/kTsOfJaYHg8StmROoyFnyE3sg76dCgLn0LENRCe5BvDhJnp5bMpQldG3XwcAxH8FGFNY4LtV/2ZKnJhxcONkfmzQPOmTyedOzrKQ+bNURsqLukCypP7/by6afBY4dA=="}}`
|
||||
// TODO(diogo): timestamps have to be the same keytype as targets and snapshots.
|
||||
// Can't test an RSA timestamp key until we stop hardcoding ECDSA as the default
|
||||
// CryptoService in NewNotaryRepository
|
||||
const timestampKeyJSON = `{"keytype":"rsa","keyval":{"public":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQAB","private":"MIIEpAIBAAKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQABAoIBAHar8FFxrE1gAGTeUpOF8fG8LIQMRwO4U6eVY7V9GpWiv6gOJTHXYFxU/aL0Ty3eQRxwy9tyVRo8EJz5pRex+e6ws1M+jLOviYqW4VocxQ8dZYd+zBvQfWmRfah7XXJ/HPUx2I05zrmR7VbGX6Bu4g5w3KnyIO61gfyQNKF2bm2Q3yblfupx3URvX0bl180R/+QN2Aslr4zxULFE6b+qJqBydrztq+AAP3WmskRxGa6irFnKxkspJqUpQN1mFselj6iQrzAcwkRPoCw0RwCCMq1/OOYvQtgxTJcO4zDVlbw54PvnxPZtcCWw7fO8oZ2Fvo2SDo75CDOATOGaT4Y9iqECgYEAzWZSpFbN9ZHmvq1lJQg//jFAyjsXRNn/nSvyLQILXltz6EHatImnXo3v+SivG91tfzBI1GfDvGUGaJpvKHoomB+qmhd8KIQhO5MBdAKZMf9fZqZofOPTD9xRXECCwdi+XqHBmL+l1OWz+O9Bh+Qobs2as/hQVgHaoXhQpE0NkTcCgYEA/Tjf6JBGl1+WxQDoGZDJrXoejzG9OFW19RjMdmPrg3t4fnbDtqTpZtCzXxPTCSeMrvplKbqAqZglWyq227ksKw4p7O6YfyhdtvC58oJmivlLr6sFaTsER7mDcYce8sQpqm+XQ8IPbnOk0Z1l6g56euTwTnew49uy25M6U1xL0P8CgYEAxEXv2Kw+OVhHV5PX4BBHHj6we88FiDyMfwM8cvfOJ0datekf9X7ImZkmZEAVPJpWBMD+B0J0jzU2b4SLjfFVkzBHVOH2Ob0xCH2MWPAWtekin7OKizUlPbW5ZV8b0+Kq30DQ/4a7D3rEhK8UPqeuX1tHZox1MAqrgbq3zJj4yvcCgYEAktYPKPm4pYCdmgFrlZ+bA0iEPf7Wvbsd91F5BtHsOOM5PQQ7e0bnvWIaEXEad/2CG9lBHlBy2WVLjDEZthILpa/h6e11ao8KwNGY0iKBuebT17rxOVMqqTjPGt8CuD2994IcEgOPFTpkAdUmyvG4XlkxbB8F6St17NPUB5DGuhsCgYA//Lfytk0FflXEeRQ16LT1YXgV7pcR2jsha4+4O5pxSFw/kTsOfJaYHg8StmROoyFnyE3sg76dCgLn0LENRCe5BvDhJnp5bMpQldG3XwcAxH8FGFNY4LtV/2ZKnJhxcONkfmzQPOmTyedOzrKQ+bNURsqLukCypP7/by6afBY4dA=="}}`
|
||||
const timestampECDSAKeyJSON = `
|
||||
{"keytype":"ECDSA","keyval":{"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw==","private":"MHcCAQEEIDqtcdzU7H3AbIPSQaxHl9+xYECt7NpK7B1+6ep5cv9CoAoGCCqGSM49AwEHoUQDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw=="}}`
|
||||
{"keytype":"ecdsa","keyval":{"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw==","private":"MHcCAQEEIDqtcdzU7H3AbIPSQaxHl9+xYECt7NpK7B1+6ep5cv9CoAoGCCqGSM49AwEHoUQDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw=="}}`
|
||||
|
||||
func createTestServer(t *testing.T) (*httptest.Server, *http.ServeMux) {
|
||||
mux := http.NewServeMux()
|
||||
|
@ -38,7 +41,13 @@ func createTestServer(t *testing.T) (*httptest.Server, *http.ServeMux) {
|
|||
|
||||
// TestInitRepo runs through the process of initializing a repository and makes
|
||||
// sure the repository looks correct on disk.
|
||||
// We test this with both an RSA and ECDSA root key
|
||||
func TestInitRepo(t *testing.T) {
|
||||
testInitRepo(t, data.RSAKey)
|
||||
testInitRepo(t, data.ECDSAKey)
|
||||
}
|
||||
|
||||
func testInitRepo(t *testing.T, rootType string) {
|
||||
gun := "docker.com/notary"
|
||||
// Temporary directory where test files will be created
|
||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||
|
@ -52,7 +61,7 @@ func TestInitRepo(t *testing.T) {
|
|||
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport)
|
||||
assert.NoError(t, err, "error creating repo: %s", err)
|
||||
|
||||
rootKeyID, err := repo.GenRootKey("ECDSA", "passphrase")
|
||||
rootKeyID, err := repo.GenRootKey(rootType, "passphrase")
|
||||
assert.NoError(t, err, "error generating root key: %s", err)
|
||||
|
||||
rootSigner, err := repo.GetRootSigner(rootKeyID, "passphrase")
|
||||
|
@ -173,7 +182,13 @@ type tufChange struct {
|
|||
// is updated correctly. Then it calls ListTargets and checks the return value.
|
||||
// Using ListTargets involves serving signed metadata files over the test's
|
||||
// internal HTTP server.
|
||||
// We test this with both an RSA and ECDSA root key
|
||||
func TestAddListTarget(t *testing.T) {
|
||||
testAddListTarget(t, data.RSAKey)
|
||||
testAddListTarget(t, data.ECDSAKey)
|
||||
}
|
||||
|
||||
func testAddListTarget(t *testing.T, rootType string) {
|
||||
// Temporary directory where test files will be created
|
||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||
defer os.RemoveAll(tempBaseDir)
|
||||
|
@ -188,7 +203,7 @@ func TestAddListTarget(t *testing.T) {
|
|||
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport)
|
||||
assert.NoError(t, err, "error creating repository: %s", err)
|
||||
|
||||
rootKeyID, err := repo.GenRootKey("ECDSA", "passphrase")
|
||||
rootKeyID, err := repo.GenRootKey(rootType, "passphrase")
|
||||
assert.NoError(t, err, "error generating root key: %s", err)
|
||||
|
||||
rootSigner, err := repo.GetRootSigner(rootKeyID, "passphrase")
|
||||
|
@ -352,6 +367,11 @@ func TestAddListTarget(t *testing.T) {
|
|||
// TestValidateRootKey verifies that the public data in root.json for the root
|
||||
// key is a valid x509 certificate.
|
||||
func TestValidateRootKey(t *testing.T) {
|
||||
testValidateRootKey(t, data.RSAKey)
|
||||
testValidateRootKey(t, data.ECDSAKey)
|
||||
}
|
||||
|
||||
func testValidateRootKey(t *testing.T, rootType string) {
|
||||
// Temporary directory where test files will be created
|
||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||
defer os.RemoveAll(tempBaseDir)
|
||||
|
@ -366,7 +386,7 @@ func TestValidateRootKey(t *testing.T) {
|
|||
repo, err := NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport)
|
||||
assert.NoError(t, err, "error creating repository: %s", err)
|
||||
|
||||
rootKeyID, err := repo.GenRootKey("ECDSA", "passphrase")
|
||||
rootKeyID, err := repo.GenRootKey(rootType, "passphrase")
|
||||
assert.NoError(t, err, "error generating root key: %s", err)
|
||||
|
||||
rootSigner, err := repo.GetRootSigner(rootKeyID, "passphrase")
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -9,7 +11,9 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
notaryclient "github.com/docker/notary/client"
|
||||
"github.com/endophage/gotuf/data"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
@ -116,7 +120,7 @@ func tufInit(cmd *cobra.Command, args []string) {
|
|||
if err != nil {
|
||||
fatalf(err.Error())
|
||||
}
|
||||
rootKeyID, err = nRepo.GenRootKey("ECDSA", passphrase)
|
||||
rootKeyID, err = nRepo.GenRootKey(data.ECDSAKey, passphrase)
|
||||
if err != nil {
|
||||
fatalf(err.Error())
|
||||
}
|
||||
|
@ -279,3 +283,43 @@ func passphraseRetriever() (string, error) {
|
|||
}
|
||||
return passphrase, nil
|
||||
}
|
||||
|
||||
func getPassphrase(confirm bool) ([]byte, error) {
|
||||
if pass := os.Getenv("NOTARY_ROOT_PASSPHRASE"); pass != "" {
|
||||
return []byte(pass), nil
|
||||
}
|
||||
|
||||
state, err := term.SaveState(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
term.DisableEcho(0, state)
|
||||
defer term.RestoreTerminal(0, state)
|
||||
|
||||
stdin := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Printf("Enter root key passphrase: ")
|
||||
passphrase, err := stdin.ReadBytes('\n')
|
||||
fmt.Println()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
passphrase = passphrase[0 : len(passphrase)-1]
|
||||
|
||||
if !confirm {
|
||||
return passphrase, nil
|
||||
}
|
||||
|
||||
fmt.Printf("Repeat root key passphrase: ")
|
||||
confirmation, err := stdin.ReadBytes('\n')
|
||||
fmt.Println()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
confirmation = confirmation[0 : len(confirmation)-1]
|
||||
|
||||
if !bytes.Equal(passphrase, confirmation) {
|
||||
return nil, errors.New("The entered passphrases do not match")
|
||||
}
|
||||
return passphrase, nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package storage
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/endophage/gotuf/data"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -46,23 +47,23 @@ func TestGetTimestampKey(t *testing.T) {
|
|||
//_, _, err := s.GetTimestampKey("gun")
|
||||
//assert.IsType(t, &ErrNoKey{}, err, "Expected err to be ErrNoKey")
|
||||
|
||||
s.SetTimestampKey("gun", "RSA", []byte("test"))
|
||||
s.SetTimestampKey("gun", data.RSAKey, []byte("test"))
|
||||
|
||||
c, k, err := s.GetTimestampKey("gun")
|
||||
assert.Nil(t, err, "Expected error to be nil")
|
||||
assert.Equal(t, "RSA", c, "Expected cipher rsa, received %s", c)
|
||||
assert.Equal(t, data.RSAKey, c, "Expected cipher rsa, received %s", c)
|
||||
assert.Equal(t, []byte("test"), k, "Key data was wrong")
|
||||
}
|
||||
|
||||
func TestSetTimestampKey(t *testing.T) {
|
||||
s := NewMemStorage()
|
||||
s.SetTimestampKey("gun", "RSA", []byte("test"))
|
||||
s.SetTimestampKey("gun", data.RSAKey, []byte("test"))
|
||||
|
||||
err := s.SetTimestampKey("gun", "RSA", []byte("test2"))
|
||||
err := s.SetTimestampKey("gun", data.RSAKey, []byte("test2"))
|
||||
assert.IsType(t, &ErrTimestampKeyExists{}, err, "Expected err to be ErrTimestampKeyExists")
|
||||
|
||||
k := s.tsKeys["gun"]
|
||||
assert.Equal(t, "RSA", k.cipher, "Expected cipher to be rsa, received %s", k.cipher)
|
||||
assert.Equal(t, data.RSAKey, k.cipher, "Expected cipher to be rsa, received %s", k.cipher)
|
||||
assert.Equal(t, []byte("test"), k.public, "Public key did not match expected")
|
||||
|
||||
}
|
||||
|
|
|
@ -103,9 +103,9 @@ func fingerprintCert(cert *x509.Certificate) (CertID, error) {
|
|||
keyType := ""
|
||||
switch cert.PublicKeyAlgorithm {
|
||||
case x509.RSA:
|
||||
keyType = "RSA"
|
||||
keyType = data.RSAx509Key
|
||||
case x509.ECDSA:
|
||||
keyType = "ECDSA"
|
||||
keyType = data.ECDSAx509Key
|
||||
default:
|
||||
return "", fmt.Errorf("error while fingerprinting certificate. Got Unknown key type.")
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ func ParsePEMPrivateKey(pemBytes []byte, passphrase string) (*data.PrivateKey, e
|
|||
return nil, fmt.Errorf("could not parse DER encoded key: %v", err)
|
||||
}
|
||||
|
||||
tufRSAPrivateKey, err := RSAToPrivateKey(rsaPrivKey)
|
||||
tufRSAPrivateKey, err := RSAToPrivateKey(rsaPrivKey, data.RSAKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert rsa.PrivateKey to data.PrivateKey: %v", err)
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ func ParsePEMPrivateKey(pemBytes []byte, passphrase string) (*data.PrivateKey, e
|
|||
return nil, fmt.Errorf("could not parse DER encoded private key: %v", err)
|
||||
}
|
||||
|
||||
tufRSAPrivateKey, err := ECDSAToPrivateKey(rsaPrivKey)
|
||||
tufRSAPrivateKey, err := ECDSAToPrivateKey(rsaPrivKey, data.ECDSAKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert ecdsa.PrivateKey to data.PrivateKey: %v", err)
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ func GenerateRSAKey(random io.Reader, bits int) (*data.PrivateKey, error) {
|
|||
return nil, fmt.Errorf("could not generate private key: %v", err)
|
||||
}
|
||||
|
||||
tufPrivKey, err := RSAToPrivateKey(rsaPrivKey)
|
||||
tufPrivKey, err := RSAToPrivateKey(rsaPrivKey, data.RSAKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ func GenerateRSAKey(random io.Reader, bits int) (*data.PrivateKey, error) {
|
|||
}
|
||||
|
||||
// RSAToPrivateKey converts an rsa.Private key to a TUF data.PrivateKey type
|
||||
func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (*data.PrivateKey, error) {
|
||||
func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey, keyType string) (*data.PrivateKey, error) {
|
||||
// Get a DER-encoded representation of the PublicKey
|
||||
rsaPubBytes, err := x509.MarshalPKIXPublicKey(&rsaPrivKey.PublicKey)
|
||||
if err != nil {
|
||||
|
@ -238,7 +238,7 @@ func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (*data.PrivateKey, error) {
|
|||
// Get a DER-encoded representation of the PrivateKey
|
||||
rsaPrivBytes := x509.MarshalPKCS1PrivateKey(rsaPrivKey)
|
||||
|
||||
return data.NewPrivateKey("RSA", rsaPubBytes, rsaPrivBytes), nil
|
||||
return data.NewPrivateKey(keyType, rsaPubBytes, rsaPrivBytes), nil
|
||||
}
|
||||
|
||||
// GenerateECDSAKey generates an ECDSA Private key and returns a TUF PrivateKey
|
||||
|
@ -250,7 +250,7 @@ func GenerateECDSAKey(random io.Reader) (*data.PrivateKey, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tufPrivKey, err := ECDSAToPrivateKey(ecdsaPrivKey)
|
||||
tufPrivKey, err := ECDSAToPrivateKey(ecdsaPrivKey, data.ECDSAKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ func GenerateECDSAKey(random io.Reader) (*data.PrivateKey, error) {
|
|||
}
|
||||
|
||||
// ECDSAToPrivateKey converts an rsa.Private key to a TUF data.PrivateKey type
|
||||
func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey) (*data.PrivateKey, error) {
|
||||
func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey, keyType string) (*data.PrivateKey, error) {
|
||||
// Get a DER-encoded representation of the PublicKey
|
||||
ecdsaPubBytes, err := x509.MarshalPKIXPublicKey(&ecdsaPrivKey.PublicKey)
|
||||
if err != nil {
|
||||
|
@ -274,7 +274,7 @@ func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey) (*data.PrivateKey, error)
|
|||
return nil, fmt.Errorf("failed to marshal private key: %v", err)
|
||||
}
|
||||
|
||||
return data.NewPrivateKey("ECDSA", ecdsaPubBytes, ecdsaPrivKeyBytes), nil
|
||||
return data.NewPrivateKey(keyType, ecdsaPubBytes, ecdsaPrivKeyBytes), nil
|
||||
}
|
||||
|
||||
// KeyToPEM returns a PEM encoded key from a Private Key
|
||||
|
@ -283,9 +283,9 @@ func KeyToPEM(privKey *data.PrivateKey) ([]byte, error) {
|
|||
cipher := privKey.Cipher()
|
||||
|
||||
switch cipher {
|
||||
case "RSA":
|
||||
case data.RSAKey:
|
||||
pemType = "RSA PRIVATE KEY"
|
||||
case "ECDSA":
|
||||
case data.ECDSAKey:
|
||||
pemType = "EC PRIVATE KEY"
|
||||
default:
|
||||
return nil, fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", cipher)
|
||||
|
@ -301,9 +301,9 @@ func EncryptPrivateKey(key *data.PrivateKey, passphrase string) ([]byte, error)
|
|||
cipher := key.Cipher()
|
||||
|
||||
switch cipher {
|
||||
case "RSA":
|
||||
case data.RSAKey:
|
||||
blockType = "RSA PRIVATE KEY"
|
||||
case "ECDSA":
|
||||
case data.ECDSAKey:
|
||||
blockType = "EC PRIVATE KEY"
|
||||
default:
|
||||
return nil, fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", cipher)
|
||||
|
|
Loading…
Reference in New Issue