Skip to content

Commit

Permalink
Removing primitives package dependency from BCCSP
Browse files Browse the repository at this point in the history
This change-set removes the dependency on the initialization
of the primitives package from the software-based BCCSP.
This is the first step in removing dependency to the primitives package
from the fabric.
This change-set comes in the context of:
https://jira.hyperledger.org/browse/FAB-354

Change-Id: I062162400970bb8fa54aa953161ddcac538c2159
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 23, 2016
1 parent 21a4c6a commit 68aef4e
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 37 deletions.
4 changes: 2 additions & 2 deletions core/crypto/bccsp/factory/sw_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 9 additions & 5 deletions core/crypto/bccsp/signer/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
7 changes: 5 additions & 2 deletions core/crypto/bccsp/sw/aeskey.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand Down
72 changes: 69 additions & 3 deletions core/crypto/bccsp/sw/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 == "" {
Expand Down
10 changes: 8 additions & 2 deletions core/crypto/bccsp/sw/ecdsakey.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"crypto/x509"
"fmt"

"crypto/sha256"

"github.com/hyperledger/fabric/core/crypto/bccsp"
"github.com/hyperledger/fabric/core/crypto/primitives"
)
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
49 changes: 34 additions & 15 deletions core/crypto/bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
}
Expand All @@ -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.
Expand All @@ -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)
}
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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())
}
Expand All @@ -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())
}
Expand Down
18 changes: 12 additions & 6 deletions core/crypto/bccsp/sw/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 68aef4e

Please sign in to comment.