Skip to content

Commit

Permalink
Merge pull request #304 from decentralized-identity/vasilis/appendix-d
Browse files Browse the repository at this point in the history
Update proofgen algorithm explanation
  • Loading branch information
BasileiosKal authored Dec 21, 2023
2 parents 0541138 + d70140d commit f8135b0
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions draft-irtf-cfrg-bbs-signatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ Procedure:

### CoreProofGen

This operation computes a zero-knowledge proof-of-knowledge of a signature, while optionally selectively disclosing from the original set of signed messages. The Prover may also supply a presentation header (`ph`). See (#header-and-presentation-header-usage) for more details. Validating the resulting proof (using the `CoreProofVerify` algorithm defined in (#coreproofverify)), guarantees the integrity and authenticity of the revealed messages, as well as the possession of a valid signature (for the public key `PK`) by the Prover.
This operation computes a zero-knowledge proof-of-knowledge of a signature, while optionally selectively disclosing from the original set of signed messages. The Prover may also supply a presentation header (`ph`). See (#header-and-presentation-header-usage) for more details. Validating the resulting proof (using the `CoreProofVerify` algorithm defined in (#coreproofverify)), guarantees the integrity and authenticity of the revealed messages, as well as the possession of a valid signature (for the public key `PK`) by the Prover. See (#proof-generation-and-verification-algorithmic-explanation) for a high level explanation on the inner-workings of the algorithm.

The `CoreProofGen` operation will accept that signature as an input. It is RECOMMENDED to validate that signature, using the inputted public key `PK` and `generators` set, against the supplied `messages` and `header`, with the `CoreVerify` operation defined in (#coreverify).

Expand Down Expand Up @@ -846,7 +846,7 @@ Procedure:

## Proof Protocol Subroutines

This section describes the subroutines used by the `CoreProofGen` ((#coreproofgen)) and `CoreProofVerify` ((#coreproofverify)) operations.
This section describes the subroutines used by the `CoreProofGen` ((#coreproofgen)) and `CoreProofVerify` ((#coreproofverify)) operations. See (#proof-generation-and-verification-algorithmic-explanation), for a high-level intuitive overview of the procedure used to generate and verify a BBS proof.

### Proof Initialization

Expand Down Expand Up @@ -2456,7 +2456,7 @@ This document does not make any requests of IANA.
# Acknowledgements
The authors would like to acknowledge the significant amount of academic work that preceeded the development of this document. In particular the original work of [@BBS04] which was subsequently developed in [@ASM06] and in [@CDL16]. This last academic work is the one mostly used by this document.
The authors would like to acknowledge the significant amount of academic work that preceeded the development of this document. In particular the original work of [@BBS04] which was subsequently developed in [@ASM06] [@CL04] [@BBDT16] [@CDL16] and in [@TZ23]. This last academic work is the one mostly used by this document.
The current state of this document is the product of the work of the Decentralized Identity Foundation Applied Cryptography Working group, which includes numerous active participants. In particular, the following individuals contributed ideas, feedback and wording that influenced this specification:
Expand Down Expand Up @@ -3200,55 +3200,61 @@ scalar = {{ $H2sFixture.bls12-381-sha-256.h2s.scalar }}
# Proof Generation and Verification Algorithmic Explanation
The following section provides a high level explanation of how the ProofGen and ProofVerify operations work. ProofGen can be categorized as a generic non-interactive zero-knowledge proof-of-knowledge (`nizk`). A `nizk` works as follows; Assume the group points `J_0`, `J_1`, ..., `J_n` and the exponents `e_0`, `e_1`, ..., `e_n`. Assume also that all the group point are publicly known, while only the exponent `e_0` is known to the verifier and the exponents `e_1`, ..., `e_n` are known only by the Prover. The `nizk` can be used to prove a relationship of the form,
The following section provides a high-level explanation of how the `CoreProofGen` and `CoreProofVerify` operations work, as presented in Appendix B of [@TZ23] and used by this document. The `CoreProofGen` procedure uses a generic non-interactive zero-knowledge proof-of-knowledge (`nizk`) protocol, executed between a Prover and a Verifier. A `nizk` works as follows; Assume the group points `J_0`, `J_1`, ..., `J_n` and the exponents `e_0`, `e_1`, ..., `e_n`. Assume also that all the group points are publicly known, while only the exponent `e_0` is known to the Verifier of the `nizk` and the exponents `e_1`, ..., `e_n` are known only by the Prover of the protocol. The `nizk` can be used to prove a relationship of the form,
```
J_O * e_0 = J_1 * e_1 + J_2 * e_2 + ... + J_n * e_n
```
While revealing nothing about the secret exponents (i.e., `e_1`, ..., `e_n`).
While revealing nothing about the secret exponents (i.e., `e_1`, ..., `e_n`), other than the fact that the Prover knows them.
For BBS, let the Prover be in possession of a BBS signature `(A, e)` on messages `msg_1, ..., msg_L` and a `domain` value (see [Sign](#signature-generation-sign)). Let `A = B * (1/(e + SK))` where `SK` the signer's secret key and,
For BBS, let the Prover be in possession of a BBS signature `(A, e)` on messages `msg_1, ..., msg_L` and a `domain` value (see `CoreSign` defined in (#coresign)). Let `A = B * (1/(e + SK))` where `SK` the Signer's secret key and,
```
[1] B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
[1] B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
```
Let `(i1, ..., iR)` be the indexes of the messages the Prover wants to disclose and `(j1, ..., jU)` be the indexes corresponding to undisclosed messages (i.e., `(j1, ..., jU) = (1, 2, ..., L) \ (i1, ..., iR)`). To prove knowledge of a signature on the disclosed messages, work as follows;
- Prove possession of a valid signature. As defined above, a signature `(A, e)`, on messages `msg_1, ..., msg_L` is valid, if `A = B * 1/(e + SK)`, where `B` as in \[1\]. However we cannot reveal neither `A`, `e` nor `B` to the verifier (signature is uniquely identifiable and `B` will reveal information about the signed messages, even the undisclosed ones). To get around this, we need to hide the signature `(A, e)` and the value of `B`, in a way that will allow proving knowledge of such ellements with the aformentioned relationship (i.e., that `A = B * 1/(e + SK)`), without revealing their value. We do this by randomizing them. To do that, take uniformly random `r1` in `[1, r-1]`, and calculate,
- Prove possession of a valid signature. As defined above, a signature `(A, e)`, on messages `msg_1, ..., msg_L` is valid if `A = B * 1/(e + SK)`, where `B` as in \[1\]. However, the Prover cannot reveal neither `A`, `e` nor `B` to the Verifier (signature is uniquely identifiable and `B` will reveal information about the signed messages, even the undisclosed ones). To get around this, the Prover needs to hide the signature `(A, e)` and the value of `B`, in a way that will allow proving knowledge of such elements with the aforementioned relationship (i.e., that `A = B * 1/(e + SK)`), without revealing their value. The Prover will do this by randomizing them. To do that, they take uniformly random `r1, r2` in `[1, r-1]`, and calculate,
```
[2] Abar = A * r1,
[3] Bbar = B * r1 + Abar * (-e)
```
```
[2] Abar = A * (r1 * r2)
[3] D = B * r2
[4] Bbar = D * r1 + Abar * (-e)
```
The values `(Abar, Bbar)` will be part of the proof and are used to prove possession of a BBS signature, without revealing the signature itself. Note that; if `Abar` and `Bbar` are constructed using a valid BBS signatures as above, then `Abar * SK = Bbar => e(Abar, PK) = e(Bbar, BP2)` where `SK`, `PK` the signer's secret and public key and `BP2` the base element in `G2` (used to create the signer’s `PK`, see (#public-key)). This last equation is something that the verifier can check. This also serves to bind the proof to the signer's `PK`.
The values `(Abar, D, Bbar)` will be part of the proof and are used to prove possession of a BBS signature, without revealing the signature itself. Note that; if `Abar`, `D` and `Bbar` are constructed using a valid BBS signature as above, then `Abar * SK = Bbar` which is equivalent to `e(Abar, PK) = e(Bbar, BP2)`, where `SK`, `PK` the Signer's secret and public key and `BP2` the base generator of `G2` (used to create the Signer’s `PK`, see (#public-key)). This last equation is something that the Verifier can check using the Signer's `PK`.
- Prove that the disclosed messages are signed by that signature. Set the following,
- Prove that the disclosed messages are signed as part of that signature. The Prover will start by setting the following,
```
[4] D = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR
[5] r1' = r1 ^ -1 mod r
```
```
[5] r2' = (1 / r2) mod r
```
If the `Abar` and `Bbar` values are constructed using a valid BBS signature as in \[2\] and \[3\], then the following equation will hold,
If the `Abar`, `D` and `Bbar` values are constructed using a valid BBS signature as in \[2\], \[3\] and \[4\], then the following will hold,
```
[6] D = Bbar * r1' + Abar * (e * r1') - H_ji * msg_j1 - ...
... - H_jU * msg_jU
```
```
[6] P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR =
D * r2' - H_ji * msg_j1 - ... - H_jU * msg_jU
```
Note that the Verifier will know the elements in the left side of \[6\] (i.e., `P1`, `Q_1`, `H_i1`, ..., `H_iR` and the disclosed messages: `msg_i1`, ..., `msg_iR`) as well as the base points of the right side (i.e., the points `D` and `H_j1, ..., H_jU`). They will not however know the exponents on the right side of \[6\] (i.e., `r2'` and the undisclosed messages: `msg_j1, ..., msg_jU`). The same holds for equation \[4\] where the Verifier will know the left side of the equation (i.e., `Bbar`) and the base points of the right side (i.e., `D` and `Abar`) but not the exponents (i.e., `r1` and `-e`).
To convince the Verifier that both \[4\] and \[6\] hold, the Prover can use a `nizk`, to prove that they know the exponents that satisfy those equations, without disclosing them.
Note that if the value `D` is constructed correctly (as in \[3\]), then `B = D * r2'`. Proving knowledge of \[6\] corresponds to proving knowledge of `r2'`, which means that the Prover does actually know a value `B = D * r2'`. If \[6\] holds, then that `B` value that the Prover knows (i.e., `D * r2'`) will also have the "correct form" for `B` (as in \[1\]), including all (the disclosed and "some" undisclosed) messages.
Note that the verifier will know the elements in the left side of \[6\] (i.e., `D`, or rather they will know all the values needed to calculate `D`, as it depends on the public `doamin` value and the disclosed messages) but not the exponents in the right side (i.e., `r1'`, `e` and the undisclosed messages: `msg_j1, ..., msg_jU`). However, using a `nizk`, the Prover can convince the verifier that they (the Prover) know the exponents that satisfy that equation, without disclosing them.
All that remains is proving that this `B` value the Prover knows, is also "signed" by the Signer i.e., that the Prover also knows values `A` and `e`, such that `A = B * 1/(e + SK)` or, equivalently, that `e(A, PK + BP2 * e) = e(B, BP2)`, which is what `CoreVerify` checks to validate a signature (see (#coreverify)).
If the above equation (\[6\]) holds, and `e(Abar, PK) = e(Bbar, BP2)`, one could solve \[6\] to get `B = Bbar * r1' + Abar * e * r1'` (where `B` as in \[1\]). Note that `B` will also contain the disclosed messages. Then, using the properties of pairings, one can see that,
Note that, the Prover will use a `nizk` to showcase (among other things), knowledge of values `r1` and `e` so that \[4\] holds (`Bbar`, `D` and `Abar` will be part of the proof and hence known to the Verifier). Setting `r1' = (1 / r1) mod r` (note that proving knowledge of `r1` indirectly proves knowledge of `r1'` as well), using \[4\] and the fact that `e(Abar, PK) = e(Bbar, BP2)` we can get that,
```
e(Abar * r1', PK + BP2 * e) = (B, BP2)
e(Abar * r1' * r2', PK + BP2 * e) = e(D * r2', BP2) = e(B, BP2)
```
which is exactly what [Verify](#signature-verification-verify) checks for `A = Abar * r1'`. So seting `A = Abar * r1'`, the values `A`, `e`, `B` will form a valid BBS signature. Note that the verifier doesn't know `r1'`, `e` or all the values to compute `B`. However, they know that the Prover knows them, and as we saw above, knowledge of those values means knowledge of a valid signature on (among others) the disclosed messages.
Note that the above is what `CoreVerify` checks, for `A = Abar * r1' * r2'`. Since the Prover showcased knowledge of `r1'` and `r2'` and revealed `Abar` as part of the proof, the Verifier can be assured that the Prover knows the value `A = Abar * r1' * r2'`. So setting `A = Abar * r1' * r2'`, the values `A`, `e`, `B` that the Prover showed knowledge of, will form a valid BBS signature. Note that the Verifier doesn't know `A` (since they don't know `r1'` and `r2'`), `e` or `B` (since they don't know `r2'` or the undisclosed messages). However, they know that the prover knows them and as we saw above, these values form a valid signature on (among others) the disclosed messages.
To sum up; in order to validate the proof, a verifier checks that `e(Abar, PK) = e(Bbar, BP2)` and verifies the `nizk`. Validating the proof, will guarantee the authenticity and integrity of the disclosed messages, as well as knowledge of the undisclosed messages and of the signature.
To sum up; in order to validate the proof, a Verifier checks that `e(Abar, PK) = e(Bbar, BP2)` and verifies the `nizk`. Validating the proof will guarantee the authenticity and integrity of the disclosed messages, as well as knowledge of the undisclosed messages and of the signature.
# Document History
Expand Down

0 comments on commit f8135b0

Please sign in to comment.