diff --git a/core/crypto/bccsp/factory/sw_factory.go b/core/crypto/bccsp/factory/sw_factory.go index 9b3cb3731e1..7855b2174d5 100644 --- a/core/crypto/bccsp/factory/sw_factory.go +++ b/core/crypto/bccsp/factory/sw_factory.go @@ -54,13 +54,13 @@ func (f *SWFactory) Get(opts Opts) (bccsp.BCCSP, error) { if !opts.Ephemeral() { f.initOnce.Do(func() { - f.bccsp, f.err = sw.New() + f.bccsp, f.err = sw.NewDefaultSecurityLevel() return }) return f.bccsp, f.err } - return sw.New() + return sw.NewDefaultSecurityLevel() } // SwOpts contains options for the SWFactory diff --git a/core/crypto/bccsp/signer/signer_test.go b/core/crypto/bccsp/signer/signer_test.go index c57cc9fb26f..0424056a245 100644 --- a/core/crypto/bccsp/signer/signer_test.go +++ b/core/crypto/bccsp/signer/signer_test.go @@ -22,7 +22,6 @@ import ( "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/bccsp/sw" - "github.com/hyperledger/fabric/core/crypto/primitives" "github.com/spf13/viper" ) @@ -32,11 +31,10 @@ var ( func getBCCSP(t *testing.T) bccsp.BCCSP { if swBCCSPInstance == nil { - primitives.InitSecurityLevel("SHA2", 256) viper.Set("security.bccsp.default.keyStorePath", os.TempDir()) var err error - swBCCSPInstance, err = sw.New() + swBCCSPInstance, err = sw.NewDefaultSecurityLevel() if err != nil { t.Fatalf("Failed initializing key store [%s]", err) } @@ -95,12 +93,18 @@ func TestSign(t *testing.T) { } msg := []byte("Hello World") - signature, err := signer.Sign(rand.Reader, primitives.Hash(msg), nil) + + digest, err := csp.Hash(msg, nil) + if err != nil { + t.Fatalf("Failed generating digest [%s]", err) + } + + signature, err := signer.Sign(rand.Reader, digest, nil) if err != nil { t.Fatalf("Failed generating ECDSA signature [%s]", err) } - valid, err := csp.Verify(k, signature, primitives.Hash(msg), nil) + valid, err := csp.Verify(k, signature, digest, nil) if err != nil { t.Fatalf("Failed verifying ECDSA signature [%s]", err) } diff --git a/core/crypto/bccsp/sw/aeskey.go b/core/crypto/bccsp/sw/aeskey.go index c2f51d41e22..11d18ca22c5 100644 --- a/core/crypto/bccsp/sw/aeskey.go +++ b/core/crypto/bccsp/sw/aeskey.go @@ -18,8 +18,9 @@ package sw import ( "errors" + "crypto/sha256" + "github.com/hyperledger/fabric/core/crypto/bccsp" - "github.com/hyperledger/fabric/core/crypto/primitives" ) type aesPrivateKey struct { @@ -39,7 +40,9 @@ func (k *aesPrivateKey) Bytes() (raw []byte, err error) { // SKI returns the subject key identifier of this key. func (k *aesPrivateKey) SKI() (ski []byte) { - return primitives.Hash(k.k) + hash := sha256.New() + hash.Write(k.k) + return hash.Sum(nil) } // Symmetric returns true if this key is a symmetric key, diff --git a/core/crypto/bccsp/sw/conf.go b/core/crypto/bccsp/sw/conf.go index 703b8c55cf1..d044a398b8e 100644 --- a/core/crypto/bccsp/sw/conf.go +++ b/core/crypto/bccsp/sw/conf.go @@ -21,16 +21,35 @@ import ( "os" + "crypto/elliptic" + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" + "github.com/spf13/viper" + "golang.org/x/crypto/sha3" ) type config struct { - keystorePath string + keystorePath string + securityLevel int + hashFamily string configurationPathProperty string + ellipticCurve elliptic.Curve + hashFunction func() hash.Hash + aesBitLength int + rsaBitLength int } -func (conf *config) init() error { +func (conf *config) init(securityLevel int, hashFamily string) error { + // Set security level + err := conf.setSecurityLevel(securityLevel, hashFamily) + if err != nil { + return fmt.Errorf("Failed initliazing security level [%s]", err) + } + // Set ks path conf.configurationPathProperty = "security.bccsp.default.keyStorePath" // Check mandatory fields @@ -45,12 +64,59 @@ func (conf *config) init() error { // Set configuration path rootPath = filepath.Join(rootPath, "crypto") - // Set ks path conf.keystorePath = filepath.Join(rootPath, "ks") return nil } +func (conf *config) setSecurityLevel(securityLevel int, hashFamily string) (err error) { + switch hashFamily { + case "SHA2": + err = conf.setSecurityLevelSHA2(securityLevel) + case "SHA3": + err = conf.setSecurityLevelSHA3(securityLevel) + default: + err = fmt.Errorf("Hash Family not supported [%s]", hashFamily) + } + return +} + +func (conf *config) setSecurityLevelSHA2(level int) (err error) { + switch level { + case 256: + conf.ellipticCurve = elliptic.P256() + conf.hashFunction = sha256.New + conf.rsaBitLength = 2048 + conf.aesBitLength = 32 + case 384: + conf.ellipticCurve = elliptic.P384() + conf.hashFunction = sha512.New384 + conf.rsaBitLength = 3072 + conf.aesBitLength = 32 + default: + err = fmt.Errorf("Security level not supported [%d]", level) + } + return +} + +func (conf *config) setSecurityLevelSHA3(level int) (err error) { + switch level { + case 256: + conf.ellipticCurve = elliptic.P256() + conf.hashFunction = sha3.New256 + conf.rsaBitLength = 2048 + conf.aesBitLength = 32 + case 384: + conf.ellipticCurve = elliptic.P384() + conf.hashFunction = sha3.New384 + conf.rsaBitLength = 3072 + conf.aesBitLength = 32 + default: + err = fmt.Errorf("Security level not supported [%d]", level) + } + return +} + func (conf *config) checkProperty(property string) error { res := viper.GetString(property) if res == "" { diff --git a/core/crypto/bccsp/sw/ecdsakey.go b/core/crypto/bccsp/sw/ecdsakey.go index 9e3fa40b507..8f925b89d76 100644 --- a/core/crypto/bccsp/sw/ecdsakey.go +++ b/core/crypto/bccsp/sw/ecdsakey.go @@ -20,6 +20,8 @@ import ( "crypto/x509" "fmt" + "crypto/sha256" + "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/primitives" ) @@ -44,7 +46,9 @@ func (k *ecdsaPrivateKey) SKI() (ski []byte) { raw, _ := primitives.PrivateKeyToDER(k.k) // TODO: Error should not be thrown. Anyway, move the marshalling at initialization. - return primitives.Hash(raw) + hash := sha256.New() + hash.Write(raw) + return hash.Sum(nil) } // Symmetric returns true if this key is a symmetric key, @@ -89,7 +93,9 @@ func (k *ecdsaPublicKey) SKI() (ski []byte) { raw, _ := primitives.PublicKeyToPEM(k.k, nil) // TODO: Error should not be thrown. Anyway, move the marshalling at initialization. - return primitives.Hash(raw) + hash := sha256.New() + hash.Write(raw) + return hash.Sum(nil) } // Symmetric returns true if this key is a symmetric key, diff --git a/core/crypto/bccsp/sw/impl.go b/core/crypto/bccsp/sw/impl.go index 3654eb828f3..0aaafb34e94 100644 --- a/core/crypto/bccsp/sw/impl.go +++ b/core/crypto/bccsp/sw/impl.go @@ -30,6 +30,8 @@ import ( "crypto/x509" + "crypto/hmac" + "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/primitives" "github.com/hyperledger/fabric/core/crypto/utils" @@ -40,10 +42,17 @@ var ( logger = logging.MustGetLogger("SW_BCCSP") ) -// New returns a new instance of the software-based BCCSP. -func New() (bccsp.BCCSP, error) { +// NewDefaultSecurityLevel returns a new instance of the software-based BCCSP +// at security level 256 and hash family SHA2 +func NewDefaultSecurityLevel() (bccsp.BCCSP, error) { + return New(256, "SHA2") +} + +// New returns a new instance of the software-based BCCSP +// set at the passed security level and hash family. +func New(securityLevel int, hashFamily string) (bccsp.BCCSP, error) { conf := &config{} - err := conf.init() + err := conf.init(securityLevel, hashFamily) if err != nil { return nil, fmt.Errorf("Failed initializing configuration [%s]", err) } @@ -52,14 +61,16 @@ func New() (bccsp.BCCSP, error) { if err := ks.init(nil, conf); err != nil { return nil, fmt.Errorf("Failed initializing key store [%s]", err) } - return &impl{ks}, nil + return &impl{conf, ks}, nil } // SoftwareBasedBCCSP is the software-based implementation of the BCCSP. -// It is based on code used in the primitives package. +// It uses util code in the primitives package but does not depend on the +// initialization of that package. // It can be configured via viper. type impl struct { - ks *keyStore + conf *config + ks *keyStore } // KeyGen generates a key using opts. @@ -72,7 +83,7 @@ func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) { // Parse algorithm switch opts.Algorithm() { case bccsp.ECDSA: - lowLevelKey, err := primitives.NewECDSAKey() + lowLevelKey, err := ecdsa.GenerateKey(csp.conf.ellipticCurve, rand.Reader) if err != nil { return nil, fmt.Errorf("Failed generating ECDSA key [%s]", err) } @@ -90,7 +101,7 @@ func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) { return k, nil case bccsp.AES: - lowLevelKey, err := primitives.GenAESKey() + lowLevelKey, err := primitives.GetRandomBytes(csp.conf.aesBitLength) if err != nil { return nil, fmt.Errorf("Failed generating AES key [%s]", err) @@ -109,7 +120,7 @@ func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) { return k, nil case bccsp.RSA: - lowLevelKey, err := primitives.NewRSAKey() + lowLevelKey, err := rsa.GenerateKey(rand.Reader, csp.conf.rsaBitLength) if err != nil { return nil, fmt.Errorf("Failed generating RSA (2048) key [%s]", err) @@ -216,7 +227,9 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e case *bccsp.HMACTruncated256AESDeriveKeyOpts: hmacOpts := opts.(*bccsp.HMACTruncated256AESDeriveKeyOpts) - hmacedKey := &aesPrivateKey{primitives.HMACAESTruncated(aesK.k, hmacOpts.Argument()), false} + mac := hmac.New(csp.conf.hashFunction, aesK.k) + mac.Write(hmacOpts.Argument()) + hmacedKey := &aesPrivateKey{mac.Sum(nil)[:csp.conf.aesBitLength], false} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { @@ -233,7 +246,9 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e hmacOpts := opts.(*bccsp.HMACDeriveKeyOpts) - hmacedKey := &aesPrivateKey{primitives.HMAC(aesK.k, hmacOpts.Argument()), true} + mac := hmac.New(csp.conf.hashFunction, aesK.k) + mac.Write(hmacOpts.Argument()) + hmacedKey := &aesPrivateKey{mac.Sum(nil), true} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { @@ -484,12 +499,16 @@ func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error) { // Hash hashes messages msg using options opts. func (csp *impl) Hash(msg []byte, opts bccsp.HashOpts) (hash []byte, err error) { if opts == nil { - return primitives.Hash(msg), nil + hash := csp.conf.hashFunction() + hash.Write(msg) + return hash.Sum(nil), nil } switch opts.Algorithm() { case bccsp.DefaultHash, bccsp.SHA: - return primitives.Hash(msg), nil + hash := csp.conf.hashFunction() + hash.Write(msg) + return hash.Sum(nil), nil default: return nil, fmt.Errorf("Algorithm not recognized [%s]", opts.Algorithm()) } @@ -499,12 +518,12 @@ func (csp *impl) Hash(msg []byte, opts bccsp.HashOpts) (hash []byte, err error) // If opts is nil then the default hash function is returned. func (csp *impl) GetHash(opts bccsp.HashOpts) (h hash.Hash, err error) { if opts == nil { - return primitives.NewHash(), nil + return csp.conf.hashFunction(), nil } switch opts.Algorithm() { case bccsp.SHA, bccsp.DefaultHash: - return primitives.NewHash(), nil + return csp.conf.hashFunction(), nil default: return nil, fmt.Errorf("Algorithm not recognized [%s]", opts.Algorithm()) } diff --git a/core/crypto/bccsp/sw/impl_test.go b/core/crypto/bccsp/sw/impl_test.go index ea0dcc52cf8..02b000baf2f 100644 --- a/core/crypto/bccsp/sw/impl_test.go +++ b/core/crypto/bccsp/sw/impl_test.go @@ -31,6 +31,10 @@ import ( "net" "time" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" + "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/bccsp/signer" "github.com/hyperledger/fabric/core/crypto/primitives" @@ -43,11 +47,10 @@ var ( func getBCCSP(t *testing.T) bccsp.BCCSP { if swBCCSPInstance == nil { - primitives.InitSecurityLevel("SHA2", 256) viper.Set("security.bccsp.default.keyStorePath", os.TempDir()) var err error - swBCCSPInstance, err = New() + swBCCSPInstance, err = NewDefaultSecurityLevel() if err != nil { t.Fatalf("Failed initializing key store [%s]", err) } @@ -418,8 +421,8 @@ func TestECDSAKeyImportFromECDSAPublicKey(t *testing.T) { func TestECDSAKeyImportFromECDSAPrivateKey(t *testing.T) { csp := getBCCSP(t) - // Generate an ECDSA key - key, err := primitives.NewECDSAKey() + // Generate an ECDSA key, default is P256 + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("Failed generating ECDSA key [%s]", err) } @@ -752,7 +755,7 @@ func TestHMACKeyDerivOverAES256Key(t *testing.T) { func TestAES256KeyImport(t *testing.T) { csp := getBCCSP(t) - raw, err := primitives.GenAESKey() + raw, err := primitives.GetRandomBytes(32) if err != nil { t.Fatalf("Failed generating AES key [%s]", err) } @@ -855,7 +858,10 @@ func TestSHA(t *testing.T) { t.Fatalf("Failed computing SHA [%s]", err) } - h2 := primitives.Hash(b[:]) + // Default HASH is SHA2 256 + hash := sha256.New() + hash.Write(b) + h2 := hash.Sum(nil) if !bytes.Equal(h1, h2) { t.Fatalf("Discrempancy found in HASH result [%x], [%x]!=[%x]", b, h1, h2) diff --git a/core/crypto/bccsp/sw/raskey.go b/core/crypto/bccsp/sw/raskey.go index fbb569f418a..11e93aaf285 100644 --- a/core/crypto/bccsp/sw/raskey.go +++ b/core/crypto/bccsp/sw/raskey.go @@ -20,6 +20,8 @@ import ( "crypto/x509" "fmt" + "crypto/sha256" + "github.com/hyperledger/fabric/core/crypto/bccsp" "github.com/hyperledger/fabric/core/crypto/primitives" ) @@ -38,7 +40,9 @@ func (k *rsaPrivateKey) Bytes() (raw []byte, err error) { func (k *rsaPrivateKey) SKI() (ski []byte) { raw := x509.MarshalPKCS1PrivateKey(k.k) - return primitives.Hash(raw) + hash := sha256.New() + hash.Write(raw) + return hash.Sum(nil) } // Symmetric returns true if this key is a symmetric key, @@ -78,7 +82,9 @@ func (k *rsaPublicKey) SKI() (ski []byte) { raw, _ := primitives.PublicKeyToPEM(k.k, nil) // TODO: Error should not be thrown. Anyway, move the marshalling at initialization. - return primitives.Hash(raw) + hash := sha256.New() + hash.Write(raw) + return hash.Sum(nil) } // Symmetric returns true if this key is a symmetric key,