From 55fd4c47a27f1fe068dbc422a5b3bdc8a2a170f4 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Mon, 21 Nov 2016 08:44:13 +0100 Subject: [PATCH] BCCSP Generalized Key Import This change-set generalizes the BCCSP key import function. It now takes in input an interface{} and allows direct import of golang objects like keys and certificates. This change-set comes in the context of: https://jira.hyperledger.org/browse/FAB-354 Change-Id: I48a52b7d6aa1426922efa23661167c602da769f6 Signed-off-by: Angelo De Caro --- core/crypto/bccsp/bccsp.go | 2 +- core/crypto/bccsp/bccsp_opts.go | 24 ----------- core/crypto/bccsp/sw/impl.go | 67 ++++++++++++++++++++----------- core/crypto/bccsp/sw/impl_test.go | 22 +++++----- 4 files changed, 54 insertions(+), 61 deletions(-) diff --git a/core/crypto/bccsp/bccsp.go b/core/crypto/bccsp/bccsp.go index 74486057cf3..e7fb7e2cf28 100644 --- a/core/crypto/bccsp/bccsp.go +++ b/core/crypto/bccsp/bccsp.go @@ -110,7 +110,7 @@ type BCCSP interface { // KeyImport imports a key from its raw representation using opts. // The opts argument should be appropriate for the primitive used. - KeyImport(raw []byte, opts KeyImportOpts) (k Key, err error) + KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error) // GetKey returns the key this CSP associates to // the Subject Key Identifier ski. diff --git a/core/crypto/bccsp/bccsp_opts.go b/core/crypto/bccsp/bccsp_opts.go index 3033931dc06..77427c746fc 100644 --- a/core/crypto/bccsp/bccsp_opts.go +++ b/core/crypto/bccsp/bccsp_opts.go @@ -16,12 +16,6 @@ limitations under the License. package bccsp -import ( - "crypto/ecdsa" - "crypto/rsa" - "crypto/x509" -) - const ( // ECDSA Elliptic Curve Digital Signature Algorithm (key gen, import, sign, verify), // at default security level (see primitives package). @@ -105,7 +99,6 @@ func (opts *ECDSAPrivateKeyImportOpts) Ephemeral() bool { // ECDSAGoPublicKeyImportOpts contains options for ECDSA key importation from ecdsa.PublicKey type ECDSAGoPublicKeyImportOpts struct { Temporary bool - PK *ecdsa.PublicKey } // Algorithm returns an identifier for the algorithm to be used @@ -120,11 +113,6 @@ func (opts *ECDSAGoPublicKeyImportOpts) Ephemeral() bool { return opts.Temporary } -// PublicKey returns the ecdsa.PublicKey to be imported. -func (opts *ECDSAGoPublicKeyImportOpts) PublicKey() *ecdsa.PublicKey { - return opts.PK -} - // ECDSAReRandKeyOpts contains options for ECDSA key re-randomization. type ECDSAReRandKeyOpts struct { Temporary bool @@ -280,7 +268,6 @@ func (opts *RSAKeyGenOpts) Ephemeral() bool { // ECDSAGoPublicKeyImportOpts contains options for RSA key importation from rsa.PublicKey type RSAGoPublicKeyImportOpts struct { Temporary bool - PK *rsa.PublicKey } // Algorithm returns an identifier for the algorithm to be used @@ -295,15 +282,9 @@ func (opts *RSAGoPublicKeyImportOpts) Ephemeral() bool { return opts.Temporary } -// PublicKey returns the ecdsa.PublicKey to be imported. -func (opts *RSAGoPublicKeyImportOpts) PublicKey() *rsa.PublicKey { - return opts.PK -} - // X509PublicKeyImportOpts contains options for importing public keys from an x509 certificate type X509PublicKeyImportOpts struct { Temporary bool - Cert *x509.Certificate } // Algorithm returns an identifier for the algorithm to be used @@ -317,8 +298,3 @@ func (opts *X509PublicKeyImportOpts) Algorithm() string { func (opts *X509PublicKeyImportOpts) Ephemeral() bool { return opts.Temporary } - -// PublicKey returns the ecdsa.PublicKey to be imported. -func (opts *X509PublicKeyImportOpts) Certificate() *x509.Certificate { - return opts.Cert -} diff --git a/core/crypto/bccsp/sw/impl.go b/core/crypto/bccsp/sw/impl.go index 1bdd4a428ae..3654eb828f3 100644 --- a/core/crypto/bccsp/sw/impl.go +++ b/core/crypto/bccsp/sw/impl.go @@ -28,6 +28,8 @@ import ( "hash" + "crypto/x509" + "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/primitives" "github.com/hyperledger/fabric/core/crypto/utils" @@ -256,8 +258,12 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e // KeyImport imports a key from its raw representation using opts. // The opts argument should be appropriate for the primitive used. -func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) { +func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) { // Validate arguments + if raw == nil { + return nil, errors.New("Invalid raw. Cannot be nil") + } + if opts == nil { return nil, errors.New("Invalid Opts parameter. It must not be nil.") } @@ -265,12 +271,16 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e switch opts.(type) { case *bccsp.AES256ImportKeyOpts: + aesRaw, ok := raw.([]byte) + if !ok { + return nil, errors.New("[AES256ImportKeyOpts] Invalid raw material. Expected byte array.") + } - if len(raw) != 32 { - return nil, fmt.Errorf("[AES256ImportKeyOpts] Invalid Key Length [%d]. Must be 32 bytes", len(raw)) + if len(aesRaw) != 32 { + return nil, fmt.Errorf("[AES256ImportKeyOpts] Invalid Key Length [%d]. Must be 32 bytes", len(aesRaw)) } - aesK := &aesPrivateKey{utils.Clone(raw), false} + aesK := &aesPrivateKey{utils.Clone(aesRaw), false} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { @@ -284,12 +294,16 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return aesK, nil case *bccsp.HMACImportKeyOpts: + aesRaw, ok := raw.([]byte) + if !ok { + return nil, errors.New("[HMACImportKeyOpts] Invalid raw material. Expected byte array.") + } - if len(raw) == 0 { + if len(aesRaw) == 0 { return nil, errors.New("[HMACImportKeyOpts] Invalid raw. It must not be nil.") } - aesK := &aesPrivateKey{utils.Clone(raw), false} + aesK := &aesPrivateKey{utils.Clone(aesRaw), false} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { @@ -303,12 +317,16 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return aesK, nil case *bccsp.ECDSAPKIXPublicKeyImportOpts: + der, ok := raw.([]byte) + if !ok { + return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw material. Expected byte array.") + } - if len(raw) == 0 { + if len(der) == 0 { return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw. It must not be nil.") } - lowLevelKey, err := primitives.DERToPublicKey(raw) + lowLevelKey, err := primitives.DERToPublicKey(der) if err != nil { return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err) } @@ -332,12 +350,16 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return k, nil case *bccsp.ECDSAPrivateKeyImportOpts: + der, ok := raw.([]byte) + if !ok { + return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw material. Expected byte array.") + } - if len(raw) == 0 { + if len(der) == 0 { return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw. It must not be nil.") } - lowLevelKey, err := primitives.DERToPrivateKey(raw) + lowLevelKey, err := primitives.DERToPrivateKey(der) if err != nil { return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err) } @@ -361,10 +383,9 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return k, nil case *bccsp.ECDSAGoPublicKeyImportOpts: - - lowLevelKey := opts.(*bccsp.ECDSAGoPublicKeyImportOpts).PublicKey() - if lowLevelKey == nil { - return nil, errors.New("Invalid Opts. ECDSA Public key cannot be nil") + lowLevelKey, ok := raw.(*ecdsa.PublicKey) + if !ok { + return nil, errors.New("[ECDSAGoPublicKeyImportOpts] Invalid raw material. Expected *ecdsa.PublicKey.") } k = &ecdsaPublicKey{lowLevelKey} @@ -381,10 +402,9 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return k, nil case *bccsp.RSAGoPublicKeyImportOpts: - - lowLevelKey := opts.(*bccsp.RSAGoPublicKeyImportOpts).PublicKey() - if lowLevelKey == nil { - return nil, errors.New("Invalid Opts. ECDSA Public key cannot be nil") + lowLevelKey, ok := raw.(*rsa.PublicKey) + if !ok { + return nil, errors.New("[RSAGoPublicKeyImportOpts] Invalid raw material. Expected *rsa.PublicKey.") } k = &rsaPublicKey{lowLevelKey} @@ -401,19 +421,18 @@ func (csp *impl) KeyImport(raw []byte, opts bccsp.KeyImportOpts) (k bccsp.Key, e return k, nil case *bccsp.X509PublicKeyImportOpts: - - x509Cert := opts.(*bccsp.X509PublicKeyImportOpts).Certificate() - if x509Cert == nil { - return nil, errors.New("Invalid Opts. X509 certificate cannot be nil") + x509Cert, ok := raw.(*x509.Certificate) + if !ok { + return nil, errors.New("[X509PublicKeyImportOpts] Invalid raw material. Expected *x509.Certificate.") } pk := x509Cert.PublicKey switch pk.(type) { case *ecdsa.PublicKey: - return csp.KeyImport(nil, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral(), PK: pk.(*ecdsa.PublicKey)}) + return csp.KeyImport(pk, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()}) case *rsa.PublicKey: - return csp.KeyImport(nil, &bccsp.RSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral(), PK: pk.(*rsa.PublicKey)}) + return csp.KeyImport(pk, &bccsp.RSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()}) default: return nil, errors.New("Certificate public key type not recognized. Supported keys: [ECDSA, RSA]") } diff --git a/core/crypto/bccsp/sw/impl_test.go b/core/crypto/bccsp/sw/impl_test.go index 58d285865f9..ea0dcc52cf8 100644 --- a/core/crypto/bccsp/sw/impl_test.go +++ b/core/crypto/bccsp/sw/impl_test.go @@ -23,8 +23,6 @@ import ( "crypto" "crypto/rsa" - "crypto/ecdsa" - "crypto/rand" "crypto/x509" "crypto/x509/pkix" @@ -387,7 +385,7 @@ func TestECDSAKeyImportFromECDSAPublicKey(t *testing.T) { } // Import the ecdsa.PublicKey - pk2, err := csp.KeyImport(pkRaw, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: true, PK: pub.(*ecdsa.PublicKey)}) + pk2, err := csp.KeyImport(pub, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: true}) if err != nil { t.Fatalf("Failed importing ECDSA public key [%s]", err) } @@ -543,8 +541,8 @@ func TestKeyImportFromX509ECDSAPublicKey(t *testing.T) { }, } - signer := &signer.CryptoSigner{} - err = signer.Init(csp, k) + cryptoSigner := &signer.CryptoSigner{} + err = cryptoSigner.Init(csp, k) if err != nil { t.Fatalf("Failed initializing CyrptoSigner [%s]", err) } @@ -565,7 +563,7 @@ func TestKeyImportFromX509ECDSAPublicKey(t *testing.T) { t.Fatalf("Failed converting raw to ECDSA.PublicKey [%s]", err) } - certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, signer) + certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, cryptoSigner) if err != nil { t.Fatalf("Failed generating self-signed certificate [%s]", err) } @@ -576,7 +574,7 @@ func TestKeyImportFromX509ECDSAPublicKey(t *testing.T) { } // Import the certificate's public key - pk2, err := csp.KeyImport(nil, &bccsp.X509PublicKeyImportOpts{Temporary: true, Cert: cert}) + pk2, err := csp.KeyImport(cert, &bccsp.X509PublicKeyImportOpts{Temporary: true}) if err != nil { t.Fatalf("Failed importing ECDSA public key [%s]", err) @@ -1086,7 +1084,7 @@ func TestRSAKeyImportFromRSAPublicKey(t *testing.T) { } // Import the RSA.PublicKey - pk2, err := csp.KeyImport(pkRaw, &bccsp.RSAGoPublicKeyImportOpts{Temporary: true, PK: pub.(*rsa.PublicKey)}) + pk2, err := csp.KeyImport(pub, &bccsp.RSAGoPublicKeyImportOpts{Temporary: true}) if err != nil { t.Fatalf("Failed importing RSA public key [%s]", err) } @@ -1182,8 +1180,8 @@ func TestKeyImportFromX509RSAPublicKey(t *testing.T) { }, } - signer := &signer.CryptoSigner{} - err = signer.Init(csp, k) + cryptoSigner := &signer.CryptoSigner{} + err = cryptoSigner.Init(csp, k) if err != nil { t.Fatalf("Failed initializing CyrptoSigner [%s]", err) } @@ -1204,7 +1202,7 @@ func TestKeyImportFromX509RSAPublicKey(t *testing.T) { t.Fatalf("Failed converting raw to RSA.PublicKey [%s]", err) } - certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, signer) + certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, cryptoSigner) if err != nil { t.Fatalf("Failed generating self-signed certificate [%s]", err) } @@ -1215,7 +1213,7 @@ func TestKeyImportFromX509RSAPublicKey(t *testing.T) { } // Import the certificate's public key - pk2, err := csp.KeyImport(nil, &bccsp.X509PublicKeyImportOpts{Temporary: true, Cert: cert}) + pk2, err := csp.KeyImport(cert, &bccsp.X509PublicKeyImportOpts{Temporary: true}) if err != nil { t.Fatalf("Failed importing RSA public key [%s]", err)