Skip to content

Commit

Permalink
Remove hardcoded position 0 for user secret key
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
ale-linux committed Aug 26, 2024
1 parent 3dce461 commit 6e5f0b7
Show file tree
Hide file tree
Showing 23 changed files with 808 additions and 284 deletions.
3 changes: 2 additions & 1 deletion bccsp/handlers/nymsigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
22 changes: 12 additions & 10 deletions bccsp/handlers/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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")
}
Expand All @@ -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,
Expand All @@ -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")
}
Expand All @@ -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,
Expand All @@ -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")
}
Expand All @@ -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,
Expand Down
37 changes: 23 additions & 14 deletions bccsp/schemes/aries/cred.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -78,31 +79,39 @@ 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 {
case types.IdemixHiddenAttribute:
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)
Expand Down
81 changes: 45 additions & 36 deletions bccsp/schemes/aries/cred.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bccsp/schemes/aries/cred.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 4 additions & 3 deletions bccsp/schemes/aries/credrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
3 changes: 0 additions & 3 deletions bccsp/schemes/aries/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 7 additions & 5 deletions bccsp/schemes/aries/nymsigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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...)

Expand All @@ -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)
}
Loading

0 comments on commit 6e5f0b7

Please sign in to comment.