Skip to content

Commit

Permalink
[FAB-9526] Idemix BCCSP
Browse files Browse the repository at this point in the history
This change-set provides a BCCSP implementation
supporting the idemix opts

Change-Id: Ia675ba19f07a464bbb01110a48276557d6ba2f13
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 25, 2018
1 parent 7472576 commit 8e6db51
Show file tree
Hide file tree
Showing 40 changed files with 941 additions and 517 deletions.
106 changes: 106 additions & 0 deletions bccsp/idemix/bccsp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package idemix

import (
"reflect"

"github.com/hyperledger/fabric/bccsp/idemix/bridge"

"github.com/hyperledger/fabric/bccsp/idemix/handlers"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/sw"
"github.com/pkg/errors"
)

type csp struct {
bccsp.BCCSP
}

func New(keyStore bccsp.KeyStore) (*csp, error) {
base, err := sw.New(keyStore)
if err != nil {
return nil, errors.Wrap(err, "failed instantiating base bccsp")
}

csp := &csp{BCCSP: base}

// key generators
base.AddWrapper(reflect.TypeOf(&bccsp.IdemixIssuerKeyGenOpts{}), &handlers.IssuerKeyGen{Issuer: &bridge.Issuer{NewRand: bridge.NewRandOrPanic}})
base.AddWrapper(reflect.TypeOf(&bccsp.IdemixUserSecretKeyGenOpts{}), &handlers.UserKeyGen{User: &bridge.User{NewRand: bridge.NewRandOrPanic}})
base.AddWrapper(reflect.TypeOf(&bccsp.IdemixRevocationKeyGenOpts{}), &handlers.RevocationKeyGen{Revocation: &bridge.Revocation{}})

// key derivers
base.AddWrapper(reflect.TypeOf(handlers.NewUserSecretKey(nil, false)), &handlers.NymKeyDerivation{
User: &bridge.User{NewRand: bridge.NewRandOrPanic},
})

// signers
base.AddWrapper(reflect.TypeOf(handlers.NewUserSecretKey(nil, false)), &userSecreKeySignerMultiplexer{
signer: &handlers.Signer{SignatureScheme: &bridge.SignatureScheme{NewRand: bridge.NewRandOrPanic}},
nymSigner: &handlers.NymSigner{NymSignatureScheme: &bridge.NymSignatureScheme{NewRand: bridge.NewRandOrPanic}},
credentialRequestSigner: &handlers.CredentialRequestSigner{CredRequest: &bridge.CredRequest{NewRand: bridge.NewRandOrPanic}},
})
base.AddWrapper(reflect.TypeOf(handlers.NewIssuerSecretKey(nil, false)), &handlers.CredentialSigner{
Credential: &bridge.Credential{NewRand: bridge.NewRandOrPanic},
})
base.AddWrapper(reflect.TypeOf(handlers.NewRevocationSecretKey(nil, false)), &handlers.CriSigner{
Revocation: &bridge.Revocation{},
})

// verifiers
base.AddWrapper(reflect.TypeOf(handlers.NewIssuerPublicKey(nil)), &issuerPublicKeyVerifierMultiplexer{
verifier: &handlers.Verifier{SignatureScheme: &bridge.SignatureScheme{NewRand: bridge.NewRandOrPanic}},
credentialRequestVerifier: &handlers.CredentialRequestVerifier{CredRequest: &bridge.CredRequest{NewRand: bridge.NewRandOrPanic}},
})
base.AddWrapper(reflect.TypeOf(handlers.NewNymPublicKey(nil)), &handlers.NymVerifier{
NymSignatureScheme: &bridge.NymSignatureScheme{NewRand: bridge.NewRandOrPanic},
})
base.AddWrapper(reflect.TypeOf(handlers.NewUserSecretKey(nil, false)), &handlers.CredentialVerifier{
Credential: &bridge.Credential{NewRand: bridge.NewRandOrPanic},
})
base.AddWrapper(reflect.TypeOf(handlers.NewRevocationPublicKey(nil)), &handlers.CriVerifier{
Revocation: &bridge.Revocation{},
})

return csp, nil
}

type userSecreKeySignerMultiplexer struct {
signer *handlers.Signer
nymSigner *handlers.NymSigner
credentialRequestSigner *handlers.CredentialRequestSigner
}

func (s *userSecreKeySignerMultiplexer) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
switch opts.(type) {
case *bccsp.IdemixSignerOpts:
return s.signer.Sign(k, digest, opts)
case *bccsp.IdemixNymSignerOpts:
return s.nymSigner.Sign(k, digest, opts)
case *bccsp.IdemixCredentialRequestSignerOpts:
return s.credentialRequestSigner.Sign(k, digest, opts)
default:
return nil, errors.New("invalid opts, expected *bccsp.IdemixSignerOpt or *bccsp.IdemixNymSignerOpts or *bccsp.IdemixCredentialRequestSignerOpts")
}
}

type issuerPublicKeyVerifierMultiplexer struct {
verifier *handlers.Verifier
credentialRequestVerifier *handlers.CredentialRequestVerifier
}

func (v *issuerPublicKeyVerifierMultiplexer) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
switch opts.(type) {
case *bccsp.IdemixSignerOpts:
return v.verifier.Verify(k, signature, digest, opts)
case *bccsp.IdemixCredentialRequestSignerOpts:
return v.credentialRequestVerifier.Verify(k, signature, digest, opts)
default:
return false, errors.New("invalid opts, expected *bccsp.IdemixSignerOpts or *bccsp.IdemixCredentialRequestSignerOpts")
}
}
291 changes: 291 additions & 0 deletions bccsp/idemix/bccsp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package idemix_test

import (
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/idemix"
"github.com/hyperledger/fabric/bccsp/sw"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Idemix Bridge", func() {

Describe("setting up the environment with one issuer and one user", func() {
var (
CSP bccsp.BCCSP
IssuerKey bccsp.Key
IssuerPublicKey bccsp.Key
AttributeNames []string

UserKey bccsp.Key
NymKey bccsp.Key
NymPublicKey bccsp.Key

credRequest []byte

credential []byte

RevocationKey bccsp.Key
RevocationPublicKey bccsp.Key
cri []byte
)

BeforeEach(func() {
var err error
CSP, err = idemix.New(sw.NewDummyKeyStore())
Expect(err).NotTo(HaveOccurred())

// Issuer
AttributeNames = []string{"Attr1", "Attr2", "Attr3", "Attr4", "Attr5"}
IssuerKey, err = CSP.KeyGen(&bccsp.IdemixIssuerKeyGenOpts{Temporary: true, AttributeNames: AttributeNames})
Expect(err).NotTo(HaveOccurred())
IssuerPublicKey, err = IssuerKey.PublicKey()
Expect(err).NotTo(HaveOccurred())

// User
UserKey, err = CSP.KeyGen(&bccsp.IdemixUserSecretKeyGenOpts{Temporary: true})
Expect(err).NotTo(HaveOccurred())

// User Nym Key
NymKey, err = CSP.KeyDeriv(UserKey, &bccsp.IdemixNymKeyDerivationOpts{Temporary: true, IssuerPK: IssuerPublicKey})
Expect(err).NotTo(HaveOccurred())
NymPublicKey, err = NymKey.PublicKey()
Expect(err).NotTo(HaveOccurred())

// Credential Request for User
credRequest, err = CSP.Sign(
UserKey,
bccsp.IdemixEmptyDigest(),
&bccsp.IdemixCredentialRequestSignerOpts{IssuerPK: IssuerPublicKey},
)
Expect(err).NotTo(HaveOccurred())

// Credential
credential, err = CSP.Sign(
IssuerKey,
credRequest,
&bccsp.IdemixCredentialSignerOpts{
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0}},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1}},
{Type: bccsp.IdemixIntAttribute, Value: 1},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1, 2}},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1, 2, 3}},
},
},
)
Expect(err).NotTo(HaveOccurred())

// Revocation
RevocationKey, err = CSP.KeyGen(&bccsp.IdemixRevocationKeyGenOpts{Temporary: true})
Expect(err).NotTo(HaveOccurred())
RevocationPublicKey, err = RevocationKey.PublicKey()
Expect(err).NotTo(HaveOccurred())

// CRI
cri, err = CSP.Sign(
RevocationKey,
bccsp.IdemixEmptyDigest(),
&bccsp.IdemixCRISignerOpts{},
)
Expect(err).NotTo(HaveOccurred())

})

It("the environment is properly set", func() {
// Verify CredRequest
valid, err := CSP.Verify(
IssuerPublicKey,
credRequest,
bccsp.IdemixEmptyDigest(),
&bccsp.IdemixCredentialRequestSignerOpts{},
)
Expect(err).NotTo(HaveOccurred())
Expect(valid).To(BeTrue())

// Verify Credential
valid, err = CSP.Verify(
UserKey,
credential,
bccsp.IdemixEmptyDigest(),
&bccsp.IdemixCredentialSignerOpts{
IssuerPK: IssuerPublicKey,
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0}},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1}},
{Type: bccsp.IdemixIntAttribute, Value: 1},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1, 2}},
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0, 1, 2, 3}},
},
},
)
Expect(err).NotTo(HaveOccurred())
Expect(valid).To(BeTrue())

// Verify CRI
valid, err = CSP.Verify(
RevocationPublicKey,
cri,
bccsp.IdemixEmptyDigest(),
&bccsp.IdemixCRISignerOpts{},
)
Expect(err).NotTo(HaveOccurred())
})

Describe("producing an idemix signature with no disclosed attribute", func() {
var (
digest []byte
signature []byte
)

BeforeEach(func() {
var err error

digest = []byte("a digest")

signature, err = CSP.Sign(
UserKey,
digest,
&bccsp.IdemixSignerOpts{
Credential: credential,
Nym: NymKey,
IssuerPK: IssuerPublicKey,
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
},
RhIndex: 4,
Epoch: 0,
CRI: cri,
},
)
Expect(err).NotTo(HaveOccurred())
})

It("the signature is valid", func() {
valid, err := CSP.Verify(
IssuerPublicKey,
signature,
digest,
&bccsp.IdemixSignerOpts{
RevocationPublicKey: RevocationPublicKey,
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
},
RhIndex: 4,
Epoch: 0,
},
)
Expect(err).NotTo(HaveOccurred())
Expect(valid).To(BeTrue())
})

})

Describe("producing an idemix signature with disclosed attributes", func() {
var (
digest []byte
signature []byte
)

BeforeEach(func() {
var err error

digest = []byte("a digest")

signature, err = CSP.Sign(
UserKey,
digest,
&bccsp.IdemixSignerOpts{
Credential: credential,
Nym: NymKey,
IssuerPK: IssuerPublicKey,
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixBytesAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixIntAttribute},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
},
RhIndex: 4,
Epoch: 0,
CRI: cri,
},
)
Expect(err).NotTo(HaveOccurred())
})

It("the signature is valid", func() {
valid, err := CSP.Verify(
IssuerPublicKey,
signature,
digest,
&bccsp.IdemixSignerOpts{
RevocationPublicKey: RevocationPublicKey,
Attributes: []bccsp.IdemixAttribute{
{Type: bccsp.IdemixBytesAttribute, Value: []byte{0}},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixIntAttribute, Value: 1},
{Type: bccsp.IdemixHiddenAttribute},
{Type: bccsp.IdemixHiddenAttribute},
},
RhIndex: 4,
Epoch: 0,
},
)
Expect(err).NotTo(HaveOccurred())
Expect(valid).To(BeTrue())
})

})

Describe("producing an idemix nym signature", func() {
var (
digest []byte
signature []byte
)

BeforeEach(func() {
var err error

digest = []byte("a digest")

signature, err = CSP.Sign(
UserKey,
digest,
&bccsp.IdemixNymSignerOpts{
Nym: NymKey,
IssuerPK: IssuerPublicKey,
},
)
Expect(err).NotTo(HaveOccurred())
})

It("the signature is valid", func() {
valid, err := CSP.Verify(
NymPublicKey,
signature,
digest,
&bccsp.IdemixNymSignerOpts{
IssuerPK: IssuerPublicKey,
},
)
Expect(err).NotTo(HaveOccurred())
Expect(valid).To(BeTrue())
})

})
})
})
Loading

0 comments on commit 8e6db51

Please sign in to comment.