Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Privacy preserving subject authentication mechanism for application with verifiable credentials #37

Closed
tplooker opened this issue Sep 8, 2020 · 39 comments
Assignees
Labels
pending-close The issue will be closed in 7 days if there are no objections.

Comments

@tplooker
Copy link
Contributor

tplooker commented Sep 8, 2020

BBS+ Signatures are a generalized digital signature scheme appropriate for a variety of applications, however their most immediate application is in the context of verifiable credentials.

Verifiable credentials in general define a cryptographically verifiable assertion format that allows an issuing authority to assert some information about a subject. In contrast to other assertion formats (e.g jwt based id_tokens in openid connect), verifiable credentials also focus on establishing a way for a credential subject to also authenticate, usually through a proof of key cryptographic mechanism.

The most common way this mechanism for subject authentication is realised in verifiable credentials is for the credential issued by the issuer to contain an identifier for the subject that when resolved contains the public cryptographic material required to verify a presentation of the credential originated from the subject it was bound to by the issuer.

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "issuer": "did:example:489398593",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "description": "Government of Example Permanent Resident Card.",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "expirationDate": "2029-12-03T12:19:52Z",
  "credentialSubject": {
    "id": "did:example:b34ca6cd37bbf23", // <= Unique identifier for the credential subject
    "type": ["PermanentResident", "Person"],
    "givenName": "JOHN",
    "familyName": "SMITH",
    "gender": "Male",
    "image": "data:image/png;base64,iVBORw0KGgokJggg==",
    "residentSince": "2015-01-01",
    "lprCategory": "C09",
    "lprNumber": "999-999-999",
    "commuterClassification": "C1",
    "birthCountry": "Bahamas",
    "birthDate": "1958-07-17"
  },
  "proof": {
    "type": "BbsBlsSignature2020",
    "created": "2020-04-26T04:21:07Z",
    "verificationMethod": "did:example:489398593#test",
    "proofPurpose": "assertionMethod",
    "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
  }

Note The current reference implementation of BBS+ signatures enables this mode today.

However, the problem with this model is that it enforces the presence of a unique identifier for the credential subject to always be present in the verifiable credential leading to the ability for relying parties / verifiers to be able to trivially track the subject across credential presentations.

Instead we need a subject authentication mechanism for verifiable credentials that does not require disclosing a unique identifier for the credential subject. But still relies on a proof of key cryptographic mechanism when the subject would like to authenticate the presentation of a verifiable credential.

In order to accomplish this we propose the following way.

Simple Terms

  1. Issuer has a BLS 12-381 G2 public/private key pair they use to issue verifiable credentials
  2. Subject has a BLS 12-381 G1 public/private key pair they will use to authenticate as the subject of a verifiable credential

When the issuer constructs a bound BBS+ signature one of the commitments they sign (other commitments being the individual statements in the verifiable credential), is the subjects BLS 12-381 G1 public key, therefore binding the signature to that key pair. In doing this in order for the subject to be able to derive a credential presentation for a credential featuring that signature they must possess the corresponding private key.

Examples

Issuer has a DID

{
    "@context": "https://w3.org/ns/did/v1",
    "id": "did:example:12345",
    "assertionMethod": [
        {
            "id": "did:example:12345#1",
            "type": "Bls12381G2Key2020",
            "controller": "did:example:12345",
            "publicKeyBase58": "mrNfdUFeVwXmjQARQBhBFDCNLu2d4xbcRVVSrqShwgLi4pWWoEPog3JMGmzqS8PJ1WgAxkqD6x2FnSfkWBw2qikaKxyuZ1gUt3Z9BXbgBJAZ13jmFSGdGGGiGxGjNsRGuuJ"
        }
    ]
}

Subject has a DID

{
    "@context": "https://w3.org/ns/did/v1",
    "id": "did:example:98765",
    "assertionMethod": [
        {
            "id": "did:example:98765#1",
            "type": "Bls12381G1Key2020",
            "controller": "did:example:98765",
            "publicKeyBase58": "mbsZx2rxTnboxrg1aE91Zc9iDDJcbeC1Q"
        }
    ]
}

Issuer issues credential of the following form

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "issuer": "did:example:12345",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "description": "Government of Example Permanent Resident Card.",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "expirationDate": "2029-12-03T12:19:52Z",
  "credentialSubject": {
    "type": ["PermanentResident", "Person"],
    "givenName": "JOHN",
    "familyName": "SMITH",
    "gender": "Male",
    "residentSince": "2015-01-01",
    "lprCategory": "C09",
    "lprNumber": "999-999-999",
    "commuterClassification": "C1",
    "birthCountry": "Bahamas",
    "birthDate": "1958-07-17"
  },
  "proof": {
    "type": "BbsBlsBoundSignature2020",
    "created": "2020-04-26T04:21:07Z",
    "verificationMethod": "did:example:12345#1",
    "subjectAuthenticationMethod": "did:example:98765#1", <= Note this is not a committed message in the signature it is merely here so that the subject knows which key the signature was bound to
    "proofPurpose": "assertionMethod",
    "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
  }
}

Subject can then create a selective proof (that requires them possessing the private key of the key pair the BbsBlsBoundSignature2020 was bound to)

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "issuer": "did:example:12345",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "description": "Government of Example Permanent Resident Card.",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "expirationDate": "2029-12-03T12:19:52Z",
  "credentialSubject": {
    "type": ["PermanentResident", "Person"],
    "givenName": "JOHN",
    "familyName": "SMITH",
    "gender": "Male",
    "residentSince": "2015-01-01",
  },
  "proof": {
    "type": "BbsBlsBoundSignatureProof2020",
    "created": "2020-04-26T04:21:07Z",
    "verificationMethod": "did:example:12345#1",
    "proofPurpose": "assertionMethod",
    "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
  }
}

Edit

  • Updated the example to remove the image as per @OR13 comments below that were confusing the intent of the example
  • Updated the subjectVerificationMethod field in the proof to be subjectAuthenticationMethod
@OR13
Copy link
Contributor

OR13 commented Sep 8, 2020

subjectVerficationMethod.... is known to the issuer... why not use credentialSubject.id here... and simply not reveal that statement when constructing the selective disclosure presentation?...

IIRC credentialSubject.id can be any URI... including did:example:98765#1

It feels like not revealing the credentialSubject.id but revealing image / age might be a better example.

Assuming subject G1 Key cannot be extracted from bound signature proof proofValue correct?

I assume this ZKP SD VC is then presented via something that supports replay attack mitigation?

This makes me wonder if we can support domain / challenge in deriveProof... and make BbsBlsBoundSignatureProof2020 a VP that matches the VC Spec 100%.

Seems like replay attacks are still a concern... the fact that the PRC has an image is actually confusing, because that feels like a solution to this problem... but it isn't...

the data subject has both the credential, and the linked private key.... but every time they use them to derive a proof, an eavesdropper might capture a selective disclosure....

its weird to think of putting a credential with no subject in a verifiable presentation.... it would feel more natural if BbsBlsBoundSignatureProof2020 was a VP and contained domain and challenge.

@tplooker
Copy link
Contributor Author

tplooker commented Sep 8, 2020

subjectVerficationMethod.... is known to the issuer... why not use credentialSubject.id here... and simply not reveal that statement when constructing the selective disclosure presentation?...

The main issue with this approach that then the generated N-Quads for the statements in the credentialSubject would then have to feature this ID meaning it would have to be known to a verifier and if not we would have to do some pretty weird credential specific logic about striping out credentialSubject.id before and after signature creation and verification.

I assume this ZKP SD VC is then presented via something that supports replay attack mitigation?

Yeap much like the signature proofs to-date you are free to have other things feature in the proof e.g we support a nonce at the moment so if this is supplied by the verifier then you have replay attack prevention. For example a bound proof featuring a nonce would look like this

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["PermanentResidentCard", "VerifiableCredential"],
  "description": "Government of Example Permanent Resident Card.",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "credentialSubject": {
    "type": ["Person", "PermanentResident"],
    "familyName": "SMITH",
    "gender": "Male",
    "givenName": "JOHN"
  },
  "expirationDate": "2029-12-03T12:19:52Z",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "issuer": "did:example:489398593",
  "proof": {
    "type": "BbsBlsBoundSignatureProof2020",
    "created": "2020-05-25T23:07:10Z",
    "verificationMethod": "did:example:489398593#test",
    "proofPurpose": "assertionMethod",
    "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
    "nonce": "37pdwue1a8FWLqgwCd0QJ0IJTFhp609KtxeCTWZGnfAVE+sOBDffYez+TY/bmVy+6z4="
  }
}

its weird to think of putting a credential with no subject in a verifiable presentation.... it would feel more natural if BbsBlsBoundSignatureProof2020 was a VP and contained domain and challenge.

Yes so to be clear a VC of the form BbsBlsBoundSignatureProof2020 would then be put into a VP like this where the inner proof authenticates the subject because of how it is generating rather than needing another proof outside this like many VP's require

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://www.w3.org/2018/credentials/examples/v1"
  ],
  "type": "VerifiablePresentation",
  "verifiableCredential": [{
    "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/citizenship/v1",
        "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
    ],
    "type": ["PermanentResidentCard", "VerifiableCredential"],
    "description": "Government of Example Permanent Resident Card.",
    "identifier": "83627465",
    "name": "Permanent Resident Card",
    "credentialSubject": {
        "type": ["Person", "PermanentResident"],
        "familyName": "SMITH",
        "gender": "Male",
        "givenName": "JOHN"
    },
    "expirationDate": "2029-12-03T12:19:52Z",
    "issuanceDate": "2019-12-03T12:19:52Z",
    "issuer": "did:example:489398593",
    "proof": {
        "type": "BbsBlsBoundSignatureProof2020",
        "created": "2020-05-25T23:07:10Z",
        "verificationMethod": "did:example:489398593#test",
        "proofPurpose": "assertionMethod",
        "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
        "nonce": "37pdwue1a8FWLqgwCd0QJ0IJTFhp609KtxeCTWZGnfAVE+sOBDffYez+TY/bmVy+6z4="
    }
  }]
}

@OR13
Copy link
Contributor

OR13 commented Sep 9, 2020

This makes sense, I also agree its wise not to take the VC Data Model as a dependency... everything can fit in the proof object.

@OR13
Copy link
Contributor

OR13 commented Sep 9, 2020

perhapse we would avoid the term subject....

subjectAuthenticationMethod

authenticationMethod / boundAuthenticationMethod...

@OR13
Copy link
Contributor

OR13 commented Sep 18, 2020

multiformats/multicodec#185 has been merged.

@tplooker wondering if we should define this key representation here now?

We should generate some test vectors for G1 / G2 and (G1 + G2), and then provide JWK, base58 and multicodec examples.

Also, should this suite define support for publicKeyMultibase and privateKeyMultibase ? see also https://github.com/w3c-ccg/lds-ed25519-2020/issues/4

This gets to my least favorite part of linked data... key representation.

IMO, tooling MUST support JWK, and MAY support any format which can be converted to JWK, included base58 or multibase.

@dlongley
Copy link
Contributor

My only comment is that you'll want to make sure that the proof purpose is for authentication when creating an authentication proof -- as opposed to assertionMethod.

@tplooker
Copy link
Contributor Author

tplooker commented Sep 18, 2020

@dlongley I think this is worth pondering a little more. A BbsBlsBoundSignatureProof2020 is unique in the sense that it is proving that the information was originally signed by the issuer BUT also authenticating the party who generated the proof. Currently in the example I have provided its quite clear about the role of the issuer but not the party who generated the proof.

@tplooker
Copy link
Contributor Author

@OR13 agree it would be a good next step. As far as test vectors we have some preliminary support for JWK for G1 and G2 here although they would not rise to the standard of a test vector yet.

OR13 added a commit that referenced this issue Sep 20, 2020
tplooker added a commit that referenced this issue Sep 20, 2020
@kdenhartog kdenhartog assigned kdenhartog and unassigned kdenhartog Apr 21, 2021
@kdenhartog
Copy link
Member

kdenhartog commented Apr 21, 2021

@brentzundel I can't assign, but during an IIW session Bren't said he'd take this issue and File a PR for it.

@brentzundel
Copy link
Member

commenting so I can be assigned

@OR13
Copy link
Contributor

OR13 commented Apr 23, 2021

@brentzundel sorry I missed the session on this. I assigned you, lmk how I can help.

@brentzundel
Copy link
Member

I am working on a PR to add this feature. It is not clear to me how the privacy of the holder is preserved when presenting a proof bound to their public BLS key. The example VP contains a reference to the holder's DID URL.
@tplooker or @mikelodder7 can someone walk me through this step by step so I can write it up?

@mikelodder7
Copy link
Contributor

@brentzundel thats why I wrote this up

https://github.com/mikelodder7/commit_twin.

The party storing the public keys knows your unique commitment in order to present but they don’t know your secret value. Also the public key is a pedersen commitment so it’s different per party and there’s no way it can be cross correlated between colluding parties

@brentzundel
Copy link
Member

brentzundel commented May 7, 2021

@tobias @mikelodder7 @OR13
I met with Mike Lodder and he walked me through Commit Twin. It is an excellent proposal that imo will come through a wider and more thorough review looking much like it does today. The drawback is that it has not yet undergone such a review.
As a private holder binding protocol, it is very similar to link secrets, in that a holder supplies a blinded commitment to a secret, then proves in zero knowledge that they know the secret, thereby demonstrating to a verifier that the credential has been bound to them. Commit Twin has an advantage over link secrets in that it does not require any pairings operations.

I believe that Commit Twin will be an excellent addition to this work moving forward and propose that it be considered as the mechanism for private holder binding a future version of this protocol. I do not think it will work for the 2020 version, primarily due to its limited review, as stated above.

After thoroughly examining the mechanism proposed by Tobias in the preceding comments, it is not clear to me how such a mechanism could be considered privacy preserving. It may be that there is some aspect of it that I simply do not grasp. Even so, Tobias's mechanism is also something knew and would benefit from the same review as Commit Twin.

Since plans are already underway to develop the next version of this specification, it does not make sense to me to add something new and untested to the 2020 version.

In order to finish the 2020 spec and bring it into a condition such that a broader community can make use of it while we develop the next version, I propose that we simply use link secrets as the private holder binding mechanism. They are already included in the Ursa base implementation and are as well-reviewed as BBS+ signatures. This would allow us to complete this spec and rapidly deploy it with a familiar and effective mechanism for private holder binding, rather than spending the time to properly review the other proposals, and rather than simply adopting either of them without review.

I am almost finished with my PR to add private holder binding to the spec. The further I got into it, the more concerned I became that what I was about to propose wasn't right. So I am sharing my concerns here and hope that we can come to agreement on the path forward.

tl;dr I think we should use link secrets for private holder binding in the 2020 spec, but move to a different (and better) binding mechanism in the next version.

@tplooker
Copy link
Contributor Author

tplooker commented May 9, 2021

@brentzundel thanks for reporting back, we should discuss this proposal further as the proposal of commit twin IMO is not directly about the credential binding technique instead it is how this binding can be used to achieve certain pseudonymity properties on top of the scheme. In essence I would like the binding to a credential to simply be a public key rather than a blinded public key (linked secret) because this makes the proof of private key signature more complex.

@brentzundel
Copy link
Member

I don't have a problem with a credential being simply bound to a public key, but couldn't understand how one could do so while providing privacy for the holder. If the proof of private key can be simpler than linked secrets while still avoiding revealing a correlating identifier, I'm all for it. I just don't see how it works, and am concerned that such a scheme will not have the necessary review. Could you help me understand how it works?
This is why I am recommending for the 2020 spec to use link secrets, while we continue to explore these potentially better options for the next version of the spec..

@tplooker
Copy link
Contributor Author

@brentzundel understood, so if it is issuer correlation you are concerned about in this case, then it is solved by simply having a different public key per issuer. Because this public key is never revealed when generating a presentation with a verifier I believe all avenues of correlation we typically talk about are prevented?

@brentzundel
Copy link
Member

brentzundel commented May 10, 2021 via email

@tplooker
Copy link
Contributor Author

Sure, so here is the example from above

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://w3c-ccg.github.io/ldp-bbs2020/context/v1"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "issuer": "did:example:12345",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "description": "Government of Example Permanent Resident Card.",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "expirationDate": "2029-12-03T12:19:52Z",
  "credentialSubject": {
    "type": ["PermanentResident", "Person"],
    "givenName": "JOHN",
    "familyName": "SMITH",
    "gender": "Male",
    "residentSince": "2015-01-01",
  },
  "proof": {
    "type": "BbsBlsBoundSignatureProof2020",
    "created": "2020-04-26T04:21:07Z",
    "verificationMethod": "did:example:12345#1",
    "proofPurpose": "assertionMethod",
    "proofValue": "jx2VhjyZqUT91e2OhzweJA7G2u2UvmiDtIfmr+wUWNHWno+UOAh0FaNpM8Br+5j2JBkH981/nO1I7/9PFaRrng6NXu7vzDroKtuyj6nHGkMmGq4OMmBzIqRnG3ybin/Sxmu5YwqOxPMRsWH3H+2wSA=="
  }
}

based on the proof.type the verifier knows that in order for the holder to have generated this presentation the holder had to have in its possession the relevant private key of which the public key was known to the issuer and bound during "issuance". The verifier has no idea the value of this public key though. What they do have is the public key of the issuer which is indicated by the "verificationMethod" property.

@brentzundel
Copy link
Member

brentzundel commented May 10, 2021 via email

@tplooker
Copy link
Contributor Author

First, please let me know if I've missed something, or added something unnecessary.

Yes that flow is correct.

how does the issuer incorporate the holder's public key? Mathematically, how does this work?

As is the case with all "messages" signed to produce a BBS signature, if your issuer public key is in G2 then the messages being signed have to result in being commitments in G1. The subject's public key is really just a special case of one of these messages that is being signed, special because:

  1. It uses the base generator in G1 (rather than an issuer specific generator)
  2. Its a pre-commited message (the issuer doesn't know the value that went into creating the commitment i.e the secret key).

As to how the holder proves knowledge of the secret key to the issuer prior to issuance, because the public key is just an ordinary public key in G1 we can reach for more standard and well known signature schemes such as a BLS signature in either basic or proof of possession mode.

@tplooker
Copy link
Contributor Author

That last point is why I felt the linked secret design added complexity that threatened implementability of the scheme as with a blinded public key or linked secret style binding, the proof of knowledge of the secret key becomes another thing you have to define, rather than saying "we'll just use BLS signatures for that piece".

@brentzundel
Copy link
Member

Okay, that helps me to understand better. What is still missing for me is a place where this is written down that we can point to from this spec where the mathematics of it are set out for anyone to review.
The scheme you describe sounds like it could work really well, and it could be much simpler than link secrets.
My concern remains that the work it will take to fully and appropriately document and review this mechanism of private holder binding will fit much better with the work to define the next version of this spec.

I'm feeling pressure to get the 2020 version "wrapped up" quickly and for that to happen in a way that it will be useable for me. For me to be able to use it and recommend it to others, it needs to include private holder binding. Your private holder binding sounds fantastic, but it is, as far as I am aware, only documented within this comment stream.

So I ask again, can we use link secrets here? I agree that they add complexity, but they are already implemented as part of the Ursa BBS+ crate. The mathematics are already well-documented and reviewed.
I know we don't want to use them long term. Using them here doesn't mean that we are stuck with them forever. I fully support abandoning link secrets in future versions of this spec. But as far as I can tell, they are currently the only option for private holder binding that are already documented, reviewed, and implemented. And using them here will allow us to get the 2020 version done so we can focus on the next version.

@mikelodder7
Copy link
Contributor

I agree with @brentzundel. I think that while this proposal is great, requires a good amount of cryptographic review and should not block the release of 2020 given the other changes we'd like to make to the spec after than.

@BasileiosKal
Copy link

Hi all!

I also have a question regarding this proposal.

Question:

If I’m not mistaken, the BBS+ proofs of security against adaptive message attacks here and here, take for granted that no message will be signed using the base generator of G1. If this is not enforced, a Holder could potentially forge a BBS+ signature.

For example, consider an (unblinded) BBS+ signature to the messages m_1, m_2 of the form (A, e, s) where,

A = (g_0 + g_0*HOLDER_SK + h_0*s + h_1*m_1 + h_2*m_2) * (1/(e+ISSUER_SK))

Here, g_0 is the base generator of G1 and h_i are Issuer specific elements. By calculating A*2 one can see that (A*2, 2*s, e) is a valid BBS+ signature to the messages 2 * m_1, 2 * m_2, and a Holder’s secret key; 2*HOLDER_SK + 1, thus achieving forgery.

Proposed Possible Solution:

If the above proves to be a problem, I think that not using the base generator of G1 and committing a message using any other (possible reserved) generator would work. That way the Holder’s secret message (private BLS key) becomes exactly like any other message signed by the Issuer. As a result, all the security proofs will continue to apply. Then, I think that security of the procedure could be proven, since if an adversary tries to create a PoK without knowing the Holder’s committed secret, will essentially have to forge a BBS+ signature.

Please let me know If there is anything wrong with my understanding :)

@mikelodder7
Copy link
Contributor

That's not entirely accurate. The math doesn't exactly check out as you describe.
First off, let's define what a forgery means. It means that Alice initially had signed HOLDER_SK but can now use another value by manipulating the signature to show that something else was signed. Let's assume Alice multiplies by 2 as you suggest and use g_0 and Alice gives the signature and values to another party to run verify.

e(2 * A, W + e * g_2) != e(g_0 + g_0 *HOLDER_SK + h_0*2s + h_1*m_1 + h_2*m_2, g_2)

In this case, verify fails because of the multiply by two. If Alice sends anything other than the actual values signed, this also fails. We can see that using g_0 does not allow forgery in this case.

Next, if we look at the proof generation, this also fails. Now let's change the verify function to receive all signed values except a proof of a signature instead.

Verification becomes

A' = 2 * A * r1
A_bar = -e * A' + r1 * (g_0 + g_0 *HOLDER_SK + h_0*2s + h_1*m_1 + h_2*m_2)

e(A', w) != e(A_bar, g_2)

It still fails in this case. They are not equal. This equation holds even if all the messages are retained and not revealed. If Alice modifies any value including HOLDER_SK, the equation does not balance.

Basically, using g_0 for the HOLDER_SK commitment doesn't necessarily harm it, but is not a good practice either. If Alice modifies the signature in any way or messages then the signature no longer verifies thus immune to adaptive message attacks.

My recommendation is if there is a desire to use the same generator point for HOLDER_SK across the ecosystem we pick a nothing up my sleeve value and use hash to curve to generate it. This results in a generator whose discrete log is unknown and thus cannot be used to manipulate in any way. But we can see that using the same generator here is not harmful.

@BasileiosKal
Copy link

First off, let's define what a forgery means. It means that Alice initially had signed HOLDER_SK but can now use another value by manipulating the signature to show that something else was signed

@mikelodder7 Thank you very much for your reply. I entirely agree, but just to make sure that I correctly understood your definition;
As a forgery, I denote the ability of an adversary to generate a valid signature for some values, on behalf of the Issuer, without knowing the Issuer’s secret key. Furthermore, a forgery can be achieved with an attack like an adaptive chosen-plaintext attack, which BBS+ signatures are proven to be secure against.

e(2 * A, W + e * g_2) != e(g_0 + g_0 *HOLDER_SK + h_0*2s + h_1*m_1 + h_2*m_2, g_2)

It is of-course correct that this equation does not hold, but that is because here Alice tries to verify the new (forged) signature (A*2, 2s, e) on the original messages m_1 and m_2 signed by the Issuer. The new signature, however, is a signature to the messages 2 x m_1 and 2 x m_2 (with ‘ x ’ I denote scalar multiplication), with the committed BLS secret key been 2 x HOLDER_SK + 1. As a result -if I am not mistaken- the equation,

e(A*2, W+e*g_2) = e(g_0 + g_0*(2 x HOLDER_SK + 1) + h_0*(2 x s) + h_1*(2 x m_1) + h_2*(2 x m_2), g_2)

would hold, meaning that (A*2, 2s, e) is a valid signature, created by Alice, on the messages 2 x m_1, 2 x m_2 (which are different from the originally signed messages). Moreover, that signature is created without Alice knowing the Issuer’s secret key. So, if my definition above is correct, Alice does generate a forged BBS+ signature, by performing a chosen-plaintext attack (she has to first get a signature on the m_1, m_2 from the issuer using her HOLDER_SK). In the end, even if the above is not considered a forgery, it does seem to me like a possible security problem.

@mikelodder7
Copy link
Contributor

It’s not a security problem because that is similar to how the zero knowledge proof works. You randomize the signature and hidden values and balance the equation. So multiplying by 2 is similar to making a ZKP. The problem is if you modify the signature you have to modify EVERY value to make it work. Of course this has nothing to do with g_0. That’s a separate problem so there is no security problem here. It’s designed to work this way.

@BasileiosKal
Copy link

It’s not a security problem because that is similar to how the zero knowledge proof works. You randomize the signature and hidden values and balance the equation. So multiplying by 2 is similar to making a ZKP.

I’m sorry, but I don’t think I understand your point. It is true that during ZKP generation A is multiplied by a random number, but I don’t see how that prevents Alice to forge a signature beforehand (assuming g_0 is used to commit messages).

Of course this has nothing to do with g_0

Maybe I’m mistaken, but I think that the above method is only possible if a Holder can make commitments (like a BLS public key) using g_0. If that is not the case, simply multiplying A by something like 4 will create a g_0*4 on the signature that will make the verification fail (of the original BBS+ signature, not the ZKP of knowledge). On the other hand, if we allow commitments to be made using g_0, the Holder could break g_0*4 to g_0 + g_0*3 and treat the first (g_0) as the standard part of the signature and the second (g_0*3) as part of a commitment. For that reason, I believe that it has to do with g_0.

Perhaps a better example will be the following. Suppose again that Alice executes a chosen message attack as before, and gets a BBS+ signature (A, e, s) from the Issuer on the messages m_1, m_2 and her Alice_SK.

The difference now is that instead of multiplying with 2 she will multiply by k = m_3/m_1 where m_3 is a new message that Alice wants to create a proof of knowledge for (but the Issuer hasn’t signed). The new signature now will be (A*k, k*s, e), where,

A*k = g_0  +  g_0*(k x Allice_SK + k - 1) + h_0*(k x s) + h_1*m_3 + h_2*(k x m_2)

As before, that signature is a valid BBS+ signature to the messages m_3, k x m_2. Note however that the Issuer has not signed m_3 (or k x m_2).

Since (A*k, k*s, e) is a valid BBS+ signature, Alice could also create a ZKP of knowledge using this signature, the messages m_3, k x m_2 and k x Allice_SK + k - 1. For example, if she calculates,

A' = k * A * r1
A_bar = -e * A' + (g_0 + g_0 *(k x Allice_SK + k - 1) + h_0*(k x s) + h_1*m_3 + h_2*(k x m_2))*r1

Then the following equation (part of the ZKP of knowledge verification) holds,

e(A', w) = e(A_bar, g_2)

In the end, Alice will manage to convince a Verifier that she possesses a valid signature on m_3 (since she actually has it), while the Issuer has never signed this message. Wouldn’t that be considered a security problem (or a forgery)?

@mikelodder7
Copy link
Contributor

Again look at your equations. They don’t balance. So no this is not a forgery

@mikelodder7
Copy link
Contributor

Another reason is the messages must be revealed or use schnorr proofs. The verifier will only follow the verify equation which makes it so it doesnt balance

@mikelodder7
Copy link
Contributor

The problem with your math is your assuming you can divide in the exponent which you can’t really do in finite fields

@BasileiosKal
Copy link

First, I want to really thank you for taking the time to answer me here!

The problem with your math is your assuming you can divide in the exponent which you can’t really do in finite fields

All messages can be viewed (by Alice) as elements of Z*p, which means that she can divide them (multiply with the inverse technically). Then she could use the result of that division to the exponent. Alternatively, she could raise an element to the power of the inverse of the message she wants to divide with (the Verifier does not need to do those operations). Even if there was a way to ensure that the messages cannot be divided, Alice could just use her attack to gain a BBS+ signature to the message m_1 = 1, and as a result, no division is needed. Lastly, in my first example I just raise to the power of 2, which should work regardless.

Another reason is the messages must be revealed or use schnorr proofs. The verifier will only follow the verify equation which makes it so it doesnt balance

That is true, but Alice doesn’t have to reveal the original messages signed by the Issuer, but the ones she created the forged signature for. The entire point is for her to gain a BBS+ signature for some messages that the Issuer has not signed. For those messages (the ones that she will send to the Verifier), I don’t see why the equations don't balance.

In the pdf here I have a more detailed explanation of why I think those equations hold, using the notation from here (which I think is more readable) and two simpler examples, similar to the ones I mentioned previously.

@mikelodder7
Copy link
Contributor

Thanks for looking into this but your math is still incorrect. It's not as straightforward as you are claiming. Multiplying by m3 means EVERY value is now m3 bigger. If you multiply by 1/m3 it doesn't exactly carry straight thru as these the values are in-the-exponent which means it's not exactly divided. Instead, it would multiple 1/(e+x). This means you can't just multiply by 1/m3 and then assume every attribute is now 1/m3. It doesn't work that way.

@BasileiosKal
Copy link

Multiplying by m3 means EVERY value is now m3 bigger

I don’t really see what the problem is if every value is m3 bigger, I would really appreciate it if you could explain that to me a little more.

If you multiply by 1/m3 it doesn't exactly carry straight thru as these the values are in-the-exponent which means it's not exactly divided. Instead, it would multiple 1/(e+x).

Both (1/(e+x)) and 1/m3 are essentially elements of Z*p and they could be treated as any other Z*p element on the exponents. As a result, I think you could carry them through (since also the operation in any finite field is commutative).

@mikelodder7
Copy link
Contributor

I think this would be better in a meeting than debating mathematics in GitHub. Email me and let’s discuss but your proposal for the vulnerability does not work

@BasileiosKal
Copy link

Hi all!

I met with @mikelodder7 where he was kind enough to explain to me what I was missing.

In the end we concluded that using the base generator of G1 to create a commitment (BLS public key) may not be the best practice, since it can -in theory- lead to a potential forgery.

Although this may not have any practical significance, perhaps it would be best to reserve a different generator (g0’) using a nothing-up-my-sleeve value as @mikelodder7 suggested, for the base generator of BLS keys. Doing that, BLS keys (using g0’) can still be used to authenticate the Holder, and the BBS+ signature will continue to be provably unforgeable.

@OR13
Copy link
Contributor

OR13 commented Apr 25, 2023

I suggest we close this, and focus on cleaning up the spec.

@OR13
Copy link
Contributor

OR13 commented May 1, 2023

Open, for a week, no objections to closing.... and a draft has begun to address, when the draft can be referenced, we will attempt to do so without creating a downref.

https://github.com/BasileiosKal/bbs-bound-signatures/blob/main/draft-bound-bbs-signatures.md

@OR13 OR13 closed this as completed May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending-close The issue will be closed in 7 days if there are no objections.
Projects
None yet
Development

No branches or pull requests

7 participants