Skip to content

Commit 6b755dd

Browse files
Idemix Schema Manager support (#1144)
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com> Co-authored-by: Marcus Brandenburger <bur@zurich.ibm.com>
1 parent 5f9bcf2 commit 6b755dd

File tree

15 files changed

+515
-250
lines changed

15 files changed

+515
-250
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/gin-gonic/gin v1.10.0
1313
github.com/gobuffalo/packr/v2 v2.7.1
1414
github.com/hashicorp/go-uuid v1.0.3
15-
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717092234-498fe9f61b5f
15+
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717111311-f6c3bf731689
1616
github.com/hyperledger/fabric-chaincode-go/v2 v2.3.0
1717
github.com/hyperledger/fabric-lib-go v1.1.3-0.20240523144151-25edd1eaf5f5
1818
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.7

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,8 +1057,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
10571057
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
10581058
github.com/hyperledger-labs/SmartBFT v0.0.0-20250503203013-eb005eef8866 h1:Mu/6NJsfl9g3wM15Ue7hqPq4LtgYDoABh8MO4u8aW4g=
10591059
github.com/hyperledger-labs/SmartBFT v0.0.0-20250503203013-eb005eef8866/go.mod h1:9aNHNXsCVy/leGz2gpTC1eOL5QecxbSAGjqsLh4T1LM=
1060-
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717092234-498fe9f61b5f h1:ZXZ7qfT4m/tXqVhDoSrMwX7g2oRJtobN9lG90rKzSno=
1061-
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717092234-498fe9f61b5f/go.mod h1:34dRgLomeTQYI7fffCYDTiSQSRo9LBsPuq0aWBU5EOA=
1060+
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717111311-f6c3bf731689 h1:yR1Fv/9fVNtHNMfGO/9HDDd0Rx4LTQzUCDZsWwgVwwo=
1061+
github.com/hyperledger-labs/fabric-smart-client v0.5.1-0.20250717111311-f6c3bf731689/go.mod h1:34dRgLomeTQYI7fffCYDTiSQSRo9LBsPuq0aWBU5EOA=
10621062
github.com/hyperledger/aries-bbs-go v0.0.0-20240528084656-761671ea73bc h1:3Ykk6MtyfnlzMOQry9zkxsoLWpCWZwDPqehO/BJwArM=
10631063
github.com/hyperledger/aries-bbs-go v0.0.0-20240528084656-761671ea73bc/go.mod h1:Kofn6A6WWea1ZM8Rys5aBW9dszwJ7Ywa0kyyYL0TPYw=
10641064
github.com/hyperledger/fabric v1.4.0-rc1.0.20250510200036-435a7f1a780a h1:l9dE3iuE+mKj7K8Tcx904cF8zJpaNQONh3GNZdXnnyc=

integration/ports.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,26 @@ var (
3737
CommType: fsc.WebSocket,
3838
ReplicationFactor: token.None,
3939
}
40-
LibP2PNoReplication = &InfrastructureType{
41-
Label: ginkgo.Label("libp2p"),
42-
CommType: fsc.LibP2P,
43-
ReplicationFactor: token.None,
44-
}
4540
WebSocketWithReplication = &InfrastructureType{
4641
Label: ginkgo.Label("replicas"),
4742
CommType: fsc.WebSocket,
4843
ReplicationFactor: 3,
4944
}
45+
LibP2PNoReplication = &InfrastructureType{
46+
Label: ginkgo.Label("libp2p"),
47+
CommType: fsc.LibP2P,
48+
ReplicationFactor: token.None,
49+
}
5050

5151
WebSocketNoReplicationOnly = []*InfrastructureType{
5252
WebSocketNoReplication,
5353
}
54-
LibP2PNoReplicationOnly = []*InfrastructureType{
55-
LibP2PNoReplication,
56-
}
5754
WebSocketWithReplicationOnly = []*InfrastructureType{
5855
WebSocketWithReplication,
5956
}
57+
LibP2PNoReplicationOnly = []*InfrastructureType{
58+
LibP2PNoReplication,
59+
}
6060

6161
AllTestTypes = []*InfrastructureType{
6262
WebSocketNoReplication,

token/services/identity/idemix/crypto/audit.go

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,27 @@ import (
1313
"github.com/pkg/errors"
1414
)
1515

16+
type Schema = string
17+
18+
// SchemaManager handles the various credential schemas. A credential schema
19+
// contains information about the number of attributes, which attributes
20+
// must be disclosed when creating proofs, the format of the attributes etc.
21+
type SchemaManager interface {
22+
// EidNymAuditOpts returns the options that `sid` must use to audit an EIDNym
23+
EidNymAuditOpts(schema string, attrs [][]byte) (*csp.EidNymAuditOpts, error)
24+
// RhNymAuditOpts returns the options that `sid` must use to audit an RhNym
25+
RhNymAuditOpts(schema string, attrs [][]byte) (*csp.RhNymAuditOpts, error)
26+
}
27+
1628
type AuditInfo struct {
1729
EidNymAuditData *csp.AttrNymAuditData
1830
RhNymAuditData *csp.AttrNymAuditData
1931
Attributes [][]byte
20-
Csp csp.BCCSP `json:"-"`
21-
IssuerPublicKey csp.Key `json:"-"`
32+
33+
Csp csp.BCCSP `json:"-"`
34+
IssuerPublicKey csp.Key `json:"-"`
35+
SchemaManager SchemaManager `json:"-"`
36+
Schema string
2237
}
2338

2439
func (a *AuditInfo) Bytes() ([]byte, error) {
@@ -44,16 +59,18 @@ func (a *AuditInfo) Match(id []byte) error {
4459
return errors.Wrap(err, "could not deserialize a SerializedIdemixIdentity")
4560
}
4661

62+
eidAuditOpts, err := a.SchemaManager.EidNymAuditOpts(a.Schema, a.Attributes)
63+
if err != nil {
64+
return errors.Wrap(err, "error while getting a RhNymAuditOpts")
65+
}
66+
eidAuditOpts.RNymEid = a.EidNymAuditData.Rand
67+
4768
// Audit EID
4869
valid, err := a.Csp.Verify(
4970
a.IssuerPublicKey,
5071
serialized.Proof,
5172
nil,
52-
&csp.EidNymAuditOpts{
53-
EidIndex: EIDIndex,
54-
EnrollmentID: string(a.Attributes[EIDIndex]),
55-
RNymEid: a.EidNymAuditData.Rand,
56-
},
73+
eidAuditOpts,
5774
)
5875
if err != nil {
5976
return errors.Wrap(err, "error while verifying the nym eid")
@@ -62,16 +79,18 @@ func (a *AuditInfo) Match(id []byte) error {
6279
return errors.New("invalid nym rh")
6380
}
6481

82+
rhAuditOpts, err := a.SchemaManager.RhNymAuditOpts(a.Schema, a.Attributes)
83+
if err != nil {
84+
return errors.Wrap(err, "error while getting a RhNymAuditOpts")
85+
}
86+
rhAuditOpts.RNymRh = a.RhNymAuditData.Rand
87+
6588
// Audit RH
6689
valid, err = a.Csp.Verify(
6790
a.IssuerPublicKey,
6891
serialized.Proof,
6992
nil,
70-
&csp.RhNymAuditOpts{
71-
RhIndex: RHIndex,
72-
RevocationHandle: string(a.Attributes[RHIndex]),
73-
RNymRh: a.RhNymAuditData.Rand,
74-
},
93+
rhAuditOpts,
7594
)
7695
if err != nil {
7796
return errors.Wrap(err, "error while verifying the nym rh")

token/services/identity/idemix/crypto/config.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ type SignerConfig struct {
4242
Role int `protobuf:"varint,4,opt,name=role,json=role" json:"role,omitempty"`
4343
// EnrollmentID contains the enrollment id of this signer
4444
EnrollmentID string `protobuf:"bytes,5,opt,name=enrollment_id,json=enrollmentId" json:"enrollment_id,omitempty"`
45-
// CRI contains a serialized Credential Revocation Information
45+
// CRI contains a serialized CredentialRevocationInformation
4646
CredentialRevocationInformation []byte `protobuf:"bytes,6,opt,name=credential_revocation_information,json=credentialRevocationInformation,proto3" json:"credential_revocation_information,omitempty"`
4747
// RevocationHandle is the handle used to single out this credential and determine its revocation status
4848
RevocationHandle string `protobuf:"bytes,7,opt,name=revocation_handle,json=revocationHandle,proto3" json:"revocation_handle,omitempty"`
4949
// CurveID specifies the name of the Idemix curve to use, defaults to 'amcl.Fp256bn'
5050
CurveID string `protobuf:"bytes,8,opt,name=curve_id,json=curveID" json:"curveID,omitempty"`
51+
// Schema contains the version of the schema used by this credential
52+
Schema string `protobuf:"bytes,9,opt,name=schema,json=schema" json:"schema,omitempty"`
5153
}
5254

5355
const (
@@ -145,6 +147,7 @@ func NewFabricCAIdemixConfig(issuerPublicKey []byte, dir string) (*Config, error
145147
EnrollmentId: si.EnrollmentID,
146148
CredentialRevocationInformation: si.CredentialRevocationInformation,
147149
RevocationHandle: si.RevocationHandle,
150+
Schema: si.Schema,
148151
}
149152
} else {
150153
if !os.IsNotExist(errors.Cause(err)) {

token/services/identity/idemix/crypto/deserializer.go

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ type Deserializer struct {
2727
VerType bccsp.VerificationType
2828
NymEID []byte
2929
RhNym []byte
30+
SchemaManager SchemaManager
31+
Schema string
3032
}
3133

32-
func (c *Deserializer) Deserialize(raw []byte, checkValidity bool) (*DeserializedIdentity, error) {
33-
return c.DeserializeAgainstNymEID(raw, checkValidity, nil)
34+
func (d *Deserializer) Deserialize(raw []byte) (*DeserializedIdentity, error) {
35+
return d.DeserializeAgainstNymEID(raw, nil)
3436
}
3537

36-
func (c *Deserializer) DeserializeAgainstNymEID(identity []byte, checkValidity bool, nymEID []byte) (*DeserializedIdentity, error) {
38+
func (d *Deserializer) DeserializeAgainstNymEID(identity []byte, nymEID []byte) (*DeserializedIdentity, error) {
3739
if len(identity) == 0 {
3840
return nil, errors.Errorf("empty identity")
3941
}
@@ -46,37 +48,41 @@ func (c *Deserializer) DeserializeAgainstNymEID(identity []byte, checkValidity b
4648
return nil, errors.Errorf("unable to deserialize idemix identity: pseudonym's public key is empty")
4749
}
4850

51+
// match schema
52+
if serialized.Schema != d.Schema {
53+
return nil, errors.Errorf("unable to deserialize idemix identity: schema does not match [%s]!=[%s]", serialized.Schema, d.Schema)
54+
}
55+
4956
// Import NymPublicKey
50-
NymPublicKey, err := c.Csp.KeyImport(
57+
NymPublicKey, err := d.Csp.KeyImport(
5158
serialized.NymPublicKey,
5259
&bccsp.IdemixNymPublicKeyImportOpts{Temporary: true},
5360
)
5461
if err != nil {
5562
return nil, errors.WithMessage(err, "failed to import nym public key")
5663
}
5764

58-
idemix := c
65+
idemix := d
5966
if len(nymEID) != 0 {
6067
idemix = &Deserializer{
61-
Name: c.Name,
62-
Ipk: c.Ipk,
63-
Csp: c.Csp,
64-
IssuerPublicKey: c.IssuerPublicKey,
65-
RevocationPK: c.RevocationPK,
66-
Epoch: c.Epoch,
67-
VerType: c.VerType,
68+
Name: d.Name,
69+
Ipk: d.Ipk,
70+
Csp: d.Csp,
71+
IssuerPublicKey: d.IssuerPublicKey,
72+
RevocationPK: d.RevocationPK,
73+
Epoch: d.Epoch,
74+
VerType: d.VerType,
6875
NymEID: nymEID,
76+
SchemaManager: d.SchemaManager,
6977
}
7078
}
7179

72-
id, err := NewIdentity(idemix, NymPublicKey, serialized.Proof, c.VerType)
80+
id, err := NewIdentity(idemix, NymPublicKey, serialized.Proof, d.VerType, d.SchemaManager, d.Schema)
7381
if err != nil {
7482
return nil, errors.Wrap(err, "cannot deserialize")
7583
}
76-
if checkValidity {
77-
if err := id.Validate(); err != nil {
78-
return nil, errors.Wrap(err, "cannot deserialize, invalid identity")
79-
}
84+
if err := id.Validate(); err != nil {
85+
return nil, errors.Wrap(err, "cannot deserialize, invalid identity")
8086
}
8187

8288
return &DeserializedIdentity{
@@ -85,12 +91,14 @@ func (c *Deserializer) DeserializeAgainstNymEID(identity []byte, checkValidity b
8591
}, nil
8692
}
8793

88-
func (c *Deserializer) DeserializeAuditInfo(raw []byte) (*AuditInfo, error) {
94+
func (d *Deserializer) DeserializeAuditInfo(raw []byte) (*AuditInfo, error) {
8995
ai, err := DeserializeAuditInfo(raw)
9096
if err != nil {
9197
return nil, errors.Wrapf(err, "failed deserializing audit info [%s]", string(raw))
9298
}
93-
ai.Csp = c.Csp
94-
ai.IssuerPublicKey = c.IssuerPublicKey
99+
ai.Csp = d.Csp
100+
ai.IssuerPublicKey = d.IssuerPublicKey
101+
ai.SchemaManager = d.SchemaManager
102+
ai.Schema = d.Schema
95103
return ai, nil
96104
}

token/services/identity/idemix/crypto/id.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ type Identity struct {
2727
// AssociationProof contains cryptographic proof that this identity is valid.
2828
AssociationProof []byte
2929
VerificationType bccsp.VerificationType
30+
31+
// Schema related fields
32+
SchemaManager SchemaManager
33+
Schema Schema
3034
}
3135

32-
func NewIdentity(idemix *Deserializer, nymPublicKey bccsp.Key, proof []byte, verificationType bccsp.VerificationType) (*Identity, error) {
33-
id := &Identity{}
34-
id.Idemix = idemix
35-
id.NymPublicKey = nymPublicKey
36-
id.AssociationProof = proof
37-
id.VerificationType = verificationType
36+
func NewIdentity(idemix *Deserializer, nymPublicKey bccsp.Key, proof []byte, verificationType bccsp.VerificationType, schemaManager SchemaManager, schema Schema) (*Identity, error) {
37+
id := &Identity{
38+
Idemix: idemix,
39+
NymPublicKey: nymPublicKey,
40+
AssociationProof: proof,
41+
VerificationType: verificationType,
42+
SchemaManager: schemaManager,
43+
Schema: schema,
44+
}
3845
return id, nil
3946
}
4047

@@ -143,9 +150,11 @@ func (id *SigningIdentity) Sign(msg []byte) ([]byte, error) {
143150
}
144151

145152
type NymSignatureVerifier struct {
146-
CSP bccsp.BCCSP
147-
IPK bccsp.Key
148-
NymPK bccsp.Key
153+
CSP bccsp.BCCSP
154+
IPK bccsp.Key
155+
NymPK bccsp.Key
156+
SchemaManager SchemaManager
157+
Schema Schema
149158
}
150159

151160
func (v *NymSignatureVerifier) Verify(message, sigma []byte) error {

0 commit comments

Comments
 (0)