Skip to content

Commit

Permalink
BCCSP hash.Hash support
Browse files Browse the repository at this point in the history
This change-set introduces support for hash.Hash at the BCCSP level.
The BCCSP will now return instances of hash.Hash to allow streaming hashing.
This change-set comes in the context of:
https://jira.hyperledger.org/browse/FAB-354

Change-Id: I78611c6ae90c58d7ac6c00d2c44eb8c3d5cf4d73
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 16, 2016
1 parent 742443e commit 50b4ae9
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
10 changes: 9 additions & 1 deletion core/crypto/bccsp/bccsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ limitations under the License.

package bccsp

import "crypto"
import (
"crypto"
"hash"
)

// Key represents a cryptographic key
type Key interface {
Expand Down Expand Up @@ -114,8 +117,13 @@ type BCCSP interface {
GetKey(ski []byte) (k Key, err error)

// Hash hashes messages msg using options opts.
// If opts is nil, the default hash function will be used.
Hash(msg []byte, opts HashOpts) (hash []byte, err error)

// GetHash returns and instance of hash.Hash using options opts.
// If opts is nil, the default hash function will be returned.
GetHash(opts HashOpts) (h hash.Hash, err error)

// Sign signs digest using key k.
// The opts argument should be appropriate for the algorithm used.
//
Expand Down
3 changes: 3 additions & 0 deletions core/crypto/bccsp/bccsp_opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const (

// X509Certificate Label for X509 certificate realted operation
X509Certificate = "X509Certificate"

// DefaultHash is the identifier for the default hash function (see primitives package)
DefaultHash = "DEFAULT_HASH"
)

// ECDSAKeyGenOpts contains options for ECDSA key generation.
Expand Down
21 changes: 19 additions & 2 deletions core/crypto/bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (

"crypto/rsa"

"hash"

"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 @@ -463,17 +465,32 @@ 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 nil, errors.New("Invalid Opts parameter. It must not be nil.")
return primitives.Hash(msg), nil
}

switch opts.Algorithm() {
case bccsp.SHA:
case bccsp.DefaultHash, bccsp.SHA:
return primitives.Hash(msg), nil
default:
return nil, fmt.Errorf("Algorithm not recognized [%s]", opts.Algorithm())
}
}

// GetHash returns and instance of hash.Hash using options opts.
// 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
}

switch opts.Algorithm() {
case bccsp.SHA, bccsp.DefaultHash:
return primitives.NewHash(), nil
default:
return nil, fmt.Errorf("Algorithm not recognized [%s]", opts.Algorithm())
}
}

// Sign signs digest using key k.
// The opts argument should be appropriate for the primitive used.
//
Expand Down
46 changes: 46 additions & 0 deletions core/crypto/bccsp/sw/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1245,3 +1245,49 @@ func TestKeyImportFromX509RSAPublicKey(t *testing.T) {
t.Fatal("Failed verifying RSA signature. Signature not valid.")
}
}

func TestGetHashAndHashCompatibility(t *testing.T) {
csp := getBCCSP(t)

msg1 := []byte("abcd")
msg2 := []byte("efgh")
msg := []byte("abcdefgh")

digest1, err := csp.Hash(msg, &bccsp.SHAOpts{})
if err != nil {
t.Fatalf("Failed computing HASH [%s]", err)
}

digest2, err := csp.Hash(msg, nil)
if err != nil {
t.Fatalf("Failed computing HASH [%s]", err)
}

if !bytes.Equal(digest1, digest2) {
t.Fatalf("Different hash computed. [%x][%x]", digest1, digest2)
}

h, err := csp.GetHash(nil)
if err != nil {
t.Fatalf("Failed getting hash.Hash instance [%s]", err)
}
h.Write(msg1)
h.Write(msg2)
digest3 := h.Sum(nil)

h2, err := csp.GetHash(&bccsp.SHAOpts{})
if err != nil {
t.Fatalf("Failed getting SHA hash.Hash instance [%s]", err)
}
h2.Write(msg1)
h2.Write(msg2)
digest4 := h2.Sum(nil)

if !bytes.Equal(digest3, digest4) {
t.Fatalf("Different hash computed. [%x][%x]", digest3, digest4)
}

if !bytes.Equal(digest1, digest3) {
t.Fatalf("Different hash computed. [%x][%x]", digest1, digest3)
}
}

0 comments on commit 50b4ae9

Please sign in to comment.