Skip to content

Commit

Permalink
[FABG-1008] Allows ecdsakey to return private key bytes (#145)
Browse files Browse the repository at this point in the history
While creating a Commercial Paper application using fabric-sdk-go, I cannot retrieve the ecdsakey private key bytes needed to create the x509Identity.  Calling the ```PrivateKey().Bytes()``` method throws a Not implemented error.  However, this same code in the fabric-skd-node happily returns the Byte array of the ecdsakey.

Expands the integration test to validate the private key bytes and tests creating a new x509 identity

Signed-off-by: Paul Plavetzki <paul@pareidolia.io>
  • Loading branch information
pplavetzki committed Sep 10, 2020
1 parent 842c4b3 commit a18228f
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 7 deletions.
16 changes: 14 additions & 2 deletions internal/github.com/hyperledger/fabric/bccsp/sw/ecdsakey.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,32 @@ import (
"crypto/elliptic"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"

"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/bccsp"
)

type ecdsaPrivateKey struct {
privKey *ecdsa.PrivateKey
privKey *ecdsa.PrivateKey
exportable bool
}

// Bytes converts this key to its byte representation,
// if this operation is allowed.
func (k *ecdsaPrivateKey) Bytes() ([]byte, error) {
return nil, errors.New("Not supported.")
if !k.exportable {
return nil, errors.New("not supported")
}

x509Encoded, err := x509.MarshalECPrivateKey(k.privKey)
if err != nil {
return nil, err
}
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})

return pemEncoded, nil
}

// SKI returns the subject key identifier of this key.
Expand Down
4 changes: 2 additions & 2 deletions internal/github.com/hyperledger/fabric/bccsp/sw/fileks.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (ks *fileBasedKeyStore) GetKey(ski []byte) (bccsp.Key, error) {

switch k := key.(type) {
case *ecdsa.PrivateKey:
return &ecdsaPrivateKey{k}, nil
return &ecdsaPrivateKey{k, true}, nil
default:
return nil, errors.New("secret key type not recognized")
}
Expand Down Expand Up @@ -227,7 +227,7 @@ func (ks *fileBasedKeyStore) searchKeystoreForSKI(ski []byte) (k bccsp.Key, err

switch kk := key.(type) {
case *ecdsa.PrivateKey:
k = &ecdsaPrivateKey{kk}
k = &ecdsaPrivateKey{kk, true}
default:
continue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (kd *ecdsaPrivateKeyKeyDeriver) KeyDeriv(key bccsp.Key, opts bccsp.KeyDeriv
return nil, errors.New("Failed temporary public key IsOnCurve check.")
}

return &ecdsaPrivateKey{tempSK}, nil
return &ecdsaPrivateKey{tempSK, true}, nil
}

type aesPrivateKeyKeyDeriver struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/github.com/hyperledger/fabric/bccsp/sw/keygen.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (kg *ecdsaKeyGenerator) KeyGen(opts bccsp.KeyGenOpts) (bccsp.Key, error) {
return nil, fmt.Errorf("Failed generating ECDSA key for [%v]: [%s]", kg.curve, err)
}

return &ecdsaPrivateKey{privKey}, nil
return &ecdsaPrivateKey{privKey, true}, nil
}

type aesKeyGenerator struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (*ecdsaPrivateKeyImportOptsKeyImporter) KeyImport(raw interface{}, opts bcc
return nil, errors.New("Failed casting to ECDSA private key. Invalid raw material.")
}

return &ecdsaPrivateKey{ecdsaSK}, nil
return &ecdsaPrivateKey{ecdsaSK, true}, nil
}

type ecdsaGoPublicKeyImportOptsKeyImporter struct{}
Expand Down
55 changes: 55 additions & 0 deletions test/integration/pkg/client/msp/identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ SPDX-License-Identifier: Apache-2.0
package msp

import (
"crypto/x509"
"encoding/pem"
"testing"

"fmt"

"github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/pkg/gateway"
"github.com/hyperledger/fabric-sdk-go/test/integration"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -216,6 +219,58 @@ func TestGetAllIdentities(t *testing.T) {
}
}

func TestSigningIdentityPrivateKey(t *testing.T) {
mspClient, sdk := setupClient(t)
defer integration.CleanupUserData(t, sdk)

// Generate a random user name
username := integration.GenerateRandomID()

req := &msp.IdentityRequest{
ID: username,
Affiliation: "org2",
Type: IdentityTypeUser,
}

// Create new identity
newIdentity, err := mspClient.CreateIdentity(req)
if err != nil {
t.Fatalf("Create identity failed: %s", err)
}

if newIdentity.Secret == "" {
t.Fatal("Secret should have been generated")
}

// Enroll the new user
err = mspClient.Enroll(username, msp.WithSecret(newIdentity.Secret))
if err != nil {
t.Fatalf("Enroll failed: %s", err)
}

// Get the new user's signing identity
si, err := mspClient.GetSigningIdentity(username)
if err != nil {
t.Fatalf("GetSigningIdentity failed: %s", err)
}
// Get the bytes of the private key
pk, err := si.PrivateKey().Bytes()
if err != nil {
t.Fatalf("Get PrivateKey Bytes should not throw error: %s", err)
}
// Test that we have a valid ECPrivateKey
p, _ := pem.Decode(pk)
_, err = x509.ParseECPrivateKey(p.Bytes)
if err != nil {
t.Fatalf("Get ParseECPrivateKey should not throw error: %s", err)
}
// Create a new Identity with the bytes
identity := gateway.NewX509Identity("org2", string(si.EnrollmentCertificate()), string(pk))
if identity == nil {
t.Fatalf("Should return a valid identity")
}
}

func containsIdentities(identities []*msp.IdentityResponse, requests ...*msp.IdentityRequest) bool {
for _, request := range requests {
if !containsIdentity(identities, request) {
Expand Down
1 change: 1 addition & 0 deletions test/performance/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/golang/protobuf v1.3.3
github.com/hyperledger/fabric-protos-go v0.0.0-20200707132912-fee30f3ccd23
github.com/hyperledger/fabric-sdk-go v0.0.0-00010101000000-000000000000
github.com/hyperledger/fabric-sdk-go/test/integration v0.0.0-20200909154308-842c4b3ea51e // indirect
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.5.1
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
Expand Down
2 changes: 2 additions & 0 deletions test/performance/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e h1:9P
github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-protos-go v0.0.0-20200707132912-fee30f3ccd23 h1:SEbB3yH4ISTGRifDamYXAst36gO2kM855ndMJlsv+pc=
github.com/hyperledger/fabric-protos-go v0.0.0-20200707132912-fee30f3ccd23/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
github.com/hyperledger/fabric-sdk-go/test/integration v0.0.0-20200909154308-842c4b3ea51e h1:OgmeW+oiQEjjY25lMKK31AEfcw/+I2ncSW3y06tPMg4=
github.com/hyperledger/fabric-sdk-go/test/integration v0.0.0-20200909154308-842c4b3ea51e/go.mod h1:pbWZ9ogxfoPuZ0Kv9M6hFcYPDGWft/EGgLoLrJPsawc=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
Expand Down

0 comments on commit a18228f

Please sign in to comment.