From 6e5f0b7f0232f8ac25bf3cfbf8fe72b758dadfb8 Mon Sep 17 00:00:00 2001 From: Alessandro Sorniotti Date: Tue, 7 Nov 2023 12:50:46 +0100 Subject: [PATCH] Remove hardcoded position `0` for user secret key This PR removes the hardcoded position 0 for the user secret key. Until now, the attribute position of the user secret key was 0. This is too restrictive since it forbids the usage of other schemas (e.g. JSON-LD) where the position of the attributes depends on the serialisation rules, and we cannot guarantee position 0. Signed-off-by: Alessandro Sorniotti --- bccsp/handlers/nymsigner.go | 3 +- bccsp/handlers/signer.go | 22 +- bccsp/schemes/aries/cred.go | 37 +- bccsp/schemes/aries/cred.pb.go | 81 +-- bccsp/schemes/aries/cred.proto | 1 + bccsp/schemes/aries/credrequest.go | 7 +- bccsp/schemes/aries/issuer.go | 3 - bccsp/schemes/aries/nymsigner.go | 12 +- bccsp/schemes/aries/nymsigner_test.go | 52 +- bccsp/schemes/aries/signer.go | 91 +-- bccsp/schemes/aries/signer_test.go | 543 ++++++++++++++++-- bccsp/schemes/aries/user.go | 7 +- bccsp/schemes/aries/util.go | 47 +- bccsp/schemes/dlog/bridge/bridge_test.go | 14 +- .../schemes/dlog/bridge/nymsignaturescheme.go | 2 +- bccsp/schemes/dlog/bridge/signaturescheme.go | 6 +- bccsp/smartcard_test.go | 2 +- bccsp/types/idemix.go | 12 +- bccsp/types/idemixopts.go | 6 + bccsp/types/mock/nymsignature_scheme.go | 18 +- bccsp/types/mock/signature_scheme.go | 118 ++-- go.mod | 4 + go.sum | 4 - 23 files changed, 808 insertions(+), 284 deletions(-) diff --git a/bccsp/handlers/nymsigner.go b/bccsp/handlers/nymsigner.go index 58b855e..80b0062 100644 --- a/bccsp/handlers/nymsigner.go +++ b/bccsp/handlers/nymsigner.go @@ -132,7 +132,8 @@ func (v *NymVerifier) Verify(k types.Key, signature, digest []byte, opts types.S ipk.pk, nymPublicKey.pk, signature, - digest) + digest, + signerOpts.SKIndex) if err != nil { return false, err } diff --git a/bccsp/handlers/signer.go b/bccsp/handlers/signer.go index bd0e76b..8b21f85 100644 --- a/bccsp/handlers/signer.go +++ b/bccsp/handlers/signer.go @@ -7,23 +7,22 @@ package handlers import ( "crypto/ecdsa" - "github.com/pkg/errors" "github.com/IBM/idemix/bccsp/types" - bccsp "github.com/IBM/idemix/bccsp/types" + "github.com/pkg/errors" ) type Signer struct { SignatureScheme types.SignatureScheme } -func (s *Signer) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) { +func (s *Signer) Sign(k types.Key, digest []byte, opts types.SignerOpts) ([]byte, error) { userSecretKey, ok := k.(*UserSecretKey) if !ok { return nil, errors.New("invalid key, expected *userSecretKey") } - signerOpts, ok := opts.(*bccsp.IdemixSignerOpts) + signerOpts, ok := opts.(*types.IdemixSignerOpts) if !ok { return nil, errors.New("invalid options, expected *IdemixSignerOpts") } @@ -73,13 +72,13 @@ type Verifier struct { SignatureScheme types.SignatureScheme } -func (v *Verifier) AuditNymEid(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) { +func (v *Verifier) AuditNymEid(k types.Key, signature, digest []byte, opts types.SignerOpts) (bool, error) { issuerPublicKey, ok := k.(*issuerPublicKey) if !ok { return false, errors.New("invalid key, expected *issuerPublicKey") } - signerOpts, ok := opts.(*bccsp.EidNymAuditOpts) + signerOpts, ok := opts.(*types.EidNymAuditOpts) if !ok { return false, errors.New("invalid options, expected *EidNymAuditOpts") } @@ -91,6 +90,7 @@ func (v *Verifier) AuditNymEid(k bccsp.Key, signature, digest []byte, opts bccsp err := v.SignatureScheme.AuditNymEid( issuerPublicKey.pk, signerOpts.EidIndex, + signerOpts.SKIndex, signature, signerOpts.EnrollmentID, signerOpts.RNymEid, @@ -103,13 +103,13 @@ func (v *Verifier) AuditNymEid(k bccsp.Key, signature, digest []byte, opts bccsp return true, nil } -func (v *Verifier) AuditNymRh(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) { +func (v *Verifier) AuditNymRh(k types.Key, signature, digest []byte, opts types.SignerOpts) (bool, error) { issuerPublicKey, ok := k.(*issuerPublicKey) if !ok { return false, errors.New("invalid key, expected *issuerPublicKey") } - signerOpts, ok := opts.(*bccsp.RhNymAuditOpts) + signerOpts, ok := opts.(*types.RhNymAuditOpts) if !ok { return false, errors.New("invalid options, expected *RhNymAuditOpts") } @@ -121,6 +121,7 @@ func (v *Verifier) AuditNymRh(k bccsp.Key, signature, digest []byte, opts bccsp. err := v.SignatureScheme.AuditNymRh( issuerPublicKey.pk, signerOpts.RhIndex, + signerOpts.SKIndex, signature, signerOpts.RevocationHandle, signerOpts.RNymRh, @@ -133,13 +134,13 @@ func (v *Verifier) AuditNymRh(k bccsp.Key, signature, digest []byte, opts bccsp. return true, nil } -func (v *Verifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) { +func (v *Verifier) Verify(k types.Key, signature, digest []byte, opts types.SignerOpts) (bool, error) { issuerPublicKey, ok := k.(*issuerPublicKey) if !ok { return false, errors.New("invalid key, expected *issuerPublicKey") } - signerOpts, ok := opts.(*bccsp.IdemixSignerOpts) + signerOpts, ok := opts.(*types.IdemixSignerOpts) if !ok { return false, errors.New("invalid options, expected *IdemixSignerOpts") } @@ -163,6 +164,7 @@ func (v *Verifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.Sign signerOpts.Attributes, signerOpts.RhIndex, signerOpts.EidIndex, + signerOpts.SKIndex, rPK, signerOpts.Epoch, signerOpts.VerificationType, diff --git a/bccsp/schemes/aries/cred.go b/bccsp/schemes/aries/cred.go index eede6f4..4960ec5 100644 --- a/bccsp/schemes/aries/cred.go +++ b/bccsp/schemes/aries/cred.go @@ -16,8 +16,9 @@ import ( ) type Cred struct { - Bls *bbs12381g2pub.BBSG2Pub - Curve *math.Curve + Bls *bbs12381g2pub.BBSG2Pub + Curve *math.Curve + UserSecretKeyIndex int } // Sign issues a new credential, which is the last step of the interactive issuance protocol @@ -34,7 +35,7 @@ func (c *Cred) Sign(key types.IssuerSecretKey, credentialRequest []byte, attribu return nil, fmt.Errorf("ParseBlindedMessages failed [%w]", err) } - msgsZr := attributesToSignatureMessage(nil, attributes, c.Curve) + msgsZr := attributesToSignatureMessage(attributes, c.Curve, c.UserSecretKeyIndex) sig, err := BlindSign(msgsZr, len(attributes)+1, blindedMsg.C, isk.SK.FR.Bytes(), c.Curve) if err != nil { @@ -78,15 +79,21 @@ func (c *Cred) Verify(sk *math.Zr, key types.IssuerPublicKey, credBytes []byte, return fmt.Errorf("ParseSignature failed [%w]", err) } - sm := make([]*bbs12381g2pub.SignatureMessage, len(credential.Attrs)+1) - sm[0] = &bbs12381g2pub.SignatureMessage{ - FR: sk, - Idx: 0, - } - for i, v := range credential.Attrs { - sm[i+1] = &bbs12381g2pub.SignatureMessage{ - FR: c.Curve.NewZrFromBytes(v), - Idx: i + 1, + i := 0 + sm := make([]*bbs12381g2pub.SignatureMessage, len(ipk.PKwG.H)) + for j := range ipk.PKwG.H { + if j == int(credential.SkPos) { + sm[j] = &bbs12381g2pub.SignatureMessage{ + FR: sk, + Idx: j, + } + + continue + } + + sm[j] = &bbs12381g2pub.SignatureMessage{ + FR: c.Curve.NewZrFromBytes(credential.Attrs[i]), + Idx: j, } switch attributes[i].Type { @@ -94,15 +101,17 @@ func (c *Cred) Verify(sk *math.Zr, key types.IssuerPublicKey, credBytes []byte, continue case types.IdemixBytesAttribute: fr := bbs12381g2pub.FrFromOKM(attributes[i].Value.([]byte), c.Curve) - if !fr.Equals(sm[i+1].FR) { + if !fr.Equals(sm[j].FR) { return errors.Errorf("credential does not contain the correct attribute value at position [%d]", i) } case types.IdemixIntAttribute: fr := c.Curve.NewZrFromInt(int64(attributes[i].Value.(int))) - if !fr.Equals(sm[i+1].FR) { + if !fr.Equals(sm[j].FR) { return errors.Errorf("credential does not contain the correct attribute value at position [%d]", i) } } + + i++ } return sigma.Verify(sm, ipk.PKwG) diff --git a/bccsp/schemes/aries/cred.pb.go b/bccsp/schemes/aries/cred.pb.go index c56551e..a84b5a3 100644 --- a/bccsp/schemes/aries/cred.pb.go +++ b/bccsp/schemes/aries/cred.pb.go @@ -24,6 +24,7 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type Credential struct { Cred []byte `protobuf:"bytes,1,opt,name=cred,proto3" json:"cred,omitempty"` Attrs [][]byte `protobuf:"bytes,2,rep,name=attrs,proto3" json:"attrs,omitempty"` + SkPos int32 `protobuf:"varint,3,opt,name=sk_pos,json=skPos,proto3" json:"sk_pos,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -68,6 +69,13 @@ func (m *Credential) GetAttrs() [][]byte { return nil } +func (m *Credential) GetSkPos() int32 { + if m != nil { + return m.SkPos + } + return 0 +} + // Signature is a PoK of a BBS+ signature (a credential) type Signature struct { MainSignature []byte `protobuf:"bytes,1,opt,name=main_signature,json=mainSignature,proto3" json:"main_signature,omitempty"` @@ -394,40 +402,41 @@ func init() { func init() { proto.RegisterFile("bccsp/schemes/aries/cred.proto", fileDescriptor_57701eac61520cf0) } var fileDescriptor_57701eac61520cf0 = []byte{ - // 553 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x41, 0x8b, 0xd3, 0x40, - 0x14, 0xc7, 0x49, 0xd3, 0xb4, 0xcd, 0x6b, 0xba, 0xba, 0x63, 0xc5, 0x2c, 0xca, 0x1a, 0x0a, 0x62, - 0xf5, 0xd0, 0x88, 0x82, 0xf7, 0x56, 0x17, 0x29, 0xcb, 0x2e, 0x21, 0x7b, 0x59, 0x44, 0x08, 0xd3, - 0x64, 0xb6, 0x1d, 0xda, 0x99, 0x09, 0x49, 0x2a, 0xcd, 0xd7, 0xf1, 0xe8, 0xe7, 0xf0, 0xe4, 0xc7, - 0xf0, 0xb8, 0x9f, 0x42, 0x66, 0x26, 0x35, 0x81, 0xd6, 0xdb, 0x9e, 0x32, 0xef, 0xff, 0x7b, 0xf3, - 0xef, 0xbc, 0xf7, 0x66, 0x0a, 0xe7, 0x8b, 0x38, 0xce, 0x53, 0x3f, 0x8f, 0x57, 0x84, 0x91, 0xdc, - 0xc7, 0x19, 0x25, 0xb9, 0x1f, 0x67, 0x24, 0x99, 0xa4, 0x99, 0x28, 0x04, 0xb2, 0x94, 0x32, 0xfa, - 0x08, 0xf0, 0x29, 0x23, 0x09, 0xe1, 0x05, 0xc5, 0x1b, 0x84, 0xa0, 0x2d, 0x53, 0x5c, 0xc3, 0x33, - 0xc6, 0x4e, 0xa8, 0xd6, 0x68, 0x08, 0x16, 0x2e, 0x8a, 0x2c, 0x77, 0x5b, 0x9e, 0x39, 0x76, 0x42, - 0x1d, 0x8c, 0xee, 0x4d, 0xb0, 0x6f, 0xe8, 0x92, 0xe3, 0x62, 0x9b, 0x11, 0xf4, 0x0a, 0x4e, 0x18, - 0xa6, 0x3c, 0xca, 0xf7, 0x4a, 0xe5, 0x30, 0x90, 0x6a, 0x9d, 0x36, 0x04, 0x8b, 0x0b, 0x1e, 0x13, - 0xb7, 0xa5, 0xa8, 0x0e, 0xd0, 0x63, 0x30, 0x79, 0xc9, 0x5c, 0x53, 0x69, 0x72, 0x89, 0x9e, 0x83, - 0xcd, 0x4b, 0x16, 0xa5, 0x99, 0x10, 0x77, 0x6e, 0x5b, 0xe9, 0x3d, 0x5e, 0xb2, 0x40, 0xc6, 0xe8, - 0x19, 0x74, 0x25, 0x24, 0x34, 0x71, 0x2d, 0x85, 0x3a, 0xbc, 0x64, 0x17, 0x34, 0x41, 0x23, 0x18, - 0x54, 0xa0, 0xda, 0xd9, 0x51, 0xb8, 0xaf, 0xb1, 0xde, 0x7c, 0x0e, 0xfd, 0x7d, 0x0e, 0x4d, 0x76, - 0x6e, 0xd7, 0x33, 0xc6, 0x56, 0x68, 0xeb, 0x8c, 0x79, 0xb2, 0x43, 0x4f, 0x41, 0xba, 0x45, 0xd9, - 0xca, 0xed, 0x55, 0x47, 0x2c, 0x59, 0xb8, 0x42, 0x1e, 0x38, 0x5a, 0xae, 0x9c, 0x6d, 0x05, 0x41, - 0x41, 0x6d, 0xfc, 0x02, 0xa0, 0xca, 0x90, 0xbe, 0xa0, 0x7c, 0x7b, 0x8a, 0x4b, 0xdb, 0x09, 0x3c, - 0xc9, 0xc8, 0x77, 0x11, 0xe3, 0x82, 0x0a, 0x1e, 0x91, 0x54, 0xc4, 0xab, 0x28, 0x5d, 0xbb, 0x7d, - 0x65, 0x73, 0x5a, 0xa3, 0x0b, 0x49, 0x82, 0x35, 0x7a, 0x0b, 0x0d, 0x31, 0x4a, 0xd7, 0xb2, 0xb1, - 0xae, 0xa3, 0xb2, 0x1f, 0xd5, 0x20, 0x58, 0xdf, 0xd0, 0xa5, 0x6c, 0xaa, 0x32, 0x74, 0x07, 0x9e, - 0x31, 0x36, 0x43, 0x1d, 0xa0, 0x4b, 0x18, 0x72, 0xc1, 0xa3, 0xa6, 0x8b, 0x3a, 0xf9, 0x89, 0x67, - 0x8c, 0xfb, 0xef, 0xcf, 0x26, 0x6a, 0xfa, 0x93, 0x6b, 0xc1, 0xc3, 0xda, 0x4e, 0x26, 0x84, 0x88, - 0x1f, 0x68, 0x23, 0x06, 0xe8, 0x30, 0x53, 0x0e, 0xbd, 0x61, 0x8f, 0x37, 0x4b, 0x35, 0x74, 0x2b, - 0x1c, 0xd4, 0xea, 0x74, 0xb3, 0x44, 0xef, 0xfe, 0x73, 0x12, 0x7d, 0x07, 0x8e, 0xfd, 0xdc, 0x2f, - 0x03, 0x5e, 0xd6, 0x97, 0xb2, 0xa6, 0x73, 0x7e, 0x27, 0x32, 0xa6, 0x96, 0x75, 0xd5, 0x46, 0xb3, - 0xea, 0x33, 0xe8, 0xfd, 0x6b, 0xae, 0xf6, 0xef, 0x92, 0xaa, 0xa5, 0x1e, 0x38, 0x7b, 0xa4, 0xba, - 0xa9, 0xaf, 0x1b, 0x54, 0x58, 0x36, 0xf2, 0xb0, 0x9e, 0xf6, 0xb1, 0x7a, 0x5e, 0x43, 0x63, 0x04, - 0x51, 0x82, 0x0b, 0x5c, 0xdd, 0xc3, 0xc6, 0xee, 0xcf, 0xb8, 0xc0, 0xa3, 0x4b, 0x70, 0xae, 0x4b, - 0xf6, 0x30, 0x8f, 0x64, 0xb6, 0x05, 0x3b, 0x16, 0x4c, 0x8f, 0x6d, 0x66, 0xcb, 0xee, 0x04, 0xf2, - 0x19, 0x07, 0xc6, 0xd7, 0x37, 0x4b, 0x5a, 0xac, 0xb6, 0x8b, 0x49, 0x2c, 0x98, 0x3f, 0x9f, 0x5d, - 0xf9, 0x34, 0x21, 0x8c, 0xee, 0xfc, 0x23, 0xcf, 0xff, 0x47, 0xcb, 0x9c, 0xde, 0xde, 0xfe, 0x6c, - 0x59, 0x53, 0x19, 0xfd, 0xae, 0xbe, 0x7f, 0x5a, 0xa7, 0xea, 0xfb, 0xed, 0x4b, 0x30, 0xbb, 0x22, - 0x05, 0x96, 0x15, 0xdd, 0x57, 0x6c, 0xd1, 0x51, 0x7f, 0x16, 0x1f, 0xfe, 0x06, 0x00, 0x00, 0xff, - 0xff, 0x2e, 0xc8, 0xaa, 0x1d, 0x4e, 0x04, 0x00, 0x00, + // 567 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xd1, 0x6e, 0xd3, 0x30, + 0x14, 0x86, 0x95, 0x66, 0xe9, 0x9a, 0xd3, 0x74, 0x30, 0x53, 0x44, 0x26, 0xd0, 0x88, 0x2a, 0x21, + 0x0a, 0x17, 0x0d, 0x82, 0x27, 0x68, 0x61, 0x42, 0xd5, 0xd4, 0x29, 0xca, 0x6e, 0x26, 0x84, 0x14, + 0xb9, 0x89, 0xd7, 0x5a, 0xa9, 0xed, 0x28, 0x49, 0x51, 0xf3, 0x3a, 0x5c, 0xf2, 0x1c, 0x5c, 0xf1, + 0x18, 0x5c, 0xee, 0x29, 0x90, 0xed, 0x94, 0x44, 0x6a, 0xb9, 0xe3, 0x2a, 0x3e, 0xe7, 0xfb, 0xfd, + 0xc7, 0xe7, 0xf8, 0x24, 0x70, 0xb9, 0x8c, 0xe3, 0x22, 0xf3, 0x8b, 0x78, 0x4d, 0x18, 0x29, 0x7c, + 0x9c, 0x53, 0x52, 0xf8, 0x71, 0x4e, 0x92, 0x49, 0x96, 0x8b, 0x52, 0x20, 0x4b, 0x65, 0x46, 0x0b, + 0x80, 0x8f, 0x39, 0x49, 0x08, 0x2f, 0x29, 0xde, 0x20, 0x04, 0x27, 0x52, 0xe2, 0x1a, 0x9e, 0x31, + 0x76, 0x42, 0xb5, 0x46, 0x43, 0xb0, 0x70, 0x59, 0xe6, 0x85, 0xdb, 0xf1, 0xcc, 0xb1, 0x13, 0xea, + 0x00, 0x3d, 0x85, 0x6e, 0x91, 0x46, 0x99, 0x28, 0x5c, 0xd3, 0x33, 0xc6, 0x56, 0x68, 0x15, 0x69, + 0x20, 0x8a, 0xd1, 0x83, 0x09, 0xf6, 0x2d, 0x5d, 0x71, 0x5c, 0x6e, 0x73, 0x82, 0x5e, 0xc1, 0x19, + 0xc3, 0x94, 0x47, 0xc5, 0x3e, 0x53, 0x1b, 0x0f, 0x64, 0xb6, 0x91, 0x0d, 0xc1, 0xe2, 0x82, 0xc7, + 0xc4, 0xed, 0x28, 0xaa, 0x03, 0xf4, 0x18, 0x4c, 0x5e, 0x31, 0x65, 0xef, 0x84, 0x72, 0x89, 0x9e, + 0x83, 0xcd, 0x2b, 0x16, 0x65, 0xb9, 0x10, 0xf7, 0xee, 0x89, 0xca, 0xf7, 0x78, 0xc5, 0x02, 0x19, + 0xa3, 0x67, 0x70, 0x2a, 0x21, 0xa1, 0x89, 0x6b, 0x29, 0xd4, 0xe5, 0x15, 0xbb, 0xa2, 0x09, 0x1a, + 0xc1, 0xa0, 0x06, 0xf5, 0xce, 0xae, 0xc2, 0x7d, 0x8d, 0xf5, 0xe6, 0x4b, 0xe8, 0xef, 0x35, 0x34, + 0xd9, 0xb9, 0xa7, 0xaa, 0x24, 0x5b, 0x2b, 0xe6, 0xc9, 0x4e, 0x56, 0x2b, 0x79, 0xbe, 0x76, 0x7b, + 0xf5, 0x11, 0x2b, 0x16, 0xae, 0x91, 0x07, 0x8e, 0x4e, 0xd7, 0xce, 0xb6, 0x82, 0xa0, 0xa0, 0x36, + 0x7e, 0x01, 0x50, 0x2b, 0xa4, 0x2f, 0x28, 0xdf, 0x9e, 0xe2, 0xd2, 0x76, 0x02, 0x4f, 0x72, 0xf2, + 0x4d, 0xc4, 0xb8, 0xa4, 0x82, 0x47, 0x24, 0x13, 0xf1, 0x3a, 0xca, 0x52, 0xb7, 0xaf, 0x6c, 0xce, + 0x1b, 0x74, 0x25, 0x49, 0x90, 0xa2, 0xb7, 0xd0, 0x4a, 0x46, 0x59, 0x2a, 0x1b, 0xeb, 0x3a, 0x4a, + 0xfd, 0xa8, 0x01, 0x41, 0x7a, 0x4b, 0x57, 0xb2, 0xa9, 0xca, 0xd0, 0x1d, 0x78, 0xc6, 0xd8, 0x0c, + 0x75, 0x80, 0xae, 0x61, 0xc8, 0x05, 0x8f, 0xda, 0x2e, 0xea, 0xe4, 0x67, 0x9e, 0x31, 0xee, 0xbf, + 0xbf, 0x98, 0xa8, 0xa1, 0x98, 0xdc, 0x08, 0x1e, 0x36, 0x76, 0x52, 0x10, 0x22, 0x7e, 0x90, 0x1b, + 0x31, 0x40, 0x87, 0x4a, 0x79, 0xe9, 0x2d, 0x7b, 0xbc, 0x59, 0xa9, 0x4b, 0xb7, 0xc2, 0x41, 0x93, + 0x9d, 0x6e, 0x56, 0xe8, 0xdd, 0x3f, 0x4e, 0xa2, 0x67, 0xe0, 0xd8, 0xeb, 0x7e, 0x1a, 0xf0, 0xb2, + 0x99, 0xd5, 0x86, 0xce, 0xf9, 0xbd, 0xc8, 0x99, 0x5a, 0x36, 0x55, 0x1b, 0xed, 0xaa, 0x2f, 0xa0, + 0xf7, 0xb7, 0xb9, 0xda, 0xff, 0x94, 0xd4, 0x2d, 0xf5, 0xc0, 0xd9, 0x23, 0xd5, 0x4d, 0x3d, 0x6e, + 0x50, 0x63, 0xd9, 0xc8, 0xc3, 0x7a, 0x4e, 0x8e, 0xd5, 0xf3, 0x1a, 0x5a, 0x57, 0x10, 0x25, 0xb8, + 0xc4, 0xf5, 0x1c, 0xb6, 0x76, 0x7f, 0xc2, 0x25, 0x1e, 0x5d, 0x83, 0x73, 0x53, 0xb1, 0xff, 0xf3, + 0x91, 0xcc, 0xb6, 0x60, 0xc7, 0x82, 0xe9, 0x6b, 0x9b, 0xd9, 0xb2, 0x3b, 0x81, 0xfc, 0xba, 0x03, + 0xe3, 0xcb, 0x9b, 0x15, 0x2d, 0xd7, 0xdb, 0xe5, 0x24, 0x16, 0xcc, 0x9f, 0xcf, 0x16, 0x3e, 0x4d, + 0x08, 0xa3, 0x3b, 0xff, 0xc8, 0x5f, 0xe1, 0x7b, 0xc7, 0x9c, 0xde, 0xdd, 0xfd, 0xe8, 0x58, 0x53, + 0x19, 0xfd, 0xaa, 0x9f, 0xbf, 0x3b, 0xe7, 0xea, 0xf9, 0xf5, 0x73, 0x30, 0x5b, 0x90, 0x12, 0xcb, + 0x8a, 0x1e, 0x6a, 0xb6, 0xec, 0xaa, 0x7f, 0xc8, 0x87, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd0, + 0x52, 0x52, 0xca, 0x65, 0x04, 0x00, 0x00, } diff --git a/bccsp/schemes/aries/cred.proto b/bccsp/schemes/aries/cred.proto index 17a120f..ecd9877 100644 --- a/bccsp/schemes/aries/cred.proto +++ b/bccsp/schemes/aries/cred.proto @@ -14,6 +14,7 @@ package aries; message Credential { bytes cred = 1; repeated bytes attrs = 2; + int32 sk_pos = 3; } // Signature is a PoK of a BBS+ signature (a credential) diff --git a/bccsp/schemes/aries/credrequest.go b/bccsp/schemes/aries/credrequest.go index 7aad806..89eb42a 100644 --- a/bccsp/schemes/aries/credrequest.go +++ b/bccsp/schemes/aries/credrequest.go @@ -15,7 +15,8 @@ import ( ) type CredRequest struct { - Curve *math.Curve + Curve *math.Curve + UserSecretKeyIndex int } // Sign creates a new Credential Request, the first message of the interactive credential issuance protocol @@ -27,7 +28,7 @@ func (c *CredRequest) Blind(sk *math.Zr, key types.IssuerPublicKey, nonce []byte } zrs := make([]*math.Zr, ipk.N+1) - zrs[UserSecretKeyIndex] = sk + zrs[c.UserSecretKeyIndex] = sk blindedMsg, err := BlindMessagesZr(zrs, ipk.PK, 1, nonce, c.Curve) if err != nil { @@ -45,7 +46,7 @@ func (c *CredRequest) BlindVerify(credRequest []byte, key types.IssuerPublicKey, } bitmap := make([]bool, ipk.N+1) - bitmap[UserSecretKeyIndex] = true + bitmap[c.UserSecretKeyIndex] = true blindedMsg, err := ParseBlindedMessages(credRequest, c.Curve) if err != nil { diff --git a/bccsp/schemes/aries/issuer.go b/bccsp/schemes/aries/issuer.go index 9f727d3..8d80f3d 100644 --- a/bccsp/schemes/aries/issuer.go +++ b/bccsp/schemes/aries/issuer.go @@ -18,9 +18,6 @@ import ( // TODO: // * expose curve from aries so we can use always that curve -// UserSecretKeyIndex is the index of `sk` among the attributes -const UserSecretKeyIndex = 0 - // IssuerPublicKey is the issuer public key type IssuerPublicKey struct { PK *bbs12381g2pub.PublicKey diff --git a/bccsp/schemes/aries/nymsigner.go b/bccsp/schemes/aries/nymsigner.go index 97b74cd..216fd58 100644 --- a/bccsp/schemes/aries/nymsigner.go +++ b/bccsp/schemes/aries/nymsigner.go @@ -18,8 +18,9 @@ import ( const nymSigLabel = "nym-sig" type NymSigner struct { - Curve *math.Curve - Rng io.Reader + Curve *math.Curve + Rng io.Reader + UserSecretKeyIndex int } // Sign creates a new idemix pseudonym signature @@ -39,7 +40,7 @@ func (s *NymSigner) Sign( commit := bbs12381g2pub.NewBBSLib(s.Curve).NewProverCommittingG1() commit.Commit(ipk.PKwG.H0) - commit.Commit(ipk.PKwG.H[0]) + commit.Commit(ipk.PKwG.H[s.UserSecretKeyIndex]) commitNym := commit.Finish() challengeBytes := []byte(nymSigLabel) @@ -68,6 +69,7 @@ func (s *NymSigner) Verify( key types.IssuerPublicKey, Nym *math.G1, sigBytes, digest []byte, + skIndex int, ) error { ipk, ok := key.(*IssuerPublicKey) if !ok { @@ -88,7 +90,7 @@ func (s *NymSigner) Verify( challengeBytes := []byte(nymSigLabel) challengeBytes = append(challengeBytes, Nym.Bytes()...) challengeBytes = append(challengeBytes, ipk.PKwG.H0.Bytes()...) - challengeBytes = append(challengeBytes, ipk.PKwG.H[0].Bytes()...) + challengeBytes = append(challengeBytes, ipk.PKwG.H[skIndex].Bytes()...) challengeBytes = append(challengeBytes, nymProof.Commitment.Bytes()...) challengeBytes = append(challengeBytes, digest...) @@ -98,5 +100,5 @@ func (s *NymSigner) Verify( challengeBytes = append(challengeBytes, sig.Nonce...) proofChallenge = bbs12381g2pub.FrFromOKM(challengeBytes, s.Curve) - return nymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[0]}, Nym, proofChallenge) + return nymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[skIndex]}, Nym, proofChallenge) } diff --git a/bccsp/schemes/aries/nymsigner_test.go b/bccsp/schemes/aries/nymsigner_test.go index 930d7d9..709f32b 100644 --- a/bccsp/schemes/aries/nymsigner_test.go +++ b/bccsp/schemes/aries/nymsigner_test.go @@ -43,38 +43,42 @@ func TestNymSigner(t *testing.T) { sk := curve.NewRandomZr(rand) rNym := curve.NewRandomZr(rand) - cb := bbs12381g2pub.NewCommitmentBuilder(2) - cb.Add(ipk.PKwG.H0, rNym) - cb.Add(ipk.PKwG.H[aries.UserSecretKeyIndex], sk) - nym := cb.Build() + for skPos := range attrs { + signer.UserSecretKeyIndex = skPos - sig, err := signer.Sign(sk, nym, rNym, _ipk, []byte("ciao")) - assert.NoError(t, err) + cb := bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.PKwG.H0, rNym) + cb.Add(ipk.PKwG.H[skPos], sk) + nym := cb.Build() - err = signer.Verify(_ipk, nym, sig, []byte("ciao")) - assert.NoError(t, err) + sig, err := signer.Sign(sk, nym, rNym, _ipk, []byte("ciao")) + assert.NoError(t, err) - sig, err = signer.Sign(sk, nym, curve.NewRandomZr(rand), _ipk, []byte("ciao")) - assert.NoError(t, err) + err = signer.Verify(_ipk, nym, sig, []byte("ciao"), skPos) + assert.NoError(t, err) - err = signer.Verify(_ipk, nym, sig, []byte("ciao")) - assert.EqualError(t, err, "contribution is not zero") + sig, err = signer.Sign(sk, nym, curve.NewRandomZr(rand), _ipk, []byte("ciao")) + assert.NoError(t, err) - sig, err = signer.Sign(curve.NewRandomZr(rand), nym, rNym, _ipk, []byte("ciao")) - assert.NoError(t, err) + err = signer.Verify(_ipk, nym, sig, []byte("ciao"), skPos) + assert.EqualError(t, err, "contribution is not zero") - err = signer.Verify(_ipk, nym, sig, []byte("ciao")) - assert.EqualError(t, err, "contribution is not zero") + sig, err = signer.Sign(curve.NewRandomZr(rand), nym, rNym, _ipk, []byte("ciao")) + assert.NoError(t, err) - sig, err = signer.Sign(sk, curve.GenG1.Mul(curve.NewRandomZr(rand)), rNym, _ipk, []byte("ciao")) - assert.NoError(t, err) + err = signer.Verify(_ipk, nym, sig, []byte("ciao"), skPos) + assert.EqualError(t, err, "contribution is not zero") - err = signer.Verify(_ipk, nym, sig, []byte("ciao")) - assert.EqualError(t, err, "contribution is not zero") + sig, err = signer.Sign(sk, curve.GenG1.Mul(curve.NewRandomZr(rand)), rNym, _ipk, []byte("ciao")) + assert.NoError(t, err) - sig, err = signer.Sign(sk, nym, rNym, _ipk, []byte("ciao")) - assert.NoError(t, err) + err = signer.Verify(_ipk, nym, sig, []byte("ciao"), skPos) + assert.EqualError(t, err, "contribution is not zero") - err = signer.Verify(_ipk, curve.GenG1.Mul(curve.NewRandomZr(rand)), sig, []byte("ciao")) - assert.EqualError(t, err, "contribution is not zero") + sig, err = signer.Sign(sk, nym, rNym, _ipk, []byte("ciao")) + assert.NoError(t, err) + + err = signer.Verify(_ipk, curve.GenG1.Mul(curve.NewRandomZr(rand)), sig, []byte("ciao"), skPos) + assert.EqualError(t, err, "contribution is not zero") + } } diff --git a/bccsp/schemes/aries/signer.go b/bccsp/schemes/aries/signer.go index e32ea2d..4236510 100644 --- a/bccsp/schemes/aries/signer.go +++ b/bccsp/schemes/aries/signer.go @@ -33,7 +33,7 @@ type Signer struct { } func (s *Signer) getPoKOfSignature( - credBytes []byte, + credential *Credential, attributes []types.IdemixAttribute, sk *math.Zr, ipk *bbs12381g2pub.PublicKeyWithGenerators, @@ -41,12 +41,6 @@ func (s *Signer) getPoKOfSignature( Nym *math.G1, RNym *math.Zr, ) (*bbs12381g2pub.PoKOfSignature, []*bbs12381g2pub.SignatureMessage, error) { - credential := &Credential{} - err := proto.Unmarshal(credBytes, credential) - if err != nil { - return nil, nil, fmt.Errorf("proto.Unmarshal failed [%w]", err) - } - signature, err := bbs12381g2pub.NewBBSLib(s.Curve).ParseSignature(credential.Cred) if err != nil { return nil, nil, fmt.Errorf("parse signature: %w", err) @@ -66,10 +60,10 @@ func (s *Signer) getPoKOfSignature( // and so we cannot prove their knowledge. We therefore pass them in to // `NewPoKOfSignatureExt` as their as, since thier correctiness has already // been proven by the smartcard in a separate proof. - messagesFr = append([]*bbs12381g2pub.SignatureMessage{{}}, messagesFr...) C := Nym.Copy() C.Sub(ipk.H0.Mul(RNym)) - pokOS, err = bbs12381g2pub.NewBBSLib(s.Curve).NewPoKOfSignatureExt(signature, messagesFr[1:], revealedAttributesIndexNoSk(attributes), ipk, Nym, RNym, C) + messagesFrNoSk := append(append([]*bbs12381g2pub.SignatureMessage{}, messagesFr[:credential.SkPos]...), messagesFr[credential.SkPos+1:]...) + pokOS, err = bbs12381g2pub.NewBBSLib(s.Curve).NewPoKOfSignatureExt(signature, messagesFrNoSk, revealedAttributesIndexNoSk(attributes), ipk, Nym, RNym, C) } else { pokOS, err = bbs12381g2pub.NewBBSLib(s.Curve).NewPoKOfSignatureExt(signature, messagesFr, revealedAttributesIndex(attributes), ipk, nil, nil, nil) } @@ -197,6 +191,7 @@ func (s *Signer) getCommitNym( ipk *IssuerPublicKey, pokSignature *bbs12381g2pub.PoKOfSignature, sigType types.SignatureType, + userSecretKeyIndex int, ) *bbs12381g2pub.ProverCommittedG1 { if sigType == types.Smartcard { @@ -207,14 +202,14 @@ func (s *Signer) getCommitNym( commit := bbs12381g2pub.NewBBSLib(s.Curve).NewProverCommittingG1() commit.Commit(ipk.PKwG.H0) - commit.Commit(ipk.PKwG.H[UserSecretKeyIndex]) + commit.Commit(ipk.PKwG.H[userSecretKeyIndex]) // we force the same blinding factor used in PokVC2 to prove equality. // 1) commit.BlindingFactors[1] is the blinding factor for the sk in the Nym // H0^{RNym} \cdot H[0]^{sk} // 2) pokSignature.PokVC2.BlindingFactors[2] is the blinding factor for the sk in // D * (-r3~) + Q_1 * s~ + H_j1 * m~_j1 + ... + H_jU * m~_jU // index 0 is for D, index 1 is for s~ and index 2 is for the first message (which is the sk) - commit.BlindingFactors[AttributeIndexInNym] = pokSignature.PokVC2.BlindingFactors[IndexOffsetVC2Attributes+UserSecretKeyIndex] + commit.BlindingFactors[AttributeIndexInNym] = pokSignature.PokVC2.BlindingFactors[IndexOffsetVC2Attributes+userSecretKeyIndex] return commit.Finish() } @@ -382,7 +377,13 @@ func (s *Signer) Sign( // Generate main PoK (1st move) // ////////////////////////////////// - pokSignature, messagesFr, err := s.getPoKOfSignature(credBytes, attributes, sk, ipk.PKwG, sigType, Nym, RNym) + credential := &Credential{} + err = proto.Unmarshal(credBytes, credential) + if err != nil { + return nil, nil, fmt.Errorf("proto.Unmarshal failed [%w]", err) + } + + pokSignature, messagesFr, err := s.getPoKOfSignature(credential, attributes, sk, ipk.PKwG, sigType, Nym, RNym) if err != nil { return nil, nil, err } @@ -391,14 +392,16 @@ func (s *Signer) Sign( // Handling Nym // ////////////////// - commitNym := s.getCommitNym(ipk, pokSignature, sigType) + commitNym := s.getCommitNym(ipk, pokSignature, sigType, int(credential.SkPos)) /////////////////// // Handle NymEID // /////////////////// - // increment the index to cater for the first hidden index for `sk` - eidIndex++ + // increment the index to cater for the index for `sk` + if eidIndex >= int(credential.SkPos) { + eidIndex++ + } nymEid, err := s.getAttributeCommitment(ipk, pokSignature, messagesFr[eidIndex].FR, eidIndex, nymEidAttrCommitmentEnabled(sigType), safeNymEidAuditDataAccess(metadata)) if err != nil { @@ -409,8 +412,10 @@ func (s *Signer) Sign( // Handle RhNym // /////////////////// - // increment the index to cater for the first hidden index for `sk` - rhIndex++ + // increment the index to cater for the index for `sk` + if rhIndex >= int(credential.SkPos) { + rhIndex++ + } rhNym, err := s.getAttributeCommitment(ipk, pokSignature, messagesFr[rhIndex].FR, rhIndex, rhAttrCommitmentEnabled(sigType), safeRhNymAuditDataAccess(metadata)) if err != nil { @@ -488,7 +493,7 @@ func (s *Signer) Verify( key types.IssuerPublicKey, signature, msg []byte, attributes []types.IdemixAttribute, - rhIndex, eidIndex int, + rhIndex, eidIndex, skIndex int, _ *ecdsa.PublicKey, _ int, verType types.VerificationType, @@ -499,6 +504,8 @@ func (s *Signer) Verify( return fmt.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk) } + lib := bbs12381g2pub.NewBBSLib(s.Curve) + sig := &Signature{} err := proto.Unmarshal(signature, sig) if err != nil { @@ -535,14 +542,14 @@ func (s *Signer) Verify( verifyRHNym := (verType == types.BestEffort && sig.NymRh != nil) || verType == types.ExpectEidNymRhNym verifyEIDNym := (verType == types.BestEffort && sig.NymEid != nil) || verType == types.ExpectEidNym || verType == types.ExpectEidNymRhNym || verType == types.ExpectSmartcard || verifyRHNym - messages := attributesToSignatureMessage(nil, attributes, s.Curve) + messages := attributesToSignatureMessage(attributes, s.Curve, skIndex) payload, err := bbs12381g2pub.ParsePoKPayload(sig.MainSignature) if err != nil { return fmt.Errorf("parse signature proof: %w", err) } - signatureProof, err := bbs12381g2pub.NewBBSLib(s.Curve).ParseSignatureProof(sig.MainSignature[payload.LenInBytes():]) + signatureProof, err := lib.ParseSignatureProof(sig.MainSignature[payload.LenInBytes():]) if err != nil { return fmt.Errorf("parse signature proof: %w", err) } @@ -558,7 +565,7 @@ func (s *Signer) Verify( var nymProof *bbs12381g2pub.ProofG1 if verType != types.ExpectSmartcard { - nymProof, err = bbs12381g2pub.NewBBSLib(s.Curve).ParseProofG1(sig.NymProof) + nymProof, err = lib.ParseProofG1(sig.NymProof) if err != nil { return fmt.Errorf("parse nym proof: %w", err) } @@ -567,7 +574,7 @@ func (s *Signer) Verify( var nymEidProof *bbs12381g2pub.ProofG1 var NymEid *math.G1 if verifyEIDNym { - nymEidProof, err = bbs12381g2pub.NewBBSLib(s.Curve).ParseProofG1(sig.NymEidProof) + nymEidProof, err = lib.ParseProofG1(sig.NymEidProof) if err != nil { return fmt.Errorf("parse nym proof: %w", err) } @@ -581,7 +588,7 @@ func (s *Signer) Verify( var rhNymProof *bbs12381g2pub.ProofG1 var RhNym *math.G1 if verifyRHNym { - rhNymProof, err = bbs12381g2pub.NewBBSLib(s.Curve).ParseProofG1(sig.NymRhProof) + rhNymProof, err = lib.ParseProofG1(sig.NymRhProof) if err != nil { return fmt.Errorf("parse rh proof: %w", err) } @@ -651,10 +658,20 @@ func (s *Signer) Verify( // Verify responses // ////////////////////// + // increment the index to cater for the index for `sk` + if eidIndex >= skIndex { + eidIndex++ + } + + // increment the index to cater for the index for `sk` + if rhIndex >= skIndex { + rhIndex++ + } + // audit eid nym if data provided and verification requested if (verifyEIDNym || verifyRHNym) && meta != nil { if meta.EidNymAuditData != nil { - ne := ipk.PKwG.H[eidIndex+1].Mul2( + ne := ipk.PKwG.H[eidIndex].Mul2( meta.EidNymAuditData.Attr, ipk.PKwG.H0, meta.EidNymAuditData.Rand) @@ -681,7 +698,7 @@ func (s *Signer) Verify( // audit rh nym if data provided and verification requested if verifyRHNym && meta != nil { if meta.RhNymAuditData != nil { - rn := ipk.PKwG.H[rhIndex+1].Mul2( + rn := ipk.PKwG.H[rhIndex].Mul2( meta.RhNymAuditData.Attr, ipk.PKwG.H0, meta.RhNymAuditData.Rand, ) @@ -708,12 +725,12 @@ func (s *Signer) Verify( if verType != types.ExpectSmartcard { // verify that `sk` in the Nym is the same as the one in the signature - if !nymProof.Responses[AttributeIndexInNym].Equals(signatureProof.ProofVC2.Responses[IndexOffsetVC2Attributes+UserSecretKeyIndex]) { + if !nymProof.Responses[AttributeIndexInNym].Equals(signatureProof.ProofVC2.Responses[IndexOffsetVC2Attributes+skIndex]) { return fmt.Errorf("failed equality proof for sk") } // verify the proof of knowledge of the Nym - err = nymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[UserSecretKeyIndex]}, Nym, proofChallenge) + err = nymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[skIndex]}, Nym, proofChallenge) if err != nil { return fmt.Errorf("verify nym proof: %w", err) } @@ -726,7 +743,7 @@ func (s *Signer) Verify( } // verify the proof of knowledge of the Nym - err = nymEidProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[eidIndex+1]}, NymEid, proofChallenge) + err = nymEidProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[eidIndex]}, NymEid, proofChallenge) if err != nil { return fmt.Errorf("verify nym eid proof: %w", err) } @@ -739,7 +756,7 @@ func (s *Signer) Verify( } // verify the proof of knowledge of the Rh - err = rhNymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[rhIndex+1]}, RhNym, proofChallenge) + err = rhNymProof.Verify([]*math.G1{ipk.PKwG.H0, ipk.PKwG.H[rhIndex]}, RhNym, proofChallenge) if err != nil { return fmt.Errorf("verify nym eid proof: %w", err) } @@ -756,7 +773,7 @@ func (s *Signer) Verify( // AuditNymEid permits the auditing of the nym eid generated by a signer func (s *Signer) AuditNymEid( key types.IssuerPublicKey, - eidIndex int, + eidIndex, skIndex int, signature []byte, enrollmentID string, RNymEid *math.Zr, @@ -794,7 +811,11 @@ func (s *Signer) AuditNymEid( eidAttr := bbs12381g2pub.FrFromOKM([]byte(enrollmentID), s.Curve) - ne := ipk.PKwG.H[eidIndex+1].Mul2(eidAttr, ipk.PKwG.H0, RNymEid) + if eidIndex >= skIndex { + eidIndex++ + } + + ne := ipk.PKwG.H[eidIndex].Mul2(eidAttr, ipk.PKwG.H0, RNymEid) if !ne.Equals(NymEid) { return fmt.Errorf("eid nym does not match") @@ -806,7 +827,7 @@ func (s *Signer) AuditNymEid( // AuditNymRh permits the auditing of the nym rh generated by a signer func (s *Signer) AuditNymRh( key types.IssuerPublicKey, - rhIndex int, + rhIndex, skIndex int, signature []byte, revocationHandle string, RNymRh *math.Zr, @@ -842,7 +863,11 @@ func (s *Signer) AuditNymRh( rhAttr := bbs12381g2pub.FrFromOKM([]byte(revocationHandle), s.Curve) - nr := ipk.PKwG.H[rhIndex+1].Mul2(rhAttr, ipk.PKwG.H0, RNymRh) + if rhIndex >= skIndex { + rhIndex++ + } + + nr := ipk.PKwG.H[rhIndex].Mul2(rhAttr, ipk.PKwG.H0, RNymRh) if !nr.Equals(RhNym) { return fmt.Errorf("rh nym does not match") diff --git a/bccsp/schemes/aries/signer_test.go b/bccsp/schemes/aries/signer_test.go index 9fe8b59..80879c1 100644 --- a/bccsp/schemes/aries/signer_test.go +++ b/bccsp/schemes/aries/signer_test.go @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0 package aries_test import ( + "encoding/base64" + "encoding/hex" "os" "testing" @@ -146,7 +148,7 @@ func TestSmartcardSigner(t *testing.T) { sig, _, err := signer.Sign(credBytes, nil, B, r, isk.Public(), idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Smartcard, nil) assert.NoError(t, err) - err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectSmartcard, nil) + err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectSmartcard, nil) assert.NoError(t, err) idemixAttrs = []types.IdemixAttribute{ @@ -168,7 +170,7 @@ func TestSmartcardSigner(t *testing.T) { sig, _, err = signer.Sign(credBytes, nil, B, r, isk.Public(), idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Smartcard, nil) assert.NoError(t, err) - err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectSmartcard, nil) + err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectSmartcard, nil) assert.NoError(t, err) idemixAttrs = []types.IdemixAttribute{ @@ -190,7 +192,7 @@ func TestSmartcardSigner(t *testing.T) { sig, _, err = signer.Sign(credBytes, nil, B, r, isk.Public(), idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Smartcard, nil) assert.NoError(t, err) - err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectSmartcard, nil) + err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectSmartcard, nil) assert.NoError(t, err) idemixAttrs = []types.IdemixAttribute{ @@ -211,7 +213,7 @@ func TestSmartcardSigner(t *testing.T) { sig, _, err = signer.Sign(credBytes, nil, B, r, isk.Public(), idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Smartcard, nil) assert.NoError(t, err) - err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectSmartcard, nil) + err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectSmartcard, nil) assert.NoError(t, err) /**************************************************/ @@ -233,7 +235,7 @@ func TestSmartcardSigner(t *testing.T) { sig, _, err = signer.Sign(credBytes, nil, B, r, isk.Public(), idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Smartcard, meta) assert.NoError(t, err) - err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectSmartcard, meta) + err = signer.Verify(isk.Public(), sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectSmartcard, meta) assert.NoError(t, err) } @@ -326,7 +328,7 @@ func TestSmartcardSigner1(t *testing.T) { { Type: types.IdemixHiddenAttribute, }, - }, 3, 2, nil, -1, types.ExpectSmartcard, &types.IdemixSignerMetadata{EidNym: NymEid.Bytes()}) + }, 3, 2, 0, nil, -1, types.ExpectSmartcard, &types.IdemixSignerMetadata{EidNym: NymEid.Bytes()}) assert.NoError(t, err) } @@ -396,6 +398,469 @@ func idemixScSign( return sig, nil } +func TestW3CCred(t *testing.T) { + curve := math.Curves[math.BLS12_381_BBS] + + rand, err := curve.Rand() + assert.NoError(t, err) + + pkHex := `87fae47132975f345b38fafd53149f7a009b89dd94fdc54d5d051a29e185ed4870acc2453fbd2e307d1543dfb7fbfdb30cf0008df96c75e2e43975b7f92864b4bc6e3f2f1495748d80a36691f6feaeb8fe151c1bb35de9bff5ac21ff9e57aebe` + sigBase64 := "tQ4rHLBIh7a9dk5MVoly8ccb80pGeoEqybhYnYZO8VmguaFDyuCN7rFdBPCVs1/SYUHlKfzccE4m7waZyoLEkBLFiK2g54Q2i+CdtYBgDdkUDsoULSBMcH1MwGHwdjfXpldFNFrHFx/IAvLVniyeMQ==" + + messagesBytes := [][]byte{ + []byte(`_:c14n0 "2023-11-03T11:12:17Z"^^ .`), + []byte(`_:c14n0 .`), + []byte(`_:c14n0 .`), + []byte(`_:c14n0 .`), + []byte(` _:c14n0 .`), + []byte(` "1990-11-22"^^ .`), + []byte(` "Bowen" .`), + []byte(` "Male" .`), + []byte(` "Jace" .`), + []byte(` .`), + []byte(` .`), + []byte(` .`), + []byte(` "Bahamas" .`), + []byte(` "C09" .`), + []byte(` "223-45-198" .`), + []byte(` "2015-01-01"^^ .`), + []byte(` "{\"hash\":\"de701215430a0c4f940ffe830efd27f54cae0d9655d78dc3849272e7641c05eedd066588345caf9d4181d9f325e73a9950a967d6fe766a4a62e02876e73255ad\",\"key\":\"aab053a5e11e3360679ce1a42c7733063843854a1002c19186743d7432a2e467\",\"link\":\"https://dev.lcn-cluster-dev-qa-app-583c1d2c1a459ad4539801325cd4ba78-0000.us-south.containers.appdomain.cloud/api/public/v1/object/70a62792-eb95-4491-a77f-e53dde8034fb\"}"^^ .`), + []byte(` "Permanent Resident Card" .`), + []byte(` .`), + []byte(` .`), + []byte(` .`), + []byte(` "2029-12-03T12:19:52Z"^^ .`), + []byte(` "2019-12-03T12:19:52Z"^^ .`), + []byte(` .`), + []byte(`_:c14n0 "chgA6VtGQeRd/0rf1P6fCFm8t7ZU1Q8eMPM/+E9gsw8=" .`), + []byte(`_:c14n0 "mytopos-mychannel-token-chaincode.example.com" .`), + []byte(`_:c14n0 "2"^^ .`), + []byte(`_:c14n0 "alice.remote" .`), + []byte(`_:c14n0 "111" .`), + } + + pkBytes, err := hex.DecodeString(pkHex) + assert.NoError(t, err) + sigBytes, err := base64.StdEncoding.DecodeString(sigBase64) + assert.NoError(t, err) + + bls := bbs12381g2pub.New(math.Curves[math.BLS12_381_BBS]) + + err = bls.Verify(messagesBytes, sigBytes, pkBytes) + assert.NoError(t, err) + + attributeNames := []string{ + "_:c14n0 ", + "_:c14n0 ", + } + + attributes := make([][]byte, len(attributeNames)) + for i, msg := range messagesBytes[1:] { + attributes[i] = bbs12381g2pub.FrFromOKM(msg, curve).Bytes() + } + + sk := bbs12381g2pub.FrFromOKM(messagesBytes[0], curve) + + cred := &aries.Credential{ + Cred: sigBytes, + Attrs: attributes, + } + credBytes, err := proto.Marshal(cred) + assert.NoError(t, err) + + credProto := &aries.Cred{ + Bls: bbs12381g2pub.New(curve), + Curve: curve, + } + + issuerProto := &aries.Issuer{curve} + + ipk, err := issuerProto.NewPublicKeyFromBytes(pkBytes, attributeNames) + assert.NoError(t, err) + + idemixAttrs := []types.IdemixAttribute{} + for _, msg := range messagesBytes[1:] { + idemixAttrs = append(idemixAttrs, types.IdemixAttribute{ + Type: types.IdemixBytesAttribute, + Value: msg, + }) + } + + err = credProto.Verify(sk, ipk, credBytes, idemixAttrs) + assert.NoError(t, err) + + signer := &aries.Signer{ + Curve: curve, + Rng: rand, + } + + userProto := &aries.User{ + Curve: curve, + Rng: rand, + } + + for i := range messagesBytes[1:] { + idemixAttrs[i] = types.IdemixAttribute{ + Type: types.IdemixHiddenAttribute, + } + } + + rhIndex, eidIndex := 27, 26 + + Nym, RNmy, err := userProto.MakeNym(sk, ipk) + assert.NoError(t, err) + + //////////////////// + // base signature // + //////////////////// + + sig, _, err := signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Standard, nil) + assert.NoError(t, err) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.Basic, nil) + assert.NoError(t, err) + + ////////////////////// + // eidNym signature // + ////////////////////// + + sig, m, err := signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNym, nil) + assert.NoError(t, err) + + cb := bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, m.EidNymAuditData.Rand) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[eidIndex+1], bbs12381g2pub.FrFromOKM([]byte(`_:c14n0 "alice.remote" .`), curve)) + assert.True(t, cb.Build().Equals(m.EidNymAuditData.Nym)) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, nil) + assert.NoError(t, err) +} + +func TestW3CCredSkElsewhere(t *testing.T) { + curve := math.Curves[math.BLS12_381_BBS] + + rand, err := curve.Rand() + assert.NoError(t, err) + + pkHex := `87fae47132975f345b38fafd53149f7a009b89dd94fdc54d5d051a29e185ed4870acc2453fbd2e307d1543dfb7fbfdb30cf0008df96c75e2e43975b7f92864b4bc6e3f2f1495748d80a36691f6feaeb8fe151c1bb35de9bff5ac21ff9e57aebe` + sigBase64 := "tQ4rHLBIh7a9dk5MVoly8ccb80pGeoEqybhYnYZO8VmguaFDyuCN7rFdBPCVs1/SYUHlKfzccE4m7waZyoLEkBLFiK2g54Q2i+CdtYBgDdkUDsoULSBMcH1MwGHwdjfXpldFNFrHFx/IAvLVniyeMQ==" + + attributeNames := []string{ + "_:c14n0 ", + "_:c14n0 ", + } + + messagesBytes := [][]byte{ + []byte(`_:c14n0 "2023-11-03T11:12:17Z"^^ .`), + []byte(`_:c14n0 .`), + []byte(`_:c14n0 .`), + []byte(`_:c14n0 .`), + []byte(` _:c14n0 .`), + []byte(` "1990-11-22"^^ .`), + []byte(` "Bowen" .`), + []byte(` "Male" .`), + []byte(` "Jace" .`), + []byte(` .`), + []byte(` .`), + []byte(` .`), + []byte(` "Bahamas" .`), + []byte(` "C09" .`), + []byte(` "223-45-198" .`), + []byte(` "2015-01-01"^^ .`), + []byte(` "{\"hash\":\"de701215430a0c4f940ffe830efd27f54cae0d9655d78dc3849272e7641c05eedd066588345caf9d4181d9f325e73a9950a967d6fe766a4a62e02876e73255ad\",\"key\":\"aab053a5e11e3360679ce1a42c7733063843854a1002c19186743d7432a2e467\",\"link\":\"https://dev.lcn-cluster-dev-qa-app-583c1d2c1a459ad4539801325cd4ba78-0000.us-south.containers.appdomain.cloud/api/public/v1/object/70a62792-eb95-4491-a77f-e53dde8034fb\"}"^^ .`), + []byte(` "Permanent Resident Card" .`), + []byte(` .`), + []byte(` .`), + []byte(` .`), + []byte(` "2029-12-03T12:19:52Z"^^ .`), + []byte(` "2019-12-03T12:19:52Z"^^ .`), + []byte(` .`), + []byte(`_:c14n0 "chgA6VtGQeRd/0rf1P6fCFm8t7ZU1Q8eMPM/+E9gsw8=" .`), + []byte(`_:c14n0 "mytopos-mychannel-token-chaincode.example.com" .`), + []byte(`_:c14n0 "2"^^ .`), + []byte(`_:c14n0 "alice.remote" .`), + []byte(`_:c14n0 "111" .`), + } + + for _, idcs := range [][]int{ + {24, 27, 26}, + {0, 0, 1}, + {0, 1, 0}, + {3, 9, 7}, + {24, 0, 1}, + {24, 1, 0}, + {24, 25, 26}, + {26, 25, 24}, + {25, 26, 24}, + {25, 24, 26}, + {0, 1, len(messagesBytes) - 2}, + {0, len(messagesBytes) - 3, len(messagesBytes) - 2}, + {len(messagesBytes) - 2, len(messagesBytes) - 3, 0}, + {len(messagesBytes) - 2, 0, len(messagesBytes) - 3}, + } { + skIndex := idcs[0] // this is an index into the `messagesBytes` array + rhIndex, eidIndex := idcs[1], idcs[2] // these are indices into the `messagesBytes` *without* the usk attribute + + eidIndexInBases := eidIndex + rhIndexInBases := rhIndex + + // increment the index to cater for the index for `sk` + if eidIndexInBases >= skIndex { + eidIndexInBases++ + } + + // increment the index to cater for the index for `sk` + if rhIndexInBases >= skIndex { + rhIndexInBases++ + } + + eidAttr := messagesBytes[eidIndexInBases] + rhAttr := messagesBytes[rhIndexInBases] + + t.Run("run", func(t *testing.T) { + pkBytes, err := hex.DecodeString(pkHex) + assert.NoError(t, err) + sigBytes, err := base64.StdEncoding.DecodeString(sigBase64) + assert.NoError(t, err) + + bls := bbs12381g2pub.New(math.Curves[math.BLS12_381_BBS]) + + err = bls.Verify(messagesBytes, sigBytes, pkBytes) + assert.NoError(t, err) + + attributes := make([][]byte, len(attributeNames)) + j := 0 + for i, msg := range messagesBytes { + if i == skIndex { + continue + } + attributes[j] = bbs12381g2pub.FrFromOKM(msg, curve).Bytes() + j++ + } + + sk := bbs12381g2pub.FrFromOKM(messagesBytes[skIndex], curve) + + cred := &aries.Credential{ + Cred: sigBytes, + Attrs: attributes, + SkPos: int32(skIndex), + } + credBytes, err := proto.Marshal(cred) + assert.NoError(t, err) + + credProto := &aries.Cred{ + Bls: bbs12381g2pub.New(curve), + Curve: curve, + } + + issuerProto := &aries.Issuer{curve} + + ipk, err := issuerProto.NewPublicKeyFromBytes(pkBytes, attributeNames) + assert.NoError(t, err) + + idemixAttrs := []types.IdemixAttribute{} + for i, msg := range messagesBytes { + if i == skIndex { + continue + } + idemixAttrs = append(idemixAttrs, types.IdemixAttribute{ + Type: types.IdemixBytesAttribute, + Value: msg, + }) + } + + err = credProto.Verify(sk, ipk, credBytes, idemixAttrs) + assert.NoError(t, err) + + signer := &aries.Signer{ + Curve: curve, + Rng: rand, + } + + userProto := &aries.User{ + Curve: curve, + Rng: rand, + UserSecretKeyIndex: skIndex, + } + + for i := range idemixAttrs { + idemixAttrs[i] = types.IdemixAttribute{ + Type: types.IdemixHiddenAttribute, + } + } + + Nym, RNmy, err := userProto.MakeNym(sk, ipk) + assert.NoError(t, err) + + //////////////////// + // base signature // + //////////////////// + + sig, _, err := signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Standard, nil) + assert.NoError(t, err) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.Basic, nil) + assert.NoError(t, err) + + ////////////////////// + // eidNym signature // + ////////////////////// + + sig, m, err := signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNym, nil) + assert.NoError(t, err) + + cb := bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, m.EidNymAuditData.Rand) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[eidIndexInBases], bbs12381g2pub.FrFromOKM(eidAttr, curve)) + assert.True(t, cb.Build().Equals(m.EidNymAuditData.Nym)) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNym, nil) + assert.NoError(t, err) + + ////////////////////// + // eidNym signature // (nym supplied) + ////////////////////// + + rNym := curve.NewRandomZr(rand) + + cb = bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, rNym) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[eidIndexInBases], bbs12381g2pub.FrFromOKM(eidAttr, curve)) + nym := cb.Build() + + meta := &types.IdemixSignerMetadata{ + EidNym: nym.Bytes(), + EidNymAuditData: &types.AttrNymAuditData{ + Nym: nym, + Rand: rNym, + Attr: bbs12381g2pub.FrFromOKM(eidAttr, curve), + }, + } + + sig, _, err = signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNym, meta) + assert.NoError(t, err) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNym, nil) + assert.NoError(t, err) + + // supply correct metadata for verification + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, + rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNym, meta) + assert.NoError(t, err) + + // audit with AuditNymEid - it should succeed with the right nym and randomness + err = signer.AuditNymEid(ipk, eidIndex, skIndex, sig, string(eidAttr), rNym, types.AuditExpectSignature) + assert.NoError(t, err) + + ///////////////////// + // NymRh signature // + ///////////////////// + + sig, m, err = signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("tome"), rhIndex, eidIndex, nil, types.EidNymRhNym, nil) + assert.NoError(t, err) + + cb = bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, m.EidNymAuditData.Rand) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[eidIndexInBases], m.EidNymAuditData.Attr) + assert.True(t, cb.Build().Equals(m.EidNymAuditData.Nym)) + + cb = bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, m.RhNymAuditData.Rand) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[rhIndexInBases], m.RhNymAuditData.Attr) + assert.True(t, cb.Build().Equals(m.RhNymAuditData.Nym)) + + err = signer.Verify(ipk, sig, []byte("tome"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNymRhNym, nil) + assert.NoError(t, err) + + ///////////////////// + // NymRh signature // (nym supplied) + ///////////////////// + + rNym = curve.NewRandomZr(rand) + + cb = bbs12381g2pub.NewCommitmentBuilder(2) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H0, rNym) + cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[rhIndexInBases], bbs12381g2pub.FrFromOKM(rhAttr, curve)) + nym = cb.Build() + + meta = &types.IdemixSignerMetadata{ + RhNym: nym.Bytes(), + RhNymAuditData: &types.AttrNymAuditData{ + Nym: nym, + Rand: rNym, + Attr: bbs12381g2pub.FrFromOKM(rhAttr, curve), + }, + } + + sig, _, err = signer.Sign(credBytes, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNymRhNym, meta) + assert.NoError(t, err) + + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNymRhNym, nil) + assert.NoError(t, err) + + // supply correct metadata for verification + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, skIndex, nil, 0, types.ExpectEidNymRhNym, meta) + assert.NoError(t, err) + + // audit with AuditNymEid - it should succeed with the right nym and randomness + err = signer.AuditNymRh(ipk, rhIndex, skIndex, sig, string(rhAttr), rNym, types.AuditExpectSignature) + assert.NoError(t, err) + }) + } +} + func TestSigner(t *testing.T) { curve := math.Curves[math.BLS12_381_BBS] @@ -512,7 +977,7 @@ func TestSigner(t *testing.T) { sig, _, err := signer.Sign(cred, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Standard, nil) assert.NoError(t, err) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.Basic, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.Basic, nil) assert.NoError(t, err) ////////////////////// @@ -527,7 +992,7 @@ func TestSigner(t *testing.T) { cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[eidIndex+1], m.EidNymAuditData.Attr) assert.True(t, cb.Build().Equals(m.EidNymAuditData.Nym)) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNym, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, nil) assert.NoError(t, err) ////////////////////// @@ -553,12 +1018,12 @@ func TestSigner(t *testing.T) { sig, _, err = signer.Sign(cred, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNym, meta) assert.NoError(t, err) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNym, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, nil) assert.NoError(t, err) // supply correct metadata for verification err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, - rhIndex, eidIndex, nil, 0, types.ExpectEidNym, meta) + rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, meta) assert.NoError(t, err) meta = &types.IdemixSignerMetadata{ @@ -572,7 +1037,7 @@ func TestSigner(t *testing.T) { // supply wrong metadata for verification err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, - rhIndex, eidIndex, nil, 0, types.ExpectEidNym, meta) + rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, meta) assert.EqualError(t, err, "signature invalid: nym eid validation failed, does not match regenerated nym eid") meta = &types.IdemixSignerMetadata{ @@ -581,7 +1046,7 @@ func TestSigner(t *testing.T) { // supply wrong metadata for verification err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, - rhIndex, eidIndex, nil, 0, types.ExpectEidNym, meta) + rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, meta) assert.EqualError(t, err, "signature invalid: nym eid validation failed, signature nym eid does not match metadata") meta = &types.IdemixSignerMetadata{ @@ -590,7 +1055,7 @@ func TestSigner(t *testing.T) { // supply wrong metadata for verification err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, - rhIndex, eidIndex, nil, 0, types.ExpectEidNym, meta) + rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, meta) assert.EqualError(t, err, "signature invalid: nym eid validation failed, failed to unmarshal meta nym eid") meta = &types.IdemixSignerMetadata{ @@ -604,43 +1069,43 @@ func TestSigner(t *testing.T) { // supply wrong metadata for verification err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, - rhIndex, eidIndex, nil, 0, types.ExpectEidNym, meta) + rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, meta) assert.EqualError(t, err, "signature invalid: nym eid validation failed, does not match metadata") // audit with AuditNymEid - it should succeed with the right nym and randomness - err = signer.AuditNymEid(ipk, eidIndex, sig, "nymeid", rNym, types.AuditExpectSignature) + err = signer.AuditNymEid(ipk, eidIndex, 0, sig, "nymeid", rNym, types.AuditExpectSignature) assert.NoError(t, err) // audit with AuditNymEid - it should fail with the wrong nym - err = signer.AuditNymEid(ipk, eidIndex, sig, "not so much the nymeid", rNym, types.AuditExpectSignature) + err = signer.AuditNymEid(ipk, eidIndex, 0, sig, "not so much the nymeid", rNym, types.AuditExpectSignature) assert.EqualError(t, err, "eid nym does not match") // audit with AuditNymEid - it should fail with the wrong randomness - err = signer.AuditNymEid(ipk, eidIndex, sig, "nymeid", curve.NewRandomZr(rand), types.AuditExpectSignature) + err = signer.AuditNymEid(ipk, eidIndex, 0, sig, "nymeid", curve.NewRandomZr(rand), types.AuditExpectSignature) assert.EqualError(t, err, "eid nym does not match") // audit with AuditNymEid - it should succeed with the right nym and randomness - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "nymeid", rNym, types.AuditExpectEidNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "nymeid", rNym, types.AuditExpectEidNym) assert.NoError(t, err) // audit with AuditNymEid - it should fail with the wrong nym - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "not so much the nymeid", rNym, types.AuditExpectEidNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "not so much the nymeid", rNym, types.AuditExpectEidNym) assert.EqualError(t, err, "eid nym does not match") // audit with AuditNymEid - it should fail with the wrong randomness - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "nymeid", curve.NewRandomZr(rand), types.AuditExpectEidNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "nymeid", curve.NewRandomZr(rand), types.AuditExpectEidNym) assert.EqualError(t, err, "eid nym does not match") // audit with AuditNymEid - it should succeed with the right nym and randomness - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "nymeid", rNym, types.AuditExpectEidNymRhNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "nymeid", rNym, types.AuditExpectEidNymRhNym) assert.NoError(t, err) // audit with AuditNymEid - it should fail with the wrong nym - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "not so much the nymeid", rNym, types.AuditExpectEidNymRhNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "not so much the nymeid", rNym, types.AuditExpectEidNymRhNym) assert.EqualError(t, err, "eid nym does not match") // audit with AuditNymEid - it should fail with the wrong randomness - err = signer.AuditNymEid(ipk, eidIndex, nym.Bytes(), "nymeid", curve.NewRandomZr(rand), types.AuditExpectEidNymRhNym) + err = signer.AuditNymEid(ipk, eidIndex, 0, nym.Bytes(), "nymeid", curve.NewRandomZr(rand), types.AuditExpectEidNymRhNym) assert.EqualError(t, err, "eid nym does not match") ////////////////////// @@ -683,7 +1148,7 @@ func TestSigner(t *testing.T) { cb.Add(ipk.(*aries.IssuerPublicKey).PKwG.H[rhIndex+1], m.RhNymAuditData.Attr) assert.True(t, cb.Build().Equals(m.RhNymAuditData.Nym)) - err = signer.Verify(ipk, sig, []byte("tome"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, nil) + err = signer.Verify(ipk, sig, []byte("tome"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, nil) assert.NoError(t, err) ///////////////////// @@ -709,11 +1174,11 @@ func TestSigner(t *testing.T) { sig, _, err = signer.Sign(cred, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNymRhNym, meta) assert.NoError(t, err) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, nil) assert.NoError(t, err) // supply correct metadata for verification - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, meta) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, meta) assert.NoError(t, err) meta = &types.IdemixSignerMetadata{ @@ -726,7 +1191,7 @@ func TestSigner(t *testing.T) { } // supply wrong metadata for verification - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, meta) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, meta) assert.EqualError(t, err, "signature invalid: nym rh validation failed, does not match regenerated nym rh") meta = &types.IdemixSignerMetadata{ @@ -734,7 +1199,7 @@ func TestSigner(t *testing.T) { } // supply wrong metadata for verification - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, meta) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, meta) assert.EqualError(t, err, "signature invalid: rh nym validation failed, signature rh nym does not match metadata") meta = &types.IdemixSignerMetadata{ @@ -742,7 +1207,7 @@ func TestSigner(t *testing.T) { } // supply wrong metadata for verification - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, meta) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, meta) assert.EqualError(t, err, "signature invalid: rh nym validation failed, failed to unmarshal meta rh nym") meta = &types.IdemixSignerMetadata{ @@ -755,35 +1220,35 @@ func TestSigner(t *testing.T) { } // supply wrong metadata for verification - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, meta) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, meta) assert.EqualError(t, err, "signature invalid: nym rh validation failed, does not match metadata") // audit with AuditNymEid - it should succeed with the right nym and randomness - err = signer.AuditNymRh(ipk, rhIndex, sig, "nymrh", rNym, types.AuditExpectSignature) + err = signer.AuditNymRh(ipk, rhIndex, 0, sig, "nymrh", rNym, types.AuditExpectSignature) assert.NoError(t, err) // audit with AuditNymEid - it should fail with the wrong nym - err = signer.AuditNymRh(ipk, rhIndex, sig, "not so much the nymrh", rNym, types.AuditExpectSignature) + err = signer.AuditNymRh(ipk, rhIndex, 0, sig, "not so much the nymrh", rNym, types.AuditExpectSignature) assert.EqualError(t, err, "rh nym does not match") // audit with AuditNymEid - it should fail with the wrong randomness - err = signer.AuditNymRh(ipk, rhIndex, sig, "nymrh", curve.NewRandomZr(rand), types.AuditExpectSignature) + err = signer.AuditNymRh(ipk, rhIndex, 0, sig, "nymrh", curve.NewRandomZr(rand), types.AuditExpectSignature) assert.EqualError(t, err, "rh nym does not match") // audit with AuditNymEid - it should succeed with the right nym and randomness - err = signer.AuditNymRh(ipk, rhIndex, nym.Bytes(), "nymrh", rNym, types.AuditExpectEidNymRhNym) + err = signer.AuditNymRh(ipk, rhIndex, 0, nym.Bytes(), "nymrh", rNym, types.AuditExpectEidNymRhNym) assert.NoError(t, err) // audit with AuditNymEid - it should fail with the wrong nym - err = signer.AuditNymRh(ipk, rhIndex, nym.Bytes(), "not so much the nymrh", rNym, types.AuditExpectEidNymRhNym) + err = signer.AuditNymRh(ipk, rhIndex, 0, nym.Bytes(), "not so much the nymrh", rNym, types.AuditExpectEidNymRhNym) assert.EqualError(t, err, "rh nym does not match") // audit with AuditNymEid - it should fail with the wrong randomness - err = signer.AuditNymRh(ipk, rhIndex, nym.Bytes(), "nymrh", curve.NewRandomZr(rand), types.AuditExpectEidNymRhNym) + err = signer.AuditNymRh(ipk, rhIndex, 0, nym.Bytes(), "nymrh", curve.NewRandomZr(rand), types.AuditExpectEidNymRhNym) assert.EqualError(t, err, "rh nym does not match") // audit with AuditNymEid - it should fail with AuditExpectEidNym - err = signer.AuditNymRh(ipk, rhIndex, nym.Bytes(), "nymrh", rNym, types.AuditExpectEidNym) + err = signer.AuditNymRh(ipk, rhIndex, 0, nym.Bytes(), "nymrh", rNym, types.AuditExpectEidNym) assert.EqualError(t, err, "invalid audit type [1]") ///////////////////// @@ -816,7 +1281,7 @@ func TestSigner(t *testing.T) { sig, _, err = signer.Sign(cred, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.Standard, nil) assert.NoError(t, err) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNym, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNym, nil) assert.EqualError(t, err, "no EidNym provided but ExpectEidNym required") ///////////////////// @@ -826,7 +1291,7 @@ func TestSigner(t *testing.T) { sig, _, err = signer.Sign(cred, sk, Nym, RNmy, ipk, idemixAttrs, []byte("silliness"), rhIndex, eidIndex, nil, types.EidNym, nil) assert.NoError(t, err) - err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, nil, 0, types.ExpectEidNymRhNym, nil) + err = signer.Verify(ipk, sig, []byte("silliness"), idemixAttrs, rhIndex, eidIndex, 0, nil, 0, types.ExpectEidNymRhNym, nil) assert.EqualError(t, err, "no RhNym provided but ExpectEidNymRhNym required") ////////////////////// diff --git a/bccsp/schemes/aries/user.go b/bccsp/schemes/aries/user.go index 4dbc623..20a872b 100644 --- a/bccsp/schemes/aries/user.go +++ b/bccsp/schemes/aries/user.go @@ -16,8 +16,9 @@ import ( ) type User struct { - Curve *math.Curve - Rng io.Reader + Curve *math.Curve + Rng io.Reader + UserSecretKeyIndex int } // NewKey generates a new User secret key @@ -50,7 +51,7 @@ func (u *User) MakeNym(sk *math.Zr, key types.IssuerPublicKey) (*math.G1, *math. cb := bbs12381g2pub.NewCommitmentBuilder(2) cb.Add(ipk.PKwG.H0, rNym) - cb.Add(ipk.PKwG.H[UserSecretKeyIndex], sk) + cb.Add(ipk.PKwG.H[u.UserSecretKeyIndex], sk) nym := cb.Build() return nym, rNym, nil diff --git a/bccsp/schemes/aries/util.go b/bccsp/schemes/aries/util.go index 9516f42..820e698 100644 --- a/bccsp/schemes/aries/util.go +++ b/bccsp/schemes/aries/util.go @@ -12,30 +12,21 @@ import ( "github.com/ale-linux/aries-framework-go/component/kmscrypto/crypto/primitive/bbs12381g2pub" ) -func attributesToSignatureMessage(sk *math.Zr, attributes []types.IdemixAttribute, curve *math.Curve) []*bbs12381g2pub.SignatureMessage { - var msgsZr []*bbs12381g2pub.SignatureMessage - - if sk == nil { - msgsZr = make([]*bbs12381g2pub.SignatureMessage, 0, len(attributes)) - } else { - msgsZr = make([]*bbs12381g2pub.SignatureMessage, 1, len(attributes)+1) - msgsZr[UserSecretKeyIndex] = &bbs12381g2pub.SignatureMessage{ - FR: sk, - Idx: UserSecretKeyIndex, - } - } +func attributesToSignatureMessage(attributes []types.IdemixAttribute, curve *math.Curve, skPos int) []*bbs12381g2pub.SignatureMessage { + attributes = append(append(append([]types.IdemixAttribute{}, attributes[:skPos]...), types.IdemixAttribute{Type: types.IdemixHiddenAttribute}), attributes[skPos:]...) + var msgsZr = make([]*bbs12381g2pub.SignatureMessage, 0, len(attributes)) for i, msg := range attributes { switch msg.Type { case types.IdemixBytesAttribute: msgsZr = append(msgsZr, &bbs12381g2pub.SignatureMessage{ FR: bbs12381g2pub.FrFromOKM(msg.Value.([]byte), curve), - Idx: i + 1, + Idx: i, }) case types.IdemixIntAttribute: msgsZr = append(msgsZr, &bbs12381g2pub.SignatureMessage{ FR: curve.NewZrFromInt(int64(msg.Value.(int))), - Idx: i + 1, + Idx: i, }) case types.IdemixHiddenAttribute: continue @@ -70,23 +61,21 @@ func revealedAttributesIndex(attributes []types.IdemixAttribute) []int { } func (c *Credential) toSignatureMessage(sk *math.Zr, curve *math.Curve) []*bbs12381g2pub.SignatureMessage { - var msgsZr []*bbs12381g2pub.SignatureMessage - - if sk == nil { - msgsZr = make([]*bbs12381g2pub.SignatureMessage, 0, len(c.Attrs)) - } else { - msgsZr = make([]*bbs12381g2pub.SignatureMessage, 1, len(c.Attrs)+1) - msgsZr[UserSecretKeyIndex] = &bbs12381g2pub.SignatureMessage{ - FR: sk, - Idx: UserSecretKeyIndex, + msgsZr := make([]*bbs12381g2pub.SignatureMessage, 0, len(c.Attrs)+1) + + j := 0 + for i := 0; i < len(c.Attrs)+1; i++ { + msg := &bbs12381g2pub.SignatureMessage{} + msgsZr = append(msgsZr, msg) + + if i == int(c.SkPos) { + msg.FR = sk + } else { + msg.FR = curve.NewZrFromBytes(c.Attrs[j]) + j++ } - } - for i, msg := range c.Attrs { - msgsZr = append(msgsZr, &bbs12381g2pub.SignatureMessage{ - FR: curve.NewZrFromBytes(msg), - Idx: i + 1, - }) + msg.Idx = i } return msgsZr diff --git a/bccsp/schemes/dlog/bridge/bridge_test.go b/bccsp/schemes/dlog/bridge/bridge_test.go index aed4356..d901953 100644 --- a/bccsp/schemes/dlog/bridge/bridge_test.go +++ b/bccsp/schemes/dlog/bridge/bridge_test.go @@ -448,23 +448,23 @@ var _ = Describe("Idemix Bridge", func() { Context("verify", func() { It("fail on nil issuer Public key", func() { - err := SignatureScheme.Verify(nil, nil, nil, nil, 0, 2, nil, 0, 0, nil) + err := SignatureScheme.Verify(nil, nil, nil, nil, 0, 2, 1, nil, 0, 0, nil) Expect(err).To(MatchError("invalid issuer public key, expected *IssuerPublicKey, got []")) }) It("fail on nil signature", func() { - err := SignatureScheme.Verify(issuerPublicKey, nil, nil, nil, 0, 2, nil, 0, 0, nil) + err := SignatureScheme.Verify(issuerPublicKey, nil, nil, nil, 0, 2, 1, nil, 0, 0, nil) Expect(err).To(MatchError("cannot verify idemix signature: received nil input")) }) It("fail on invalid signature", func() { - err := SignatureScheme.Verify(issuerPublicKey, []byte{0, 1, 2, 3, 4}, nil, nil, 0, 2, nil, 0, 0, nil) + err := SignatureScheme.Verify(issuerPublicKey, []byte{0, 1, 2, 3, 4}, nil, nil, 0, 2, 1, nil, 0, 0, nil) Expect(err.Error()).To(ContainSubstring("cannot parse invalid wire-format data")) }) It("fail on invalid attributes", func() { err := SignatureScheme.Verify(issuerPublicKey, nil, nil, - []types.IdemixAttribute{{Type: -1}}, 0, 2, nil, 0, 0, nil) + []types.IdemixAttribute{{Type: -1}}, 0, 2, 1, nil, 0, 0, nil) Expect(err).To(MatchError("attribute type not allowed or supported [-1] at position [0]")) }) }) @@ -488,17 +488,17 @@ var _ = Describe("Idemix Bridge", func() { Context("verify", func() { It("fail on nil issuer Public key", func() { - err := NymSignatureScheme.Verify(nil, nil, nil, nil) + err := NymSignatureScheme.Verify(nil, nil, nil, nil, 0) Expect(err).To(MatchError("invalid issuer public key, expected *IssuerPublicKey, got []")) }) It("panic on nil signature", func() { - err := NymSignatureScheme.Verify(issuerPublicKey, nymPublicKey, nil, nil) + err := NymSignatureScheme.Verify(issuerPublicKey, nymPublicKey, nil, nil, 0) Expect(err).To(MatchError(ContainSubstring("failure [runtime error: invalid memory address or nil pointer dereference]"))) }) It("fail on invalid signature", func() { - err := NymSignatureScheme.Verify(issuerPublicKey, nymPublicKey, []byte{0, 1, 2, 3, 4}, nil) + err := NymSignatureScheme.Verify(issuerPublicKey, nymPublicKey, []byte{0, 1, 2, 3, 4}, nil, 0) Expect(err.Error()).To(ContainSubstring("error unmarshalling signature")) }) diff --git a/bccsp/schemes/dlog/bridge/nymsignaturescheme.go b/bccsp/schemes/dlog/bridge/nymsignaturescheme.go index c101b31..9921367 100644 --- a/bccsp/schemes/dlog/bridge/nymsignaturescheme.go +++ b/bccsp/schemes/dlog/bridge/nymsignaturescheme.go @@ -53,7 +53,7 @@ func (n *NymSignatureScheme) Sign(sk *math.Zr, Nym *math.G1, RNym *math.Zr, ipk // Verify checks that the passed signatures is valid with the respect to the passed digest, issuer public key, // and pseudonym public key. -func (n *NymSignatureScheme) Verify(ipk types.IssuerPublicKey, Nym *math.G1, signature, digest []byte) (err error) { +func (n *NymSignatureScheme) Verify(ipk types.IssuerPublicKey, Nym *math.G1, signature, digest []byte, _ int) (err error) { defer func() { if r := recover(); r != nil { err = errors.Errorf("failure [%s]", r) diff --git a/bccsp/schemes/dlog/bridge/signaturescheme.go b/bccsp/schemes/dlog/bridge/signaturescheme.go index f50b92c..ace60a3 100644 --- a/bccsp/schemes/dlog/bridge/signaturescheme.go +++ b/bccsp/schemes/dlog/bridge/signaturescheme.go @@ -92,7 +92,7 @@ func (s *SignatureScheme) Sign(cred []byte, sk *math.Zr, Nym *math.G1, RNym *mat // AuditNymEid Audits the pseudonymous enrollment id of a signature func (s *SignatureScheme) AuditNymEid( ipk types.IssuerPublicKey, - eidIndex int, + eidIndex, _ int, signature []byte, enrollmentID string, RNymEid *math.Zr, @@ -148,7 +148,7 @@ func (s *SignatureScheme) AuditNymEid( // AuditNymRh Audits the pseudonymous revocation handle of a signature func (s *SignatureScheme) AuditNymRh( ipk types.IssuerPublicKey, - rhIndex int, + rhIndex, _ int, signature []byte, revocationHandle string, RNymRh *math.Zr, @@ -205,7 +205,7 @@ func (s *SignatureScheme) Verify( ipk types.IssuerPublicKey, signature, digest []byte, attributes []bccsp.IdemixAttribute, - rhIndex, eidIndex int, + rhIndex, eidIndex, _ int, revocationPublicKey *ecdsa.PublicKey, epoch int, verType bccsp.VerificationType, diff --git a/bccsp/smartcard_test.go b/bccsp/smartcard_test.go index cfa7e04..f90ab06 100644 --- a/bccsp/smartcard_test.go +++ b/bccsp/smartcard_test.go @@ -477,7 +477,7 @@ func TestSmartcardCSP(t *testing.T) { { Type: types.IdemixHiddenAttribute, }, - }, 3, 2, nil, -1, types.ExpectSmartcard, &types.IdemixSignerMetadata{EidNym: nymEid.Bytes()}) + }, 3, 2, 0, nil, -1, types.ExpectSmartcard, &types.IdemixSignerMetadata{EidNym: nymEid.Bytes()}) assert.NoError(t, err) /*******************************************************************************/ diff --git a/bccsp/types/idemix.go b/bccsp/types/idemix.go index 9722bfe..5fcdaed 100644 --- a/bccsp/types/idemix.go +++ b/bccsp/types/idemix.go @@ -156,16 +156,20 @@ type SignatureScheme interface { // msg: message signed; // attributes: as described above; // rhIndex: revocation handle index relative to attributes; + // eidIndex: index of the enrollment ID relative to attributes; + // skIndex: index of the secret key relative to attributes; // revocationPublicKey: revocation public key; // epoch: revocation epoch. - Verify(ipk IssuerPublicKey, signature, msg []byte, attributes []IdemixAttribute, rhIndex, eidIndex int, + // verType: type of verification. + // meta: additional verification metadata. + Verify(ipk IssuerPublicKey, signature, msg []byte, attributes []IdemixAttribute, rhIndex, eidIndex, skIndex int, revocationPublicKey *ecdsa.PublicKey, epoch int, verType VerificationType, meta *IdemixSignerMetadata) error // AuditNymEid permits the auditing of the nym eid generated by a signer - AuditNymEid(ipk IssuerPublicKey, eidIndex int, signature []byte, enrollmentID string, RNymEid *math.Zr, verType AuditVerificationType) error + AuditNymEid(ipk IssuerPublicKey, eidIndex, skIndex int, signature []byte, enrollmentID string, RNymEid *math.Zr, verType AuditVerificationType) error // AuditNymRh permits the auditing of the nym rh generated by a signer - AuditNymRh(ipk IssuerPublicKey, rhIndex int, signature []byte, revocationHandle string, RNymRh *math.Zr, verType AuditVerificationType) error + AuditNymRh(ipk IssuerPublicKey, rhIndex, skIndex int, signature []byte, revocationHandle string, RNymRh *math.Zr, verType AuditVerificationType) error } // NymSignatureScheme is a local interface to decouple from the idemix implementation @@ -175,7 +179,7 @@ type NymSignatureScheme interface { Sign(sk *math.Zr, Nym *math.G1, RNym *math.Zr, ipk IssuerPublicKey, digest []byte) ([]byte, error) // Verify verifies an idemix NymSignature - Verify(pk IssuerPublicKey, Nym *math.G1, signature, digest []byte) error + Verify(pk IssuerPublicKey, Nym *math.G1, signature, digest []byte, skIndex int) error } // SmartcardNymSignatureScheme is a local interface to decouple from the idemix implementation diff --git a/bccsp/types/idemixopts.go b/bccsp/types/idemixopts.go index fdaf2ad..cd93194 100644 --- a/bccsp/types/idemixopts.go +++ b/bccsp/types/idemixopts.go @@ -298,6 +298,8 @@ type IdemixSignerOpts struct { RhIndex int // EidIndex contains the index of the EID attrbiute EidIndex int + // SKIndex contains the index of the secret key + SKIndex int // CRI contains the credential revocation information CRI []byte // Epoch is the revocation epoch the signature should be produced against @@ -324,6 +326,7 @@ type EidNymAuditOpts struct { EidIndex int // Index of enrollment ID attribute in signature EnrollmentID string // Enrollment ID of identity RNymEid *math.Zr // Field element of randomness + SKIndex int // index of the secret key } func (o *EidNymAuditOpts) HashFunc() crypto.Hash { @@ -336,6 +339,7 @@ type RhNymAuditOpts struct { RhIndex int // Index of revocation handle attribute in signature RevocationHandle string // Revocation handle of identity RNymRh *math.Zr // Field element of randomness + SKIndex int // index of the secret key } func (o *RhNymAuditOpts) HashFunc() crypto.Hash { @@ -365,6 +369,8 @@ type IdemixNymSignerOpts struct { // data about the nym returned by the smartcard implementation NymG1 *math.G1 RNym *math.Zr + + SKIndex int // index of the secret key } // HashFunc returns an identifier for the hash function used to produce diff --git a/bccsp/types/mock/nymsignature_scheme.go b/bccsp/types/mock/nymsignature_scheme.go index 045fb0a..1d73993 100644 --- a/bccsp/types/mock/nymsignature_scheme.go +++ b/bccsp/types/mock/nymsignature_scheme.go @@ -26,13 +26,14 @@ type NymSignatureScheme struct { result1 []byte result2 error } - VerifyStub func(types.IssuerPublicKey, *math.G1, []byte, []byte) error + VerifyStub func(types.IssuerPublicKey, *math.G1, []byte, []byte, int) error verifyMutex sync.RWMutex verifyArgsForCall []struct { arg1 types.IssuerPublicKey arg2 *math.G1 arg3 []byte arg4 []byte + arg5 int } verifyReturns struct { result1 error @@ -117,7 +118,7 @@ func (fake *NymSignatureScheme) SignReturnsOnCall(i int, result1 []byte, result2 }{result1, result2} } -func (fake *NymSignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 *math.G1, arg3 []byte, arg4 []byte) error { +func (fake *NymSignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 *math.G1, arg3 []byte, arg4 []byte, arg5 int) error { var arg3Copy []byte if arg3 != nil { arg3Copy = make([]byte, len(arg3)) @@ -135,13 +136,14 @@ func (fake *NymSignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 *math.G1 arg2 *math.G1 arg3 []byte arg4 []byte - }{arg1, arg2, arg3Copy, arg4Copy}) + arg5 int + }{arg1, arg2, arg3Copy, arg4Copy, arg5}) stub := fake.VerifyStub fakeReturns := fake.verifyReturns - fake.recordInvocation("Verify", []interface{}{arg1, arg2, arg3Copy, arg4Copy}) + fake.recordInvocation("Verify", []interface{}{arg1, arg2, arg3Copy, arg4Copy, arg5}) fake.verifyMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3, arg4) + return stub(arg1, arg2, arg3, arg4, arg5) } if specificReturn { return ret.result1 @@ -155,17 +157,17 @@ func (fake *NymSignatureScheme) VerifyCallCount() int { return len(fake.verifyArgsForCall) } -func (fake *NymSignatureScheme) VerifyCalls(stub func(types.IssuerPublicKey, *math.G1, []byte, []byte) error) { +func (fake *NymSignatureScheme) VerifyCalls(stub func(types.IssuerPublicKey, *math.G1, []byte, []byte, int) error) { fake.verifyMutex.Lock() defer fake.verifyMutex.Unlock() fake.VerifyStub = stub } -func (fake *NymSignatureScheme) VerifyArgsForCall(i int) (types.IssuerPublicKey, *math.G1, []byte, []byte) { +func (fake *NymSignatureScheme) VerifyArgsForCall(i int) (types.IssuerPublicKey, *math.G1, []byte, []byte, int) { fake.verifyMutex.RLock() defer fake.verifyMutex.RUnlock() argsForCall := fake.verifyArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5 } func (fake *NymSignatureScheme) VerifyReturns(result1 error) { diff --git a/bccsp/types/mock/signature_scheme.go b/bccsp/types/mock/signature_scheme.go index 4a2248e..8a8a060 100644 --- a/bccsp/types/mock/signature_scheme.go +++ b/bccsp/types/mock/signature_scheme.go @@ -10,15 +10,16 @@ import ( ) type SignatureScheme struct { - AuditNymEidStub func(types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) error + AuditNymEidStub func(types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) error auditNymEidMutex sync.RWMutex auditNymEidArgsForCall []struct { arg1 types.IssuerPublicKey arg2 int - arg3 []byte - arg4 string - arg5 *math.Zr - arg6 types.AuditVerificationType + arg3 int + arg4 []byte + arg5 string + arg6 *math.Zr + arg7 types.AuditVerificationType } auditNymEidReturns struct { result1 error @@ -26,15 +27,16 @@ type SignatureScheme struct { auditNymEidReturnsOnCall map[int]struct { result1 error } - AuditNymRhStub func(types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) error + AuditNymRhStub func(types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) error auditNymRhMutex sync.RWMutex auditNymRhArgsForCall []struct { arg1 types.IssuerPublicKey arg2 int - arg3 []byte - arg4 string - arg5 *math.Zr - arg6 types.AuditVerificationType + arg3 int + arg4 []byte + arg5 string + arg6 *math.Zr + arg7 types.AuditVerificationType } auditNymRhReturns struct { result1 error @@ -68,7 +70,7 @@ type SignatureScheme struct { result2 *types.IdemixSignerMetadata result3 error } - VerifyStub func(types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) error + VerifyStub func(types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) error verifyMutex sync.RWMutex verifyArgsForCall []struct { arg1 types.IssuerPublicKey @@ -77,10 +79,11 @@ type SignatureScheme struct { arg4 []types.IdemixAttribute arg5 int arg6 int - arg7 *ecdsa.PublicKey - arg8 int - arg9 types.VerificationType - arg10 *types.IdemixSignerMetadata + arg7 int + arg8 *ecdsa.PublicKey + arg9 int + arg10 types.VerificationType + arg11 *types.IdemixSignerMetadata } verifyReturns struct { result1 error @@ -92,28 +95,29 @@ type SignatureScheme struct { invocationsMutex sync.RWMutex } -func (fake *SignatureScheme) AuditNymEid(arg1 types.IssuerPublicKey, arg2 int, arg3 []byte, arg4 string, arg5 *math.Zr, arg6 types.AuditVerificationType) error { - var arg3Copy []byte - if arg3 != nil { - arg3Copy = make([]byte, len(arg3)) - copy(arg3Copy, arg3) +func (fake *SignatureScheme) AuditNymEid(arg1 types.IssuerPublicKey, arg2 int, arg3 int, arg4 []byte, arg5 string, arg6 *math.Zr, arg7 types.AuditVerificationType) error { + var arg4Copy []byte + if arg4 != nil { + arg4Copy = make([]byte, len(arg4)) + copy(arg4Copy, arg4) } fake.auditNymEidMutex.Lock() ret, specificReturn := fake.auditNymEidReturnsOnCall[len(fake.auditNymEidArgsForCall)] fake.auditNymEidArgsForCall = append(fake.auditNymEidArgsForCall, struct { arg1 types.IssuerPublicKey arg2 int - arg3 []byte - arg4 string - arg5 *math.Zr - arg6 types.AuditVerificationType - }{arg1, arg2, arg3Copy, arg4, arg5, arg6}) + arg3 int + arg4 []byte + arg5 string + arg6 *math.Zr + arg7 types.AuditVerificationType + }{arg1, arg2, arg3, arg4Copy, arg5, arg6, arg7}) stub := fake.AuditNymEidStub fakeReturns := fake.auditNymEidReturns - fake.recordInvocation("AuditNymEid", []interface{}{arg1, arg2, arg3Copy, arg4, arg5, arg6}) + fake.recordInvocation("AuditNymEid", []interface{}{arg1, arg2, arg3, arg4Copy, arg5, arg6, arg7}) fake.auditNymEidMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5, arg6) + return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7) } if specificReturn { return ret.result1 @@ -127,17 +131,17 @@ func (fake *SignatureScheme) AuditNymEidCallCount() int { return len(fake.auditNymEidArgsForCall) } -func (fake *SignatureScheme) AuditNymEidCalls(stub func(types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) error) { +func (fake *SignatureScheme) AuditNymEidCalls(stub func(types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) error) { fake.auditNymEidMutex.Lock() defer fake.auditNymEidMutex.Unlock() fake.AuditNymEidStub = stub } -func (fake *SignatureScheme) AuditNymEidArgsForCall(i int) (types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) { +func (fake *SignatureScheme) AuditNymEidArgsForCall(i int) (types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) { fake.auditNymEidMutex.RLock() defer fake.auditNymEidMutex.RUnlock() argsForCall := fake.auditNymEidArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7 } func (fake *SignatureScheme) AuditNymEidReturns(result1 error) { @@ -163,28 +167,29 @@ func (fake *SignatureScheme) AuditNymEidReturnsOnCall(i int, result1 error) { }{result1} } -func (fake *SignatureScheme) AuditNymRh(arg1 types.IssuerPublicKey, arg2 int, arg3 []byte, arg4 string, arg5 *math.Zr, arg6 types.AuditVerificationType) error { - var arg3Copy []byte - if arg3 != nil { - arg3Copy = make([]byte, len(arg3)) - copy(arg3Copy, arg3) +func (fake *SignatureScheme) AuditNymRh(arg1 types.IssuerPublicKey, arg2 int, arg3 int, arg4 []byte, arg5 string, arg6 *math.Zr, arg7 types.AuditVerificationType) error { + var arg4Copy []byte + if arg4 != nil { + arg4Copy = make([]byte, len(arg4)) + copy(arg4Copy, arg4) } fake.auditNymRhMutex.Lock() ret, specificReturn := fake.auditNymRhReturnsOnCall[len(fake.auditNymRhArgsForCall)] fake.auditNymRhArgsForCall = append(fake.auditNymRhArgsForCall, struct { arg1 types.IssuerPublicKey arg2 int - arg3 []byte - arg4 string - arg5 *math.Zr - arg6 types.AuditVerificationType - }{arg1, arg2, arg3Copy, arg4, arg5, arg6}) + arg3 int + arg4 []byte + arg5 string + arg6 *math.Zr + arg7 types.AuditVerificationType + }{arg1, arg2, arg3, arg4Copy, arg5, arg6, arg7}) stub := fake.AuditNymRhStub fakeReturns := fake.auditNymRhReturns - fake.recordInvocation("AuditNymRh", []interface{}{arg1, arg2, arg3Copy, arg4, arg5, arg6}) + fake.recordInvocation("AuditNymRh", []interface{}{arg1, arg2, arg3, arg4Copy, arg5, arg6, arg7}) fake.auditNymRhMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5, arg6) + return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7) } if specificReturn { return ret.result1 @@ -198,17 +203,17 @@ func (fake *SignatureScheme) AuditNymRhCallCount() int { return len(fake.auditNymRhArgsForCall) } -func (fake *SignatureScheme) AuditNymRhCalls(stub func(types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) error) { +func (fake *SignatureScheme) AuditNymRhCalls(stub func(types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) error) { fake.auditNymRhMutex.Lock() defer fake.auditNymRhMutex.Unlock() fake.AuditNymRhStub = stub } -func (fake *SignatureScheme) AuditNymRhArgsForCall(i int) (types.IssuerPublicKey, int, []byte, string, *math.Zr, types.AuditVerificationType) { +func (fake *SignatureScheme) AuditNymRhArgsForCall(i int) (types.IssuerPublicKey, int, int, []byte, string, *math.Zr, types.AuditVerificationType) { fake.auditNymRhMutex.RLock() defer fake.auditNymRhMutex.RUnlock() argsForCall := fake.auditNymRhArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7 } func (fake *SignatureScheme) AuditNymRhReturns(result1 error) { @@ -332,7 +337,7 @@ func (fake *SignatureScheme) SignReturnsOnCall(i int, result1 []byte, result2 *t }{result1, result2, result3} } -func (fake *SignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 []byte, arg3 []byte, arg4 []types.IdemixAttribute, arg5 int, arg6 int, arg7 *ecdsa.PublicKey, arg8 int, arg9 types.VerificationType, arg10 *types.IdemixSignerMetadata) error { +func (fake *SignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 []byte, arg3 []byte, arg4 []types.IdemixAttribute, arg5 int, arg6 int, arg7 int, arg8 *ecdsa.PublicKey, arg9 int, arg10 types.VerificationType, arg11 *types.IdemixSignerMetadata) error { var arg2Copy []byte if arg2 != nil { arg2Copy = make([]byte, len(arg2)) @@ -357,17 +362,18 @@ func (fake *SignatureScheme) Verify(arg1 types.IssuerPublicKey, arg2 []byte, arg arg4 []types.IdemixAttribute arg5 int arg6 int - arg7 *ecdsa.PublicKey - arg8 int - arg9 types.VerificationType - arg10 *types.IdemixSignerMetadata - }{arg1, arg2Copy, arg3Copy, arg4Copy, arg5, arg6, arg7, arg8, arg9, arg10}) + arg7 int + arg8 *ecdsa.PublicKey + arg9 int + arg10 types.VerificationType + arg11 *types.IdemixSignerMetadata + }{arg1, arg2Copy, arg3Copy, arg4Copy, arg5, arg6, arg7, arg8, arg9, arg10, arg11}) stub := fake.VerifyStub fakeReturns := fake.verifyReturns - fake.recordInvocation("Verify", []interface{}{arg1, arg2Copy, arg3Copy, arg4Copy, arg5, arg6, arg7, arg8, arg9, arg10}) + fake.recordInvocation("Verify", []interface{}{arg1, arg2Copy, arg3Copy, arg4Copy, arg5, arg6, arg7, arg8, arg9, arg10, arg11}) fake.verifyMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) + return stub(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) } if specificReturn { return ret.result1 @@ -381,17 +387,17 @@ func (fake *SignatureScheme) VerifyCallCount() int { return len(fake.verifyArgsForCall) } -func (fake *SignatureScheme) VerifyCalls(stub func(types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) error) { +func (fake *SignatureScheme) VerifyCalls(stub func(types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) error) { fake.verifyMutex.Lock() defer fake.verifyMutex.Unlock() fake.VerifyStub = stub } -func (fake *SignatureScheme) VerifyArgsForCall(i int) (types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) { +func (fake *SignatureScheme) VerifyArgsForCall(i int) (types.IssuerPublicKey, []byte, []byte, []types.IdemixAttribute, int, int, int, *ecdsa.PublicKey, int, types.VerificationType, *types.IdemixSignerMetadata) { fake.verifyMutex.RLock() defer fake.verifyMutex.RUnlock() argsForCall := fake.verifyArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7, argsForCall.arg8, argsForCall.arg9, argsForCall.arg10 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5, argsForCall.arg6, argsForCall.arg7, argsForCall.arg8, argsForCall.arg9, argsForCall.arg10, argsForCall.arg11 } func (fake *SignatureScheme) VerifyReturns(result1 error) { diff --git a/go.mod b/go.mod index 7847e55..af45cd3 100644 --- a/go.mod +++ b/go.mod @@ -45,3 +45,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/IBM/idemix/bccsp/types => ./bccsp/types/ + +replace github.com/IBM/idemix/bccsp/schemes/aries => ./bccsp/schemes/aries/ diff --git a/go.sum b/go.sum index 19cf4e5..69d510d 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/IBM/idemix/bccsp/schemes/aries v0.0.0-20240612072411-114d281b442d h1:8w1yWLIk0VzLTHFE1O8GwCaXs5hT9M7u4KsO+IwIen0= -github.com/IBM/idemix/bccsp/schemes/aries v0.0.0-20240612072411-114d281b442d/go.mod h1:vHi4fk2Im6fO0ofevbRr/EvblygatrTb1t2XlER58ik= github.com/IBM/idemix/bccsp/schemes/weak-bb v0.0.0-20240612072411-114d281b442d h1:jIDz71083inpGWt9IPVGb0DoqyF7tQW/YH0gBLb6sKo= github.com/IBM/idemix/bccsp/schemes/weak-bb v0.0.0-20240612072411-114d281b442d/go.mod h1:FC0vVgNI6bv8GH0VTwjup+arwJ8Tau1iEhroWZ1oPwU= -github.com/IBM/idemix/bccsp/types v0.0.0-20240612072411-114d281b442d h1:cv8IVW3eP0l3SxOLvKtPygBe4SC8+0QpwzQsJW4vtVE= -github.com/IBM/idemix/bccsp/types v0.0.0-20240612072411-114d281b442d/go.mod h1:IMIJ8WcUpBmV4gcOO/BYKuFYpdXCPYZjpNhFSUlO9b8= github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da h1:qqGozq4tF6EOVnWoTgBoJGudRKKZXSAYnEtDggzTnsw= github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da/go.mod h1:Tco9QzE3fQzjMS7nPbHDeFfydAzctStf1Pa8hsh6Hjs= github.com/ale-linux/aries-framework-go/component/kmscrypto v0.0.0-20231023164747-f3f972769504 h1:sQyFeDcHVHWJ3IeE437NSJjv0+J/6MvGQOJew4X+Cuw=