Skip to content

Commit

Permalink
[FAB-2362] Customizable Hash at MSP
Browse files Browse the repository at this point in the history
This change-set does the following:
1. It allows the hash function to be used
to sign/verify and to compute the msp identity's identifier.
In order to do so, FabricMSPConfig message has
been enhanced to contain information about the
crypto algorithms to be used.
Currently, the configuration values are hardcoded.

Change-Id: I50c78fb907f48ebdf66e3833b595ff5cbfde5e9e
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Apr 23, 2017
1 parent 88ac3ba commit 446573e
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 44 deletions.
17 changes: 17 additions & 0 deletions bccsp/hashopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.

package bccsp

import "fmt"

// SHA256Opts contains options relating to SHA-256.
type SHA256Opts struct {
}
Expand Down Expand Up @@ -51,3 +53,18 @@ type SHA3_384Opts struct {
func (opts *SHA3_384Opts) Algorithm() string {
return SHA3_384
}

// GetHashOpt returns the HashOpts corresponding to the passed hash function
func GetHashOpt(hashFunction string) (HashOpts, error) {
switch hashFunction {
case SHA256:
return &SHA256Opts{}, nil
case SHA384:
return &SHA384Opts{}, nil
case SHA3_256:
return &SHA3_256Opts{}, nil
case SHA3_384:
return &SHA3_384Opts{}, nil
}
return nil, fmt.Errorf("hash function not recognized [%s]", hashFunction)
}
5 changes: 5 additions & 0 deletions bccsp/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ const (
// an error will be returned.
SHA = "SHA"

// SHA2 is an identifier for SHA2 hash family
SHA2 = "SHA2"
// SHA3 is an identifier for SHA3 hash family
SHA3 = "SHA3"

// SHA256
SHA256 = "SHA256"
// SHA384
Expand Down
11 changes: 10 additions & 1 deletion msp/configbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"encoding/pem"
"path/filepath"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/protos/msp"
)
Expand Down Expand Up @@ -161,12 +162,20 @@ func getMspConfig(dir string, bccspConfig *factory.FactoryOpts, ID string, sigid
intermediatecert, _ := getPemMaterialFromDir(intermediatecertsDir)
// intermediate certs are not mandatory

// Load FabricCryptoConfig
cryptoConfig := &msp.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
}

// Compose FabricMSPConfig
fmspconf := &msp.FabricMSPConfig{
Admins: admincert,
RootCerts: cacerts,
IntermediateCerts: intermediatecert,
SigningIdentity: sigid,
Name: ID}
Name: ID,
CryptoConfig: cryptoConfig}

fmpsjs, _ := proto.Marshal(fmspconf)

Expand Down
24 changes: 22 additions & 2 deletions msp/identities.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,12 @@ func (id *identity) Verify(msg []byte, sig []byte) error {
// mspLogger.Infof("Verifying signature")

// Compute Hash
digest, err := id.msp.bccsp.Hash(msg, &bccsp.SHA256Opts{})
hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily)
if err != nil {
return fmt.Errorf("Failed getting hash function options [%s]", err)
}

digest, err := id.msp.bccsp.Hash(msg, hashOpt)
if err != nil {
return fmt.Errorf("Failed computing digest [%s]", err)
}
Expand Down Expand Up @@ -167,6 +172,16 @@ func (id *identity) Serialize() ([]byte, error) {
return idBytes, nil
}

func (id *identity) getHashOpt(hashFamily string) (bccsp.HashOpts, error) {
switch hashFamily {
case bccsp.SHA2:
return bccsp.GetHashOpt(bccsp.SHA256)
case bccsp.SHA3:
return bccsp.GetHashOpt(bccsp.SHA3_256)
}
return nil, fmt.Errorf("hash famility not recognized [%s]", hashFamily)
}

type signingidentity struct {
// we embed everything from a base identity
identity
Expand All @@ -185,7 +200,12 @@ func (id *signingidentity) Sign(msg []byte) ([]byte, error) {
//mspLogger.Infof("Signing message")

// Compute Hash
digest, err := id.msp.bccsp.Hash(msg, &bccsp.SHA256Opts{})
hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily)
if err != nil {
return nil, fmt.Errorf("Failed getting hash function options [%s]", err)
}

digest, err := id.msp.bccsp.Hash(msg, hashOpt)
if err != nil {
return nil, fmt.Errorf("Failed computing digest [%s]", err)
}
Expand Down
45 changes: 41 additions & 4 deletions msp/mspimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ type bccspmsp struct {

// list of OUs
ouIdentifiers []*m.FabricOUIdentifier

// cryptoConfig contains
cryptoConfig *m.FabricCryptoConfig
}

// NewBccspMsp returns an MSP instance backed up by a BCCSP
Expand All @@ -82,7 +85,7 @@ func NewBccspMsp() (MSP, error) {

func (msp *bccspmsp) getIdentityFromConf(idBytes []byte) (Identity, bccsp.Key, error) {
if idBytes == nil {
return nil, nil, fmt.Errorf("getIdentityFromBytes error: nil idBytes")
return nil, nil, fmt.Errorf("getIdentityFromConf error: nil idBytes")
}

// Decode the pem bytes
Expand All @@ -105,7 +108,12 @@ func (msp *bccspmsp) getIdentityFromConf(idBytes []byte) (Identity, bccsp.Key, e
}

// Use the hash of the identity's certificate as id in the IdentityIdentifier
digest, err := factory.GetDefault().Hash(cert.Raw, &bccsp.SHA256Opts{})
hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction)
if err != nil {
return nil, nil, fmt.Errorf("getIdentityFromConf failed getting hash function options [%s]", err)
}

digest, err := msp.bccsp.Hash(cert.Raw, hashOpt)
if err != nil {
return nil, nil, fmt.Errorf("getIdentityFromConf failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err)
}
Expand Down Expand Up @@ -152,7 +160,12 @@ func (msp *bccspmsp) getSigningIdentityFromConf(sidInfo *m.SigningIdentityInfo)
}

// Use the hash of the identity's certificate as id in the IdentityIdentifier
digest, err := factory.GetDefault().Hash(idPub.(*identity).cert.Raw, &bccsp.SHA256Opts{})
hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction)
if err != nil {
return nil, fmt.Errorf("getIdentityFromBytes failed getting hash function options [%s]", err)
}

digest, err := msp.bccsp.Hash(idPub.(*identity).cert.Raw, hashOpt)
if err != nil {
return nil, fmt.Errorf("Failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err)
}
Expand Down Expand Up @@ -263,6 +276,25 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error {
msp.name = conf.Name
mspLogger.Debugf("Setting up MSP instance %s", msp.name)

// setup crypto config
msp.cryptoConfig = conf.CryptoConfig
if msp.cryptoConfig == nil {
// Move to defaults
msp.cryptoConfig = &m.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
}
mspLogger.Debugf("CryptoConfig was nil. Move to defaults.")
}
if msp.cryptoConfig.SignatureHashFamily == "" {
msp.cryptoConfig.SignatureHashFamily = bccsp.SHA2
mspLogger.Debugf("CryptoConfig.SignatureHashFamily was nil. Move to defaults.")
}
if msp.cryptoConfig.IdentityIdentifierHashFunction == "" {
msp.cryptoConfig.IdentityIdentifierHashFunction = bccsp.SHA256
mspLogger.Debugf("CryptoConfig.IdentityIdentifierHashFunction was nil. Move to defaults.")
}

// make and fill the set of admin certs (if present)
msp.admins = make([]Identity, len(conf.Admins))
for i, admCert := range conf.Admins {
Expand Down Expand Up @@ -526,7 +558,12 @@ func (msp *bccspmsp) deserializeIdentityInternal(serializedIdentity []byte) (Ide
// (yet) to encode the MSP ID into the x.509 body of a cert

// Use the hash of the identity's certificate as id in the IdentityIdentifier
digest, err := factory.GetDefault().Hash(cert.Raw, &bccsp.SHA256Opts{})
hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction)
if err != nil {
return nil, fmt.Errorf("Failed getting hash function options [%s]", err)
}

digest, err := msp.bccsp.Hash(cert.Raw, hashOpt)
if err != nil {
return nil, fmt.Errorf("Failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err)
}
Expand Down
9 changes: 8 additions & 1 deletion msp/mspwithintermediatecas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/protos/msp"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -90,11 +91,17 @@ func TestMSPWithIntermediateCAs(t *testing.T) {

sigid := &msp.SigningIdentityInfo{PublicSigner: []byte(signcert), PrivateSigner: keyinfo}

cryptoConfig := &msp.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
}

fmspconf := &msp.FabricMSPConfig{
RootCerts: [][]byte{[]byte(cacert)},
IntermediateCerts: [][]byte{[]byte(intermediatecert)},
SigningIdentity: sigid,
Name: "DEFAULT"}
Name: "DEFAULT",
CryptoConfig: cryptoConfig}

fmpsjs, _ := proto.Marshal(fmspconf)

Expand Down
9 changes: 8 additions & 1 deletion msp/revocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/protos/msp"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -83,11 +84,17 @@ func TestRevocation(t *testing.T) {

sigid := &msp.SigningIdentityInfo{PublicSigner: []byte(signcertrev), PrivateSigner: keyinfo}

cryptoConfig := &msp.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
}

fmspconf := &msp.FabricMSPConfig{
RootCerts: [][]byte{[]byte(cacertrev)},
RevocationList: [][]byte{[]byte(crlrev)},
SigningIdentity: sigid,
Name: "DEFAULT"}
Name: "DEFAULT",
CryptoConfig: cryptoConfig}

fmpsjs, _ := proto.Marshal(fmspconf)

Expand Down
1 change: 1 addition & 0 deletions protos/msp/identities.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 446573e

Please sign in to comment.