Skip to content

Commit 141831e

Browse files
committed
BCCSP-based crypto.Signer
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 <[email protected]>
1 parent 6ac4ed5 commit 141831e

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

core/crypto/bccsp/signer/signer.go

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package signer
17+
18+
import (
19+
"crypto"
20+
"errors"
21+
"fmt"
22+
"io"
23+
24+
"github.com/hyperledger/fabric/core/crypto/bccsp"
25+
"github.com/hyperledger/fabric/core/crypto/primitives"
26+
)
27+
28+
// CryptoSigner is the BCCSP-based implementation of a crypto.Signer
29+
type CryptoSigner struct {
30+
csp bccsp.BCCSP
31+
key bccsp.Key
32+
pk interface{}
33+
}
34+
35+
// Init initializes this CryptoSigner.
36+
func (s *CryptoSigner) Init(csp bccsp.BCCSP, key bccsp.Key) error {
37+
// Validate arguments
38+
if csp == nil {
39+
return errors.New("Invalid BCCSP. Nil.")
40+
}
41+
if key == nil {
42+
return errors.New("Invalid Key. Nil.")
43+
}
44+
if key.Symmetric() {
45+
return errors.New("Invalid Key. Symmetric.")
46+
}
47+
48+
// Marshall the bccsp public key as a crypto.PublicKey
49+
pub, err := key.PublicKey()
50+
if err != nil {
51+
return fmt.Errorf("Failed getting public key [%s]", err)
52+
}
53+
54+
raw, err := pub.Bytes()
55+
if err != nil {
56+
return fmt.Errorf("Failed marshalling public key [%s]", err)
57+
}
58+
59+
pk, err := primitives.DERToPublicKey(raw)
60+
if err != nil {
61+
return fmt.Errorf("Failed marshalling public key [%s]", err)
62+
}
63+
64+
// Init fields
65+
s.csp = csp
66+
s.key = key
67+
s.pk = pk
68+
69+
return nil
70+
71+
}
72+
73+
// Public returns the public key corresponding to the opaque,
74+
// private key.
75+
func (s *CryptoSigner) Public() crypto.PublicKey {
76+
return s.pk
77+
}
78+
79+
// Sign signs digest with the private key, possibly using entropy from
80+
// rand. For an RSA key, the resulting signature should be either a
81+
// PKCS#1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA
82+
// key, it should be a DER-serialised, ASN.1 signature structure.
83+
//
84+
// Hash implements the SignerOpts interface and, in most cases, one can
85+
// simply pass in the hash function used as opts. Sign may also attempt
86+
// to type assert opts to other types in order to obtain algorithm
87+
// specific values. See the documentation in each package for details.
88+
//
89+
// Note that when a signature of a hash of a larger message is needed,
90+
// the caller is responsible for hashing the larger message and passing
91+
// the hash (as digest) and the hash function (as opts) to Sign.
92+
func (s *CryptoSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
93+
if opts == nil {
94+
return s.csp.Sign(s.key, digest, nil)
95+
}
96+
97+
so, ok := opts.(bccsp.SignerOpts)
98+
if !ok {
99+
return nil, errors.New("Invalid opts type. Expecting bccsp.SignerOpts")
100+
}
101+
102+
return s.csp.Sign(s.key, digest, so)
103+
}
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package signer
17+
18+
import (
19+
"crypto/rand"
20+
"os"
21+
"testing"
22+
23+
"github.com/hyperledger/fabric/core/crypto/bccsp"
24+
"github.com/hyperledger/fabric/core/crypto/bccsp/sw"
25+
"github.com/hyperledger/fabric/core/crypto/primitives"
26+
"github.com/spf13/viper"
27+
)
28+
29+
var (
30+
swBCCSPInstance bccsp.BCCSP
31+
)
32+
33+
func getBCCSP(t *testing.T) bccsp.BCCSP {
34+
if swBCCSPInstance == nil {
35+
primitives.InitSecurityLevel("SHA2", 256)
36+
viper.Set("security.bccsp.default.keyStorePath", os.TempDir())
37+
38+
var err error
39+
swBCCSPInstance, err = sw.New()
40+
if err != nil {
41+
t.Fatalf("Failed initializing key store [%s]", err)
42+
}
43+
}
44+
45+
return swBCCSPInstance
46+
}
47+
48+
func TestInit(t *testing.T) {
49+
csp := getBCCSP(t)
50+
51+
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true})
52+
if err != nil {
53+
t.Fatalf("Failed generating ECDSA key [%s]", err)
54+
}
55+
56+
signer := &CryptoSigner{}
57+
err = signer.Init(csp, k)
58+
if err != nil {
59+
t.Fatalf("Failed initializing CryptoSigner [%s]", err)
60+
}
61+
}
62+
63+
func TestPublic(t *testing.T) {
64+
csp := getBCCSP(t)
65+
66+
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true})
67+
if err != nil {
68+
t.Fatalf("Failed generating ECDSA key [%s]", err)
69+
}
70+
71+
signer := &CryptoSigner{}
72+
err = signer.Init(csp, k)
73+
if err != nil {
74+
t.Fatalf("Failed initializing CryptoSigner [%s]", err)
75+
}
76+
77+
pk := signer.Public()
78+
if pk == nil {
79+
t.Fatal("Failed getting PublicKey. Nil.")
80+
}
81+
}
82+
83+
func TestSign(t *testing.T) {
84+
csp := getBCCSP(t)
85+
86+
k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true})
87+
if err != nil {
88+
t.Fatalf("Failed generating ECDSA key [%s]", err)
89+
}
90+
91+
signer := &CryptoSigner{}
92+
err = signer.Init(csp, k)
93+
if err != nil {
94+
t.Fatalf("Failed initializing CryptoSigner [%s]", err)
95+
}
96+
97+
msg := []byte("Hello World")
98+
signature, err := signer.Sign(rand.Reader, primitives.Hash(msg), nil)
99+
if err != nil {
100+
t.Fatalf("Failed generating ECDSA signature [%s]", err)
101+
}
102+
103+
valid, err := csp.Verify(k, signature, primitives.Hash(msg))
104+
if err != nil {
105+
t.Fatalf("Failed verifying ECDSA signature [%s]", err)
106+
}
107+
if !valid {
108+
t.Fatal("Failed verifying ECDSA signature. Signature not valid.")
109+
}
110+
}

0 commit comments

Comments
 (0)