-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This change-set introduced a crypto.Signer implementation based on BCCSP. This is needed to be able to sign x509 certificates using the BCCSP. This change-set comes in the context of: https://jira.hyperledger.org/browse/FAB-354 Change-Id: I3adaf716bd513f6447f0d65c23ec71b06d5dcdda Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
- Loading branch information
Showing
2 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
Copyright IBM Corp. 2016 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
package signer | ||
|
||
import ( | ||
"crypto" | ||
"errors" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/hyperledger/fabric/core/crypto/bccsp" | ||
"github.com/hyperledger/fabric/core/crypto/primitives" | ||
) | ||
|
||
// CryptoSigner is the BCCSP-based implementation of a crypto.Signer | ||
type CryptoSigner struct { | ||
csp bccsp.BCCSP | ||
key bccsp.Key | ||
pk interface{} | ||
} | ||
|
||
// Init initializes this CryptoSigner. | ||
func (s *CryptoSigner) Init(csp bccsp.BCCSP, key bccsp.Key) error { | ||
// Validate arguments | ||
if csp == nil { | ||
return errors.New("Invalid BCCSP. Nil.") | ||
} | ||
if key == nil { | ||
return errors.New("Invalid Key. Nil.") | ||
} | ||
if key.Symmetric() { | ||
return errors.New("Invalid Key. Symmetric.") | ||
} | ||
|
||
// Marshall the bccsp public key as a crypto.PublicKey | ||
pub, err := key.PublicKey() | ||
if err != nil { | ||
return fmt.Errorf("Failed getting public key [%s]", err) | ||
} | ||
|
||
raw, err := pub.Bytes() | ||
if err != nil { | ||
return fmt.Errorf("Failed marshalling public key [%s]", err) | ||
} | ||
|
||
pk, err := primitives.DERToPublicKey(raw) | ||
if err != nil { | ||
return fmt.Errorf("Failed marshalling public key [%s]", err) | ||
} | ||
|
||
// Init fields | ||
s.csp = csp | ||
s.key = key | ||
s.pk = pk | ||
|
||
return nil | ||
|
||
} | ||
|
||
// Public returns the public key corresponding to the opaque, | ||
// private key. | ||
func (s *CryptoSigner) Public() crypto.PublicKey { | ||
return s.pk | ||
} | ||
|
||
// Sign signs digest with the private key, possibly using entropy from | ||
// rand. For an RSA key, the resulting signature should be either a | ||
// PKCS#1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA | ||
// key, it should be a DER-serialised, ASN.1 signature structure. | ||
// | ||
// Hash implements the SignerOpts interface and, in most cases, one can | ||
// simply pass in the hash function used as opts. Sign may also attempt | ||
// to type assert opts to other types in order to obtain algorithm | ||
// specific values. See the documentation in each package for details. | ||
// | ||
// Note that when a signature of a hash of a larger message is needed, | ||
// the caller is responsible for hashing the larger message and passing | ||
// the hash (as digest) and the hash function (as opts) to Sign. | ||
func (s *CryptoSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { | ||
if opts == nil { | ||
return s.csp.Sign(s.key, digest, nil) | ||
} | ||
|
||
so, ok := opts.(bccsp.SignerOpts) | ||
if !ok { | ||
return nil, errors.New("Invalid opts type. Expecting bccsp.SignerOpts") | ||
} | ||
|
||
return s.csp.Sign(s.key, digest, so) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
Copyright IBM Corp. 2016 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
package signer | ||
|
||
import ( | ||
"crypto/rand" | ||
"os" | ||
"testing" | ||
|
||
"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" | ||
) | ||
|
||
var ( | ||
swBCCSPInstance bccsp.BCCSP | ||
) | ||
|
||
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() | ||
if err != nil { | ||
t.Fatalf("Failed initializing key store [%s]", err) | ||
} | ||
} | ||
|
||
return swBCCSPInstance | ||
} | ||
|
||
func TestInit(t *testing.T) { | ||
csp := getBCCSP(t) | ||
|
||
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true}) | ||
if err != nil { | ||
t.Fatalf("Failed generating ECDSA key [%s]", err) | ||
} | ||
|
||
signer := &CryptoSigner{} | ||
err = signer.Init(csp, k) | ||
if err != nil { | ||
t.Fatalf("Failed initializing CryptoSigner [%s]", err) | ||
} | ||
} | ||
|
||
func TestPublic(t *testing.T) { | ||
csp := getBCCSP(t) | ||
|
||
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true}) | ||
if err != nil { | ||
t.Fatalf("Failed generating ECDSA key [%s]", err) | ||
} | ||
|
||
signer := &CryptoSigner{} | ||
err = signer.Init(csp, k) | ||
if err != nil { | ||
t.Fatalf("Failed initializing CryptoSigner [%s]", err) | ||
} | ||
|
||
pk := signer.Public() | ||
if pk == nil { | ||
t.Fatal("Failed getting PublicKey. Nil.") | ||
} | ||
} | ||
|
||
func TestSign(t *testing.T) { | ||
csp := getBCCSP(t) | ||
|
||
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true}) | ||
if err != nil { | ||
t.Fatalf("Failed generating ECDSA key [%s]", err) | ||
} | ||
|
||
signer := &CryptoSigner{} | ||
err = signer.Init(csp, k) | ||
if err != nil { | ||
t.Fatalf("Failed initializing CryptoSigner [%s]", err) | ||
} | ||
|
||
msg := []byte("Hello World") | ||
signature, err := signer.Sign(rand.Reader, primitives.Hash(msg), nil) | ||
if err != nil { | ||
t.Fatalf("Failed generating ECDSA signature [%s]", err) | ||
} | ||
|
||
valid, err := csp.Verify(k, signature, primitives.Hash(msg)) | ||
if err != nil { | ||
t.Fatalf("Failed verifying ECDSA signature [%s]", err) | ||
} | ||
if !valid { | ||
t.Fatal("Failed verifying ECDSA signature. Signature not valid.") | ||
} | ||
} |