integreating with @cyli's improvements

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-10-29 19:31:55 -07:00
parent 7a24fbf32f
commit 06990fd5a1
8 changed files with 104 additions and 231 deletions

View File

@ -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)
}

View File

@ -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
}

View File

@ -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())

View File

@ -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

View File

@ -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) {

View File

@ -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
}

View File

@ -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
}

View File

@ -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")