From 299411397e3e3bd910d58202c665a1f7eb3ef155 Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Mon, 25 Nov 2024 13:27:01 +0200 Subject: [PATCH 1/6] docs: adjusts example for correct number of messages --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 86f64012..67e19b8d 100644 --- a/README.md +++ b/README.md @@ -474,17 +474,17 @@ const sig: BBSSignature = ...; // Prover prepares the attributes he wants to disclose, i.e. attribute index 2 and 4 (indexing is 0-based), and the ones he wants to hide. const revealedMsgIndices: Set = new Set(); revealedMsgIndices.add(2); -revealedMsgIndices.add(4); +revealedMsgIndices.add(3); // revealedMsgs are the attributes disclosed to the verifier const revealedMsgs: Map = new Map(); revealedMsgs.set(2, messages[2]); +revealedMsgs.set(3, messages[3]); // unrevealedMsgs are the attributes hidden from the verifier const unrevealedMsgs: Map = new Map(); unrevealedMsgs.set(0, messages[0]); unrevealedMsgs.set(1, messages[1]); -unrevealedMsgs.set(3, messages[3]); ``` Since there is only 1 kind of proof, i.e. the knowledge of a BBS signature and the signed attributes, there would be only 1 `Statement`. From fa33eacbc648e9749e2423daf22eb7a78f16c4e0 Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Mon, 25 Nov 2024 13:29:03 +0200 Subject: [PATCH 2/6] docs: little adjustments to comment lines --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 67e19b8d..afc55381 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,8 @@ const pk: BBSPublicKey; // The signature const sig: BBSSignature = ...; -// Prover prepares the attributes he wants to disclose, i.e. attribute index 2 and 4 (indexing is 0-based), and the ones he wants to hide. +// Prover prepares the attributes he wants to disclose, +// i.e. attribute index 2 and 4 (indexing is 0-based), and the ones he wants to hide. const revealedMsgIndices: Set = new Set(); revealedMsgIndices.add(2); revealedMsgIndices.add(3); @@ -492,18 +493,18 @@ Since there is only 1 kind of proof, i.e. the knowledge of a BBS signature and t ```ts import { Statement, Statements } from '@docknetwork/crypto-wasm-ts' -// Create a BBS signature, true indicates that attributes/messages are arbitrary bytes and should be encoded first +// Create a BBS signature, true indicates that attributes/messages are arbitrary bytes and should be encoded first. const statement1 = Statement.bbsSignatureProverConstantTime(paramsDeterministc, revealedMsgs, true); const statements = new Statements(); statements.add(statement1); -// Optional context of the proof, this can specify the reason why the proof was created or date of the proof, or self-attested attributes (as JSON string), etc +// Optional context of the proof, this can specify the reason why the proof was created or date of the proof, or self-attested attributes (as JSON string), etc. const context = stringToBytes('some context'); ``` Once it has been established what needs to be proven, `ProofSpec` needs to be created which represents all the requirements. Both the prover and verifier should independently construct this `ProofSpec`. Note that there are no `MetaStatements` as there are no -other conditions on the witnesses and thus its empty +other conditions on the witnesses and thus its empty. ```ts import { ProofSpec, MetaStatements } from '@docknetwork/crypto-wasm-ts'; @@ -531,8 +532,8 @@ const nonce = stringToBytes('a unique nonce given by verifier'); const proof = CompositeProof.generate(proofSpec, witnesses, nonce); ``` -Verifier can now verify this proof. Note that the verifier does not and must not receive `ProofSpec` from prover, it -needs to generate on its own. +Verifier can now verify this proof. Note that the verifier does not and must not receive `ProofSpec` from prover, +it needs to generate on its own. ```ts console.assert(proof.verify(proofSpec, nonce).verified); From c43fca47bb18e704ea1e8dde09bc1e305bd8aa25 Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Mon, 25 Nov 2024 13:29:42 +0200 Subject: [PATCH 3/6] docs: Improves documentation for composite proof verifier example This is important to indicate to the user that constructing the ProofSpec is a bit different for verifiers and doesn't include witnesses. --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index afc55381..384b90bf 100644 --- a/README.md +++ b/README.md @@ -534,9 +534,18 @@ const proof = CompositeProof.generate(proofSpec, witnesses, nonce); Verifier can now verify this proof. Note that the verifier does not and must not receive `ProofSpec` from prover, it needs to generate on its own. +Also, note the usage of `bbsSignatureVerifierConstantTime` instead. ```ts -console.assert(proof.verify(proofSpec, nonce).verified); +const statement1 = Statement.bbsSignatureVerifierConstantTime(sigParams, keyPair.publicKey, revealedMsgs, true); +const statements = new Statements(); +statements.add(statement1); +const context = stringToBytes('some context'); + +const ms = new MetaStatements(); +const verifierProofSpec = new ProofSpec(statements, ms, [], context); + +console.assert(proof.verify(verifierProofSpec, nonce).verified); ``` ##### BBS signatures over varying number of messages From 0872b46a5bb11a0b954842780d5622a5973f78ea Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Mon, 25 Nov 2024 13:30:12 +0200 Subject: [PATCH 4/6] docs: improves some comments in tests --- .../variable-number-of-messages.spec.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/composite-proofs/variable-number-of-messages.spec.ts b/tests/composite-proofs/variable-number-of-messages.spec.ts index 3590d50c..79f052b3 100644 --- a/tests/composite-proofs/variable-number-of-messages.spec.ts +++ b/tests/composite-proofs/variable-number-of-messages.spec.ts @@ -3,12 +3,12 @@ import { buildWitness, encodeMessageForSigningIfPS, Scheme } from '../scheme'; import { checkResult, getParamsAndKeys, proverStmt, signAndVerify, stringToBytes, verifierStmt } from '../utils'; describe(`Proving knowledge of 1 ${Scheme} signature where some of the attributes are null, i.e. not applicable`, () => { - it('works', async () => { + it('encodes messages with null values in a meaningful way', async () => { // Load the WASM module await initializeWasm(); - // Messages to sign; the messages are attributes of a user like SSN (Social Security Number), name, email, etc. The attributes - // N/A don't apply to this user + // Messages to sign; the messages are attributes of a user like SSN (Social Security Number), name, email, etc. + // The attributes N/A don't apply to this user. const messages: Uint8Array[] = []; // Comma separated indices of N/A messages. An efficient way, especially in large number of messages, could be to use a bitvector // where an unset bit would indicate N/A @@ -35,15 +35,15 @@ describe(`Proving knowledge of 1 ${Scheme} signature where some of the attribute const messageCount = messages.length; const label = stringToBytes('My sig params in g1'); - // Signers keys + // Signer's keys const [params, sk, pk] = getParamsAndKeys(messageCount, label); // Signer knows all the messages and signs const [sig, result] = signAndVerify(messages, params, sk, pk, true); checkResult(result); - // User reveals his name, high school year and city to verifier, i.e. indices 2, 4 and 8. He also needs to reveal first - // attribute (index 0) which indicates which attributes don't apply to him. + // User reveals his name, high school year, and city to verifier, i.e. indices 2, 4 and 8. + // He also needs to reveal first attribute (index 0) which indicates which attributes don't apply to him. const revealedMsgIndices: Set = new Set(); revealedMsgIndices.add(0); revealedMsgIndices.add(2); @@ -62,7 +62,7 @@ describe(`Proving knowledge of 1 ${Scheme} signature where some of the attribute const statement1 = proverStmt(params, revealedMsgs, pk, true); const statements = new Statements(statement1); - // Both the prover (user) and verifier should independently construct this `ProofSpec` but only for testing, i am reusing it. + // Prover constructing their ProofSpec const proverProofSpec = new ProofSpec(statements, new MetaStatements()); expect(proverProofSpec.isValid()).toEqual(true); @@ -73,6 +73,7 @@ describe(`Proving knowledge of 1 ${Scheme} signature where some of the attribute const statement2 = verifierStmt(params, revealedMsgs, pk, true); const verifierStatements = new Statements(statement2); + // Verifier constructing their own ProofSpec const verifierProofSpec = new ProofSpec(verifierStatements, new MetaStatements(), []); expect(verifierProofSpec.isValid()).toEqual(true); checkResult(proof.verify(verifierProofSpec)); From e8570f0b7587142943eb9126e86a8e2d37b2b5f6 Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Mon, 25 Nov 2024 13:30:26 +0200 Subject: [PATCH 5/6] docs: changes varying number of messages to with null messages It makes more sense here to say null messages rather than varying number of messages which would indicate that the the count of messages being encoded in the signature changes. --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 384b90bf..4b9534fe 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ the [WASM wrapper](https://github.com/docknetwork/crypto-wasm). - [Terminology](#terminology) - [Examples](#examples) - [Selective disclosure](#selective-disclosure) - - [BBS signature over varying number of messages](#bbs-signature-over-varying-number-of-messages) + - [BBS signature over null-valued messages](#bbs-signatures-over-null-valued-messages) - [Multiple BBS signatures](#multiple-bbs-signatures) - [BBS signature together with accumulator membership](#bbs-signature-together-with-accumulator-membership) - [Getting a blind signature](#getting-a-blind-signature) @@ -548,14 +548,18 @@ const verifierProofSpec = new ProofSpec(statements, ms, [], context); console.assert(proof.verify(verifierProofSpec, nonce).verified); ``` -##### BBS signatures over varying number of messages +##### BBS signatures over null-valued messages -The examples shown here have assumed that the number of messages for given signature params is fixed but that might not be always true. -An example is where some of the messages in the signature are null (like N/A) in certain signatures. Eg, when the messages are attributes -in a credential that specifies the educational qualifications and institutes of a person, someone with a high school level education will -have N/A for attributes like university name, major, etc. One way to deal with it is to decide some sentinel value like 0 for all the N/A -attributes and disclose those attributes while creating a proof. Other is to have certain attribute in the credential specify which attribute -indices that are N/A and always reveal this attribute. A complete example of the latter is shown in this [test](tests/composite-proofs/variable-number-of-messages.spec.ts). +The examples above assumed all messages have values in them. However, in some cases, one or more attributes will be null within the credential. +An example in which some of the messages correspond to attributes with null values (e.g. N/A) is a education qualification credential of a person. Someone with a highschool-level education will +have N/A for attributes like university name, major, etc. + +One way to deal with this is to decide on some sentinel value like 0 or 'N/A' for all the null attributes +and disclose those values to the verifier. +Another is to have a certain attribute (e.g. first message) in the credential specify which attribute +indices are null and always reveal this attribute. +A complete example of the latter is shown in this +[test](tests/composite-proofs/variable-number-of-messages.spec.ts). ##### Multiple BBS signatures From 3c8a0be0ada77262e79bfd65d06b55873c344500 Mon Sep 17 00:00:00 2001 From: Ahmed Elghareeb Date: Wed, 27 Nov 2024 17:02:31 +0200 Subject: [PATCH 6/6] docs: adjust selective disclosure example to use 5 attributes --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4b9534fe..baed99e8 100644 --- a/README.md +++ b/README.md @@ -462,7 +462,9 @@ to reveal his last name and city, but not any other attribute while proving that ```ts // The attributes, [SSN, first name, last name, email, city] -const messages: Uint8Array[] = [...]; +const messages: Uint8Array[] = [ + "230-95-4628", "Harry", "Potter", "harry@potter.com", "Little Whinging" +].map(element => stringToBytes(element)); // Public values const params: BBSSignatureParams; @@ -475,17 +477,18 @@ const sig: BBSSignature = ...; // i.e. attribute index 2 and 4 (indexing is 0-based), and the ones he wants to hide. const revealedMsgIndices: Set = new Set(); revealedMsgIndices.add(2); -revealedMsgIndices.add(3); +revealedMsgIndices.add(4); // revealedMsgs are the attributes disclosed to the verifier const revealedMsgs: Map = new Map(); revealedMsgs.set(2, messages[2]); -revealedMsgs.set(3, messages[3]); +revealedMsgs.set(4, messages[4]); // unrevealedMsgs are the attributes hidden from the verifier const unrevealedMsgs: Map = new Map(); unrevealedMsgs.set(0, messages[0]); unrevealedMsgs.set(1, messages[1]); +unrevealedMsgs.set(1, messages[3]); ``` Since there is only 1 kind of proof, i.e. the knowledge of a BBS signature and the signed attributes, there would be only 1 `Statement`.