From 06990fd5a1006c05f8ab63cdbe2e7db7caf42c52 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 29 Oct 2015 19:31:55 -0700 Subject: [PATCH] integreating with @cyli's improvements Signed-off-by: David Lawrence (github: endophage) --- cryptoservice/certificate.go | 30 +---- cryptoservice/crypto_service.go | 101 ++------------- cryptoservice/crypto_service_test.go | 2 +- signer/keydbstore.go | 5 +- trustmanager/x509utils.go | 6 +- tuf/data/keys.go | 182 +++++++++++---------------- tuf/signed/ed25519.go | 6 +- tuf/signed/verifiers_test.go | 3 +- 8 files changed, 104 insertions(+), 231 deletions(-) diff --git a/cryptoservice/certificate.go b/cryptoservice/certificate.go index 2df51bb1dd..6e932ed288 100644 --- a/cryptoservice/certificate.go +++ b/cryptoservice/certificate.go @@ -1,10 +1,7 @@ package cryptoservice import ( - "crypto" - "crypto/ecdsa" "crypto/rand" - "crypto/rsa" "crypto/x509" "fmt" @@ -15,28 +12,11 @@ import ( // GenerateCertificate generates an X509 Certificate from a template, given a GUN func GenerateCertificate(rootKey data.PrivateKey, gun string) (*x509.Certificate, error) { - algorithm := rootKey.Algorithm() - var ( - publicKey crypto.PublicKey - privateKey crypto.PrivateKey - err error - ) - switch algorithm { - case data.RSAKey: - var rsaPrivateKey *rsa.PrivateKey - rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(rootKey.Private()) - privateKey = rsaPrivateKey - publicKey = rsaPrivateKey.Public() - case data.ECDSAKey: - var ecdsaPrivateKey *ecdsa.PrivateKey - ecdsaPrivateKey, err = x509.ParseECPrivateKey(rootKey.Private()) - privateKey = ecdsaPrivateKey - publicKey = ecdsaPrivateKey.Public() + switch rootKey.(type) { + case *data.RSAPrivateKey, *data.ECDSAPrivateKey: + // go doesn't fall through default: - return nil, fmt.Errorf("only RSA or ECDSA keys are currently supported. Found: %s", algorithm) - } - if err != nil { - return nil, fmt.Errorf("failed to parse root key: %s (%v)", gun, err) + return nil, fmt.Errorf("only bare RSA or ECDSA keys (not x509 variants) are currently supported. Found: %s", rootKey.Algorithm()) } template, err := trustmanager.NewCertificate(gun) @@ -44,7 +24,7 @@ func GenerateCertificate(rootKey data.PrivateKey, gun string) (*x509.Certificate return nil, fmt.Errorf("failed to create the certificate template for: %s (%v)", gun, err) } - derBytes, err := x509.CreateCertificate(rand.Reader, template, template, publicKey, privateKey) + derBytes, err := x509.CreateCertificate(rand.Reader, template, template, rootKey.CryptoSigner().Public(), rootKey.CryptoSigner()) if err != nil { return nil, fmt.Errorf("failed to create the certificate for: %s (%v)", gun, err) } diff --git a/cryptoservice/crypto_service.go b/cryptoservice/crypto_service.go index 8f39ee90ee..1a80807d21 100644 --- a/cryptoservice/crypto_service.go +++ b/cryptoservice/crypto_service.go @@ -1,17 +1,11 @@ package cryptoservice import ( - "crypto" - "crypto/ecdsa" "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" "fmt" "path/filepath" "github.com/Sirupsen/logrus" - "github.com/agl/ed25519" "github.com/docker/notary/trustmanager" "github.com/docker/notary/tuf/data" ) @@ -91,18 +85,14 @@ func (ccs *CryptoService) RemoveKey(keyID string) error { func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signature, error) { signatures := make([]data.Signature, 0, len(keyIDs)) for _, keyid := range keyIDs { - var ( - privKey data.PrivateKey - err error - keyName = keyid - ) + keyName := keyid // Try to get the key first without a GUN (in which case it's a root // key). If that fails, try to get the key with the GUN (non-root // key). If that fails, then we don't have the key. - privKey, _, err = ccs.keyStore.GetKey(keyName) + privKey, _, err := ccs.keyStore.GetKey(keyName) if err != nil { - keyName := filepath.Join(ccs.gun, keyid) + keyName = filepath.Join(ccs.gun, keyid) privKey, _, err = ccs.keyStore.GetKey(keyName) if err != nil { logrus.Debugf("error attempting to retrieve key ID: %s, %v", keyid, err) @@ -110,28 +100,23 @@ func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signatur } } - algorithm := privKey.Algorithm() var sigAlgorithm data.SigAlgorithm - var sig []byte - switch algorithm { - case data.RSAKey: - sig, err = rsaSign(privKey, payload) + switch privKey.(type) { + case *data.RSAPrivateKey: sigAlgorithm = data.RSAPSSSignature - case data.ECDSAKey: - sig, err = ecdsaSign(privKey, payload) + case *data.ECDSAPrivateKey: sigAlgorithm = data.ECDSASignature - case data.ED25519Key: - // ED25519 does not operate on a SHA256 hash - sig, err = ed25519Sign(privKey, payload) + case *data.ED25519PrivateKey: sigAlgorithm = data.EDDSASignature } + sig, err := privKey.Sign(rand.Reader, payload, nil) if err != nil { - logrus.Debugf("ignoring error attempting to %s sign with keyID: %s, %v", algorithm, keyid, err) + logrus.Debugf("ignoring error attempting to %s sign with keyID: %s, %v", privKey.Algorithm(), keyid, err) return nil, err } - logrus.Debugf("appending %s signature with Key ID: %s", algorithm, keyid) + logrus.Debugf("appending %s signature with Key ID: %s", privKey.Algorithm(), keyid) // Append signatures to result array signatures = append(signatures, data.Signature{ @@ -143,69 +128,3 @@ func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signatur return signatures, nil } - -func rsaSign(privKey data.PrivateKey, message []byte) ([]byte, error) { - if privKey.Algorithm() != data.RSAKey { - return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) - } - - hashed := sha256.Sum256(message) - - // Create an rsa.PrivateKey out of the private key bytes - rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.Private()) - if err != nil { - return nil, err - } - - // Use the RSA key to RSASSA-PSS sign the data - sig, err := rsa.SignPSS(rand.Reader, rsaPrivKey, crypto.SHA256, hashed[:], &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) - if err != nil { - return nil, err - } - - return sig, nil -} - -func ecdsaSign(privKey data.PrivateKey, message []byte) ([]byte, error) { - if privKey.Algorithm() != data.ECDSAKey { - return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) - } - - hashed := sha256.Sum256(message) - - // Create an ecdsa.PrivateKey out of the private key bytes - ecdsaPrivKey, err := x509.ParseECPrivateKey(privKey.Private()) - if err != nil { - return nil, err - } - - // Use the ECDSA key to sign the data - r, s, err := ecdsa.Sign(rand.Reader, ecdsaPrivKey, hashed[:]) - if err != nil { - return nil, err - } - - rBytes, sBytes := r.Bytes(), s.Bytes() - octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3 - - // MUST include leading zeros in the output - rBuf := make([]byte, octetLength-len(rBytes), octetLength) - sBuf := make([]byte, octetLength-len(sBytes), octetLength) - - rBuf = append(rBuf, rBytes...) - sBuf = append(sBuf, sBytes...) - - return append(rBuf, sBuf...), nil -} - -func ed25519Sign(privKey data.PrivateKey, message []byte) ([]byte, error) { - if privKey.Algorithm() != data.ED25519Key { - return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) - } - - priv := [ed25519.PrivateKeySize]byte{} - copy(priv[:], privKey.Private()[ed25519.PublicKeySize:]) - sig := ed25519.Sign(&priv, message) - - return sig[:], nil -} diff --git a/cryptoservice/crypto_service_test.go b/cryptoservice/crypto_service_test.go index a3b1197d7c..4ed3682a79 100644 --- a/cryptoservice/crypto_service_test.go +++ b/cryptoservice/crypto_service_test.go @@ -35,7 +35,7 @@ func testCryptoService(t *testing.T, keyAlgo string, verifier signed.Verifier) { assert.Len(t, signatures, 1, "wrong number of signatures") err = verifier.Verify(tufKey, signatures[0].Signature, content) - assert.NoError(t, err, "verification failed") + assert.NoError(t, err, "verification failed for %s key type", keyAlgo) // Test GetKey retrievedKey := cryptoService.GetKey(tufKey.ID()) diff --git a/signer/keydbstore.go b/signer/keydbstore.go index 163b6a08a9..06576b209a 100644 --- a/signer/keydbstore.go +++ b/signer/keydbstore.go @@ -126,7 +126,10 @@ func (s *KeyDBStore) GetKey(name string) (data.PrivateKey, string, error) { pubKey := data.NewPublicKey(dbPrivateKey.Algorithm, []byte(dbPrivateKey.Public)) // Create a new PrivateKey with unencrypted bytes - privKey := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey)) + privKey, err := data.NewPrivateKey(pubKey, []byte(decryptedPrivKey)) + if err != nil { + return nil, "", err + } // Add the key to cache s.cachedKeys[privKey.ID()] = privKey diff --git a/trustmanager/x509utils.go b/trustmanager/x509utils.go index 0c2c8fe0d7..e462671a04 100644 --- a/trustmanager/x509utils.go +++ b/trustmanager/x509utils.go @@ -325,7 +325,7 @@ func RSAToPrivateKey(rsaPrivKey *rsa.PrivateKey) (data.PrivateKey, error) { rsaPrivBytes := x509.MarshalPKCS1PrivateKey(rsaPrivKey) pubKey := data.NewRSAPublicKey(rsaPubBytes) - return data.NewRSAPrivateKey(*pubKey, rsaPrivBytes), nil + return data.NewRSAPrivateKey(pubKey, rsaPrivBytes) } // GenerateECDSAKey generates an ECDSA Private key and returns a TUF PrivateKey @@ -383,7 +383,7 @@ func ECDSAToPrivateKey(ecdsaPrivKey *ecdsa.PrivateKey) (data.PrivateKey, error) } pubKey := data.NewECDSAPublicKey(ecdsaPubBytes) - return data.NewECDSAPrivateKey(*pubKey, ecdsaPrivKeyBytes), nil + return data.NewECDSAPrivateKey(pubKey, ecdsaPrivKeyBytes) } // ED25519ToPrivateKey converts a serialized ED25519 key to a TUF @@ -394,7 +394,7 @@ func ED25519ToPrivateKey(privKeyBytes []byte) (data.PrivateKey, error) { } pubKey := data.NewED25519PublicKey(privKeyBytes[:ed25519.PublicKeySize]) - return data.NewED25519PrivateKey(*pubKey, privKeyBytes), nil + return data.NewED25519PrivateKey(*pubKey, privKeyBytes) } func blockType(k data.PrivateKey) (string, error) { diff --git a/tuf/data/keys.go b/tuf/data/keys.go index 71bddb8e98..be5e297f42 100644 --- a/tuf/data/keys.go +++ b/tuf/data/keys.go @@ -3,6 +3,7 @@ package data import ( "crypto" "crypto/ecdsa" + "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/asn1" @@ -28,6 +29,7 @@ type PrivateKey interface { PublicKey Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) Private() []byte + CryptoSigner() crypto.Signer } // KeyPair holds the public and private key bytes @@ -90,34 +92,34 @@ func typedPublicKey(tk tufKey) PublicKey { return &UnknownPublicKey{tufKey: tk} } -func typedPrivateKey(tk tufKey) PrivateKey { +func typedPrivateKey(tk tufKey) (PrivateKey, error) { private := tk.Value.Private tk.Value.Private = nil switch tk.Algorithm() { case ECDSAKey: return NewECDSAPrivateKey( - ECDSAPublicKey{ + &ECDSAPublicKey{ tufKey: tk, }, private, ) case ECDSAx509Key: - return NewECDSAx509PrivateKey( - ECDSAx509PublicKey{ + return NewECDSAPrivateKey( + &ECDSAx509PublicKey{ tufKey: tk, }, private, ) case RSAKey: return NewRSAPrivateKey( - RSAPublicKey{ + &RSAPublicKey{ tufKey: tk, }, private, ) case RSAx509Key: - return NewRSAx509PrivateKey( - RSAx509PublicKey{ + return NewRSAPrivateKey( + &RSAx509PublicKey{ tufKey: tk, }, private, @@ -133,7 +135,7 @@ func typedPrivateKey(tk tufKey) PrivateKey { return &UnknownPrivateKey{ tufKey: tk, privateKey: privateKey{private: private}, - } + }, nil } // NewPublicKey creates a new, correctly typed PublicKey, using the @@ -150,7 +152,7 @@ func NewPublicKey(alg string, public []byte) PublicKey { // NewPrivateKey creates a new, correctly typed PrivateKey, using the // UnknownPrivateKey catchall for unsupported ciphers -func NewPrivateKey(pubKey PublicKey, private []byte) PrivateKey { +func NewPrivateKey(pubKey PublicKey, private []byte) (PrivateKey, error) { tk := tufKey{ Type: pubKey.Algorithm(), Value: KeyPair{ @@ -178,7 +180,7 @@ func UnmarshalPrivateKey(data []byte) (PrivateKey, error) { if err != nil { return nil, err } - return typedPrivateKey(parsed), nil + return typedPrivateKey(parsed) } // tufKey is the structure used for both public and private keys in TUF. @@ -329,34 +331,22 @@ type privateKey struct { private []byte } -// ECDSAPrivateKey represents a private ECDSA key -type ECDSAPrivateKey struct { - ECDSAPublicKey - privateKey - Signer crypto.Signer +type signer struct { + signer crypto.Signer } -// ECDSAx509PrivateKey represents a private ECDSA key where the public -// component is serialized into an x509 cert -type ECDSAx509PrivateKey struct { - ECDSAx509PublicKey +// ECDSAPrivateKey represents a private ECDSA key +type ECDSAPrivateKey struct { + PublicKey privateKey - Signer crypto.Signer + signer } // RSAPrivateKey represents a private RSA key type RSAPrivateKey struct { - RSAPublicKey + PublicKey privateKey - Signer crypto.Signer -} - -// RSAx509PrivateKey represents a private RSA key where the public -// component is serialized into an x509 cert -type RSAx509PrivateKey struct { - RSAx509PublicKey - privateKey - Signer crypto.Signer + signer } // ED25519PrivateKey represents a private ED25519 key @@ -372,63 +362,47 @@ type UnknownPrivateKey struct { } // NewECDSAPrivateKey initializes a new ECDSA private key -func NewECDSAPrivateKey(public ECDSAPublicKey, private []byte) *ECDSAPrivateKey { +func NewECDSAPrivateKey(public PublicKey, private []byte) (*ECDSAPrivateKey, error) { + switch public.(type) { + case *ECDSAPublicKey, *ECDSAx509PublicKey: + default: + return nil, errors.New("Invalid public key type provided to NewECDSAPrivateKey") + } ecdsaPrivKey, err := x509.ParseECPrivateKey(private) if err != nil { - return nil + return nil, err } return &ECDSAPrivateKey{ - ECDSAPublicKey: public, - privateKey: privateKey{private: private}, - Signer: ecdsaPrivKey, - } -} - -// NewECDSAx509PrivateKey initializes a new ECDSA private key -func NewECDSAx509PrivateKey(public ECDSAx509PublicKey, private []byte) *ECDSAx509PrivateKey { - ecdsaPrivKey, err := x509.ParseECPrivateKey(private) - if err != nil { - return nil - } - return &ECDSAx509PrivateKey{ - ECDSAx509PublicKey: public, - privateKey: privateKey{private: private}, - Signer: ecdsaPrivKey, - } + PublicKey: public, + privateKey: privateKey{private: private}, + signer: signer{signer: ecdsaPrivKey}, + }, nil } // NewRSAPrivateKey initialized a new RSA private key -func NewRSAPrivateKey(public RSAPublicKey, private []byte) *RSAPrivateKey { +func NewRSAPrivateKey(public PublicKey, private []byte) (*RSAPrivateKey, error) { + switch public.(type) { + case *RSAPublicKey, *RSAx509PublicKey: + default: + return nil, errors.New("Invalid public key type provided to NewRSAPrivateKey") + } rsaPrivKey, err := x509.ParsePKCS1PrivateKey(private) if err != nil { - return nil + return nil, err } return &RSAPrivateKey{ - RSAPublicKey: public, - privateKey: privateKey{private: private}, - Signer: rsaPrivKey, - } -} - -// NewRSAx509PrivateKey initialized a new RSA private key -func NewRSAx509PrivateKey(public RSAx509PublicKey, private []byte) *RSAx509PrivateKey { - rsaPrivKey, err := x509.ParsePKCS1PrivateKey(private) - if err != nil { - return nil - } - return &RSAx509PrivateKey{ - RSAx509PublicKey: public, - privateKey: privateKey{private: private}, - Signer: rsaPrivKey, - } + PublicKey: public, + privateKey: privateKey{private: private}, + signer: signer{signer: rsaPrivKey}, + }, nil } // NewED25519PrivateKey initialized a new ED25519 private key -func NewED25519PrivateKey(public ED25519PublicKey, private []byte) *ED25519PrivateKey { +func NewED25519PrivateKey(public ED25519PublicKey, private []byte) (*ED25519PrivateKey, error) { return &ED25519PrivateKey{ ED25519PublicKey: public, privateKey: privateKey{private: private}, - } + }, nil } // Private return the serialized private bytes of the key @@ -436,6 +410,22 @@ func (k privateKey) Private() []byte { return k.private } +// CryptoSigner returns the underlying crypto.Signer for use cases where we need the default +// signature or public key functionality (like when we generate certificates) +func (s signer) CryptoSigner() crypto.Signer { + return s.signer +} + +// CryptoSigner returns the ED25519PrivateKey which already implements crypto.Signer +func (k ED25519PrivateKey) CryptoSigner() crypto.Signer { + return nil +} + +// CryptoSigner returns the UnknownPrivateKey which already implements crypto.Signer +func (k UnknownPrivateKey) CryptoSigner() crypto.Signer { + return nil +} + type ecdsaSig struct { R *big.Int S *big.Int @@ -443,17 +433,21 @@ type ecdsaSig struct { // Sign creates an ecdsa signature func (k ECDSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { - ecdsaPrivKey, ok := k.Signer.(*ecdsa.PrivateKey) + ecdsaPrivKey, ok := k.CryptoSigner().(*ecdsa.PrivateKey) if !ok { return nil, errors.New("Signer was based on the wrong key type") } hashed := sha256.Sum256(msg) - sigASN1, err := k.Signer.Sign(rand, hashed[:], opts) + sigASN1, err := ecdsaPrivKey.Sign(rand, hashed[:], opts) if err != nil { return nil, err } + sig := ecdsaSig{} _, err = asn1.Unmarshal(sigASN1, &sig) + if err != nil { + return nil, err + } rBytes, sBytes := sig.R.Bytes(), sig.S.Bytes() octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3 @@ -463,53 +457,25 @@ func (k ECDSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts rBuf = append(rBuf, rBytes...) sBuf = append(sBuf, sBytes...) - - return append(rBuf, sBuf...), nil -} - -// Sign creates an ecdsa signature -func (k ECDSAx509PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { - ecdsaPrivKey, ok := k.Signer.(*ecdsa.PrivateKey) - if !ok { - return nil, errors.New("Signer was based on the wrong key type") - } - hashed := sha256.Sum256(msg) - sigASN1, err := k.Signer.Sign(rand, hashed[:], opts) - if err != nil { - return nil, err - } - sig := ecdsaSig{} - _, err = asn1.Unmarshal(sigASN1, &sig) - rBytes, sBytes := sig.R.Bytes(), sig.S.Bytes() - octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3 - - // MUST include leading zeros in the output - rBuf := make([]byte, octetLength-len(rBytes), octetLength) - sBuf := make([]byte, octetLength-len(sBytes), octetLength) - - rBuf = append(rBuf, rBytes...) - sBuf = append(sBuf, sBytes...) - return append(rBuf, sBuf...), nil } // Sign creates an rsa signature func (k RSAPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { hashed := sha256.Sum256(msg) - return k.Signer.Sign(rand, hashed[:], opts) -} - -// Sign creates an rsa signature -func (k RSAx509PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { - hashed := sha256.Sum256(msg) - return k.Signer.Sign(rand, hashed[:], opts) - + if opts == nil { + opts = &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + Hash: crypto.SHA256, + } + } + return k.CryptoSigner().Sign(rand, hashed[:], opts) } // Sign creates an ed25519 signature func (k ED25519PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) (signature []byte, err error) { priv := [ed25519.PrivateKeySize]byte{} - copy(priv[:], k.private) + copy(priv[:], k.private[ed25519.PublicKeySize:]) return ed25519.Sign(&priv, msg)[:], nil } diff --git a/tuf/signed/ed25519.go b/tuf/signed/ed25519.go index cbc1e64bd1..6db53baa98 100644 --- a/tuf/signed/ed25519.go +++ b/tuf/signed/ed25519.go @@ -60,7 +60,11 @@ func (e *Ed25519) Create(role, algorithm string) (data.PublicKey, error) { return nil, err } public := data.NewED25519PublicKey(pub[:]) - private := data.NewED25519PrivateKey(*public, priv[:]) + private, err := data.NewED25519PrivateKey(*public, priv[:]) + if err != nil { + return nil, err + } + e.addKey(private) return public, nil } diff --git a/tuf/signed/verifiers_test.go b/tuf/signed/verifiers_test.go index 7607a7f673..dc7d093e73 100644 --- a/tuf/signed/verifiers_test.go +++ b/tuf/signed/verifiers_test.go @@ -307,7 +307,8 @@ func TestECDSAVerifierOtherCurves(t *testing.T) { assert.NoError(t, err, "failed to marshal private key") testECDSAPubKey := data.NewECDSAPublicKey(ecdsaPubBytes) - testECDSAKey := data.NewECDSAPrivateKey(*testECDSAPubKey, ecdsaPrivKeyBytes) + testECDSAKey, err := data.NewECDSAPrivateKey(testECDSAPubKey, ecdsaPrivKeyBytes) + assert.NoError(t, err, "failed to read private key") // Sign some data using ECDSA message := []byte("test data for signing")