Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

self-contained identity stack #561

Merged
merged 1 commit into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions token/core/fabtoken/driver/deserializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (e *EnrollmentService) GetRevocationHandler(auditInfo []byte) (string, erro
if err := ai.FromBytes(si.Recipient); err != nil {
return "", errors.Wrapf(err, "failed unamrshalling audit info [%s]", auditInfo)
}
return ai.RevocationHandle, nil
return string(ai.RevocationHandle), nil
}

return "", nil
Expand All @@ -171,5 +171,5 @@ func (e *EnrollmentService) GetRevocationHandler(auditInfo []byte) (string, erro
if err := ai.FromBytes(auditInfo); err != nil {
return "", errors.Wrapf(err, "failed unmarshalling audit info [%s]", auditInfo)
}
return ai.RevocationHandle, nil
return string(ai.RevocationHandle), nil
}
5 changes: 2 additions & 3 deletions token/core/zkatdlog/crypto/audit/auditor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"time"

math "github.com/IBM/mathlib"
idemix2 "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/msp/idemix"
sig2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/core/sig"
_ "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver/memory"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/kvs"
Expand Down Expand Up @@ -226,7 +225,7 @@ func (f *fakeProv) TranslatePath(path string) string {
return ""
}

func getIdemixInfo(dir string) (view.Identity, *idemix2.AuditInfo) {
func getIdemixInfo(dir string) (view.Identity, *idemix.AuditInfo) {
registry := registry2.New()
Expect(registry.RegisterService(&fakeProv{typ: "memory"})).NotTo(HaveOccurred())

Expand All @@ -241,7 +240,7 @@ func getIdemixInfo(dir string) (view.Identity, *idemix2.AuditInfo) {
config, err := msp2.GetLocalMspConfigWithType(dir, nil, "idemix", "idemix")
Expect(err).NotTo(HaveOccurred())

p, err := idemix2.NewProviderWithEidRhNymPolicy(config, registry)
p, err := idemix.NewProviderWithEidRhNymPolicy(config, registry)
Expect(err).NotTo(HaveOccurred())
Expect(p).NotTo(BeNil())

Expand Down
7 changes: 3 additions & 4 deletions token/core/zkatdlog/crypto/validator/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"time"

math "github.com/IBM/mathlib"
idemix2 "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/msp/idemix"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/core/sig"
_ "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver/memory"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/kvs"
Expand Down Expand Up @@ -360,7 +359,7 @@ func (f *fakeProv) TranslatePath(path string) string {
return ""
}

func getIdemixInfo(dir string) (view.Identity, *idemix2.AuditInfo, driver.SigningIdentity) {
func getIdemixInfo(dir string) (view.Identity, *idemix.AuditInfo, driver.SigningIdentity) {
registry := registry2.New()
Expect(registry.RegisterService(&fakeProv{typ: "memory"})).NotTo(HaveOccurred())

Expand All @@ -375,7 +374,7 @@ func getIdemixInfo(dir string) (view.Identity, *idemix2.AuditInfo, driver.Signin
config, err := msp2.GetLocalMspConfigWithType(dir, nil, "idemix", "idemix")
Expect(err).NotTo(HaveOccurred())

p, err := idemix2.NewProviderWithEidRhNymPolicy(config, registry)
p, err := idemix.NewProviderWithEidRhNymPolicy(config, registry)
Expect(err).NotTo(HaveOccurred())
Expect(p).NotTo(BeNil())

Expand Down Expand Up @@ -448,7 +447,7 @@ func prepareIssue(auditor *audit.Auditor, issuer issue2.Issuer) (*driver.TokenRe
return ir, issueMetadata
}

func prepareTransfer(pp *crypto.PublicParams, signer driver.SigningIdentity, auditor *audit.Auditor, auditInfo *idemix2.AuditInfo, id []byte, owners [][]byte) (*transfer.Sender, *driver.TokenRequest, *driver.TokenRequestMetadata, []*tokn.Token) {
func prepareTransfer(pp *crypto.PublicParams, signer driver.SigningIdentity, auditor *audit.Auditor, auditInfo *idemix.AuditInfo, id []byte, owners [][]byte) (*transfer.Sender, *driver.TokenRequest, *driver.TokenRequestMetadata, []*tokn.Token) {

signers := make([]driver.Signer, 2)
signers[0] = signer
Expand Down
4 changes: 2 additions & 2 deletions token/services/identity/msp/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ package common
import (
"reflect"

"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/msp/idemix"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver"
view2 "github.com/hyperledger-labs/fabric-smart-client/platform/view"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/core/sig"
driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/view/driver"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -58,7 +58,7 @@ func (i *IdentityInfo) Remote() bool {
}

type SignerService interface {
idemix.SignerService
RegisterSigner(identity view.Identity, signer driver2.Signer, verifier driver2.Verifier) error
IsMe(view.Identity) bool
RegisterVerifier(identity view.Identity, v driver.Verifier) error
RegisterAuditInfo(identity view.Identity, info []byte) error
Expand Down
101 changes: 101 additions & 0 deletions token/services/identity/msp/idemix/audit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package idemix

import (
"encoding/json"

csp "github.com/IBM/idemix/bccsp/types"
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/proto"
m "github.com/hyperledger/fabric-protos-go/msp"
"github.com/pkg/errors"
)

type AuditInfo struct {
EidNymAuditData *csp.AttrNymAuditData
RhNymAuditData *csp.AttrNymAuditData
Attributes [][]byte
Csp csp.BCCSP `json:"-"`
IssuerPublicKey csp.Key `json:"-"`
}

func (a *AuditInfo) Bytes() ([]byte, error) {
return json.Marshal(a)
}

func (a *AuditInfo) FromBytes(raw []byte) error {
return json.Unmarshal(raw, a)
}

func (a *AuditInfo) EnrollmentID() string {
return string(a.Attributes[2])
}

func (a *AuditInfo) RevocationHandle() string {
return string(a.Attributes[3])
}

func (a *AuditInfo) Match(id []byte) error {
si := &m.SerializedIdentity{}
err := proto.Unmarshal(id, si)
if err != nil {
return errors.Wrap(err, "failed to unmarshal to msp.SerializedIdentity{}")
}

serialized := new(m.SerializedIdemixIdentity)
err = proto.Unmarshal(si.IdBytes, serialized)
if err != nil {
return errors.Wrap(err, "could not deserialize a SerializedIdemixIdentity")
}

// Audit EID
valid, err := a.Csp.Verify(
a.IssuerPublicKey,
serialized.Proof,
nil,
&csp.EidNymAuditOpts{
EidIndex: EIDIndex,
EnrollmentID: string(a.Attributes[EIDIndex]),
RNymEid: a.EidNymAuditData.Rand,
},
)
if err != nil {
return errors.Wrap(err, "error while verifying the nym eid")
}
if !valid {
return errors.New("invalid nym rh")
}

// Audit RH
valid, err = a.Csp.Verify(
a.IssuerPublicKey,
serialized.Proof,
nil,
&csp.RhNymAuditOpts{
RhIndex: RHIndex,
RevocationHandle: string(a.Attributes[RHIndex]),
RNymRh: a.RhNymAuditData.Rand,
},
)
if err != nil {
return errors.Wrap(err, "error while verifying the nym rh")
}
if !valid {
return errors.New("invalid nym eid")
}

return nil
}

func DeserializeAuditInfo(raw []byte) (*AuditInfo, error) {
auditInfo := &AuditInfo{}
err := auditInfo.FromBytes(raw)
if err != nil {
return nil, err
}
return auditInfo, nil
}
7 changes: 3 additions & 4 deletions token/services/identity/msp/idemix/bccsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/IBM/idemix/bccsp/keystore"
bccsp "github.com/IBM/idemix/bccsp/types"
math "github.com/IBM/mathlib"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/msp/idemix"
"github.com/pkg/errors"
)

Expand All @@ -20,16 +19,16 @@ import (
func NewKVSBCCSP(kvsStore keystore.KVS, curveID math.CurveID) (bccsp.BCCSP, error) {
if curveID == math.BLS12_381_BBS {
logger.Debugf("new aries KVS-based BCCSP")
return idemix.NewKSVBCCSP(kvsStore, curveID, true)
return NewKSVBCCSP(kvsStore, curveID, true)
}
logger.Debugf("new dlog KVS-based BCCSP")
return idemix.NewKSVBCCSP(kvsStore, curveID, false)
return NewKSVBCCSP(kvsStore, curveID, false)
}

// NewAriesBCCSP returns an instance of the idemix BCCSP for the given curve based on aries
func NewAriesBCCSP() (bccsp.BCCSP, error) {
logger.Infof("new aries no-KeyStore BCCSP")
curve, tr, err := idemix.GetCurveAndTranslator(math.BLS12_381_BBS)
curve, tr, err := GetCurveAndTranslator(math.BLS12_381_BBS)
if err != nil {
return nil, err
}
Expand Down
121 changes: 94 additions & 27 deletions token/services/identity/msp/idemix/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,126 @@ SPDX-License-Identifier: Apache-2.0
package idemix

import (
"runtime"
"sync"
"time"

"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/core/generic/msp/idemix"
driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver"
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
"go.uber.org/zap/zapcore"
)

func NewIdentityCache(backed idemix.IdentityCacheBackendFunc, size int) *idemix.IdentityCache {
return idemix.NewIdentityCache(backed, size, &driver2.IdentityOptions{EIDExtension: true})
type IdentityCacheBackendFunc func(opts *driver.IdentityOptions) (view.Identity, []byte, error)

type identityCacheEntry struct {
Identity view.Identity
Audit []byte
}

type IdentityCache struct {
once sync.Once
backed IdentityCacheBackendFunc
cache chan identityCacheEntry
opts *driver.IdentityOptions
}

type WalletIdentityCacheBackendFunc func() (view.Identity, error)
func NewIdentityCache(backed IdentityCacheBackendFunc, size int, opts *driver.IdentityOptions) *IdentityCache {
ci := &IdentityCache{
backed: backed,
cache: make(chan identityCacheEntry, size),
opts: opts,
}

type WalletIdentityCache struct {
backed WalletIdentityCacheBackendFunc
ch chan view.Identity
timeout time.Duration
return ci
}

func NewWalletIdentityCache(backed WalletIdentityCacheBackendFunc, size int) *WalletIdentityCache {
ci := &WalletIdentityCache{
backed: backed,
ch: make(chan view.Identity, size),
timeout: time.Millisecond * 100,
func (c *IdentityCache) Identity(opts *driver.IdentityOptions) (view.Identity, []byte, error) {
if opts != nil {
return c.fetchIdentityFromBackend(opts)
}
if size > 0 {
go ci.run()

c.once.Do(func() {
if cap(c.cache) > 0 {
// Spin up as many background goroutines as we need to prepare identities in the background.
for i := 0; i < runtime.NumCPU(); i++ {
go c.provisionIdentities()
}
}
})

if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("fetching identity from cache...")
}
return ci

return c.fetchIdentityFromCache(opts)

}

func (c *WalletIdentityCache) Identity() (view.Identity, error) {
func (c *IdentityCache) fetchIdentityFromCache(opts *driver.IdentityOptions) (view.Identity, []byte, error) {
var identity view.Identity
var audit []byte

var start time.Time

if logger.IsEnabledFor(zapcore.DebugLevel) {
start = time.Now()
}

timeout := time.NewTimer(time.Second)
defer timeout.Stop()

select {
case entry := <-c.ch:

case entry := <-c.cache:
identity = entry.Identity
audit = entry.Audit

if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("fetch identity from producer channel done [%s][%d]", entry)
logger.Debugf("fetching identity from cache [%s][%d] took %v", identity, len(audit), time.Since(start))
}

case <-timeout.C:
id, a, err := c.backed(opts)
if err != nil {
return nil, nil, err
}
return entry, nil
default:
identity = id
audit = a

if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("fetch identity from producer channel timeout")
logger.Debugf("fetching identity from backend after a timeout [%s][%d] took %v", identity, len(audit), time.Since(start))
}
return c.backed()
}

return identity, audit, nil
}

func (c *WalletIdentityCache) run() {
func (c *IdentityCache) fetchIdentityFromBackend(opts *driver.IdentityOptions) (view.Identity, []byte, error) {
if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("fetching identity from backend")
}
id, audit, err := c.backed(opts)
if err != nil {
return nil, nil, err
}
if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("fetch identity from backend done [%s][%d]", id, len(audit))
}

return id, audit, nil
}

func (c *IdentityCache) provisionIdentities() {
count := 0
for {
id, err := c.backed()
id, audit, err := c.backed(c.opts)
if err != nil {
logger.Errorf("failed to provision identity [%s]", err)
continue
}
c.ch <- id
if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("generated new idemix identity [%d]", count)
}
c.cache <- identityCacheEntry{Identity: id, Audit: audit}
}
}
Loading
Loading