Skip to content

Commit

Permalink
BCCSP Generalized Key Import
Browse files Browse the repository at this point in the history
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 <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 21, 2016
1 parent 9d3abd1 commit 55fd4c4
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 61 deletions.
2 changes: 1 addition & 1 deletion core/crypto/bccsp/bccsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
24 changes: 0 additions & 24 deletions core/crypto/bccsp/bccsp_opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
67 changes: 43 additions & 24 deletions core/crypto/bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -256,21 +258,29 @@ 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.")
}

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() {
Expand All @@ -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() {
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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}
Expand All @@ -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}
Expand All @@ -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]")
}
Expand Down
22 changes: 10 additions & 12 deletions core/crypto/bccsp/sw/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"crypto"
"crypto/rsa"

"crypto/ecdsa"

"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
Expand Down

0 comments on commit 55fd4c4

Please sign in to comment.