public static bool Verify(Transcript transcript, IEnumerable <Statement> statements, IEnumerable <Proof> proofs) { Guard.Same(nameof(proofs), proofs.Count(), statements.Count()); // Before anything else all components in a compound proof commit to the // individual sub-statement that will be proven, ensuring that the // challenges and therefore the responses depend on the statement as a // whole. foreach (var statement in statements) { transcript.CommitStatement(statement); } // After all the statements have been committed, the public nonces are // added to the transcript. This is done separately from the statement // commitments because the prover derives these based on the compound // statements, and the verifier must add data to the transcript in the // same order as the prover. foreach (var proof in proofs) { transcript.CommitPublicNonces(proof.PublicNonces); } // After all the public nonces have been committed, a challenge can be // generated based on transcript state. Since challenges are deterministic // outputs of a hash function which depends on the prover commitments, the // verifier obtains the same challenge and then accepts if the responses // satisfy the verification equation. var challenge = transcript.GenerateChallenge(); return(Enumerable.Zip(statements, proofs, (s, p) => s.CheckVerificationEquation(p.PublicNonces, challenge, p.Responses)).All(x => x)); }
private RespondToChallenge CommitToNonces(Transcript transcript, WasabiRandom random) { // With all the statements committed, generate a vector of random secret // nonces for every equation in underlying proof system. In order to // ensure that nonces are never reused (e.g. due to an insecure RNG) with // different challenges which would leak the witness, these are generated // as synthetic nonces that also depend on the witness data. var secretNonceProvider = transcript.CreateSyntheticSecretNonceProvider(Knowledge.Witness, random); // Actually generate all of the required nonces and save them in an array // because if the enumerable is evaluated several times the results will // be different. // Note, ToArray() is needed to make sure that secretNonces is captured // once and shared between the phases. var equations = Knowledge.Statement.Equations; var secretNonces = secretNonceProvider.Sequence.Take(equations.Count()).ToArray(); // The prover then commits to these, adding the corresponding public // points to the transcript. var publicNonces = new GroupElementVector(equations.Zip(secretNonces, (equation, pointSecretNonces) => pointSecretNonces * equation.Generators)); transcript.CommitPublicNonces(publicNonces); return(() => Respond(transcript, publicNonces, secretNonces)); }
public void ComplexEquivalenceTest() { var protocol = Encoding.UTF8.GetBytes("test protocol"); var realTranscript = new Transcript(protocol); var testTranscript = new TestTranscript(protocol); realTranscript.CommitPublicNonces(new[] { Generators.G }); testTranscript.CommitPublicNonces(new[] { Generators.G }); for (var i = 0; i < 32; i++) { var realChallenge = realTranscript.GenerateChallenge(); var testChallenge = testTranscript.GenerateChallenge(); Assert.Equal(realChallenge, testChallenge); realTranscript.CommitPublicNonces(new[] { Generators.G, Generators.GV }); testTranscript.CommitPublicNonces(new[] { Generators.G, Generators.GV }); } }
private VerifyResponse CommitToNonces(Transcript transcript, Proof proof) { // After all the statements have been committed, the public nonces are // added to the transcript. This is done separately from the statement // commitments because the prover derives these based on the compound // statements, and the verifier must add data to the transcript in the // same order as the prover. transcript.CommitPublicNonces(proof.PublicNonces); return(() => VerifyResponse(transcript, proof)); }
public void SyntheticNoncesSecretDependenceTest() { var protocol = Encoding.UTF8.GetBytes("test TranscriptRng collisions"); // if all synthetic nonce provider get the same randomness, nonce sequences // with different witnesses or commitments should still diverge var rnd = new MockRandom(); rnd.GetBytesResults.Add(new byte[32]); rnd.GetBytesResults.Add(new byte[32]); rnd.GetBytesResults.Add(new byte[32]); rnd.GetBytesResults.Add(new byte[32]); var commitment1 = new[] { Generators.Gx0 }; var commitment2 = new[] { Generators.Gx1 }; var witness1 = new[] { Scalar.One }; var witness2 = new[] { Scalar.Zero }; var transcript1 = new Transcript(protocol); var transcript2 = new Transcript(protocol); var transcript3 = new Transcript(protocol); var transcript4 = new Transcript(protocol); transcript1.CommitPublicNonces(commitment1); transcript2.CommitPublicNonces(commitment2); transcript3.CommitPublicNonces(commitment2); transcript4.CommitPublicNonces(commitment2); var secretNonceGenerator1 = transcript1.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceGenerator2 = transcript2.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceGenerator3 = transcript3.CreateSyntheticSecretNonceProvider(witness2, rnd); var secretNonceGenerator4 = transcript4.CreateSyntheticSecretNonceProvider(witness2, rnd); Assert.Empty(rnd.GetBytesResults); var secretNonce1 = secretNonceGenerator1.GetScalar(); var secretNonce2 = secretNonceGenerator2.GetScalar(); var secretNonce3 = secretNonceGenerator3.GetScalar(); var secretNonce4 = secretNonceGenerator4.GetScalar(); Assert.NotEqual(secretNonce1, secretNonce2); Assert.NotEqual(secretNonce1, secretNonce3); Assert.NotEqual(secretNonce1, secretNonce4); Assert.NotEqual(secretNonce2, secretNonce3); Assert.NotEqual(secretNonce2, secretNonce4); // Since transcript3 and transcript4 share the same public inputs and // witness, with no randomness they should be identical Assert.Equal(secretNonce3, secretNonce4); }
public void SyntheticNoncesTest() { var protocol = Encoding.UTF8.GetBytes("test TranscriptRng collisions"); using var rnd = new SecureRandom(); var commitment1 = new[] { Generators.Gx0 }; var commitment2 = new[] { Generators.Gx1 }; var witness1 = new[] { rnd.GetScalar() }; var witness2 = new[] { rnd.GetScalar() }; var transcript1 = new Transcript(protocol); var transcript2 = new Transcript(protocol); var transcript3 = new Transcript(protocol); var transcript4 = new Transcript(protocol); transcript1.CommitPublicNonces(commitment1); transcript2.CommitPublicNonces(commitment2); transcript3.CommitPublicNonces(commitment2); transcript4.CommitPublicNonces(commitment2); var secretNonceProvider1 = transcript1.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceProvider2 = transcript2.CreateSyntheticSecretNonceProvider(witness1, rnd); var secretNonceProvider3 = transcript3.CreateSyntheticSecretNonceProvider(witness2, rnd); var secretNonceProvider4 = transcript4.CreateSyntheticSecretNonceProvider(witness2, rnd); var secretNonce1 = secretNonceProvider1.GetScalar(); var secretNonce2 = secretNonceProvider2.GetScalar(); var secretNonce3 = secretNonceProvider3.GetScalar(); var secretNonce4 = secretNonceProvider4.GetScalar(); Assert.NotEqual(secretNonce1, secretNonce2); Assert.NotEqual(secretNonce1, secretNonce3); Assert.NotEqual(secretNonce1, secretNonce4); Assert.NotEqual(secretNonce2, secretNonce3); Assert.NotEqual(secretNonce2, secretNonce4); Assert.NotEqual(secretNonce3, secretNonce4); }
public static IEnumerable <Proof> Prove(Transcript transcript, IEnumerable <Knowledge> knowledge, WasabiRandom random) { // Before anything else all components in a compound proof commit to the // individual sub-statement that will be proven, ensuring that the // challenges and therefore the responses depend on the statement as a // whole. foreach (var k in knowledge) { transcript.CommitStatement(k.Statement); } var deferredResponds = new List <DeferredProofCreator>(); foreach (var k in knowledge) { // With all the statements committed, generate a vector of random secret // nonces for every equation in underlying proof system. In order to // ensure that nonces are never reused (e.g. due to an insecure RNG) with // different challenges which would leak the witness, these are generated // as synthetic nonces that also depend on the witness data. var secretNonceProvider = transcript.CreateSyntheticSecretNonceProvider(k.Witness, random); ScalarVector secretNonces = secretNonceProvider.GetScalarVector(); // The prover then commits to these, adding the corresponding public // points to the transcript. var equations = k.Statement.Equations; var publicNonces = new GroupElementVector(equations.Select(equation => secretNonces * equation.Generators)); transcript.CommitPublicNonces(publicNonces); deferredResponds.Add((challenge) => new Proof(publicNonces, k.RespondToChallenge(challenge, secretNonces))); } // With the public nonces committed to the transcript the prover can then // derive a challenge that depend on the transcript state without needing // to interact with the verifier, but ensuring that they can't know the // challenge before the prover commitments are generated. Scalar challenge = transcript.GenerateChallenge(); return(deferredResponds.Select(createProof => createProof(challenge))); }
public void SyntheticNoncesTest() { var protocol = Encoding.UTF8.GetBytes("test TranscriptRng collisions"); var rnd = new SecureRandom(); var commitment1 = new[] { Generators.Gx0 }; var commitment2 = new[] { Generators.Gx1 }; var witness1 = new[] { rnd.GetScalar() }; var witness2 = new[] { rnd.GetScalar() }; var transcript1 = new Transcript(protocol); var transcript2 = new Transcript(protocol); var transcript3 = new Transcript(protocol); var transcript4 = new Transcript(protocol); transcript1.CommitPublicNonces(commitment1); transcript2.CommitPublicNonces(commitment2); transcript3.CommitPublicNonces(commitment2); transcript4.CommitPublicNonces(commitment2); var publicNonceGenerator1 = transcript1.CreateSyntheticPublicNoncesProvider(witness1, rnd); var publicNonceGenerator2 = transcript2.CreateSyntheticPublicNoncesProvider(witness1, rnd); var publicNonceGenerator3 = transcript3.CreateSyntheticPublicNoncesProvider(witness2, rnd); var publicNonceGenerator4 = transcript4.CreateSyntheticPublicNoncesProvider(witness2, rnd); var publicNonce1 = publicNonceGenerator1().First(); var publicNonce2 = publicNonceGenerator2().First(); var publicNonce3 = publicNonceGenerator3().First(); var publicNonce4 = publicNonceGenerator4().First(); Assert.NotEqual(publicNonce1, publicNonce2); Assert.NotEqual(publicNonce1, publicNonce3); Assert.NotEqual(publicNonce1, publicNonce4); Assert.NotEqual(publicNonce2, publicNonce3); Assert.NotEqual(publicNonce2, publicNonce4); Assert.NotEqual(publicNonce3, publicNonce4); }