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 SyntheticNoncesThrows() { var protocol = Encoding.UTF8.GetBytes("empty witness not allowed"); var rnd = new SecureRandom(); var transcript = new Transcript(protocol); Assert.ThrowsAny <ArgumentException>(() => transcript.CreateSyntheticSecretNonceProvider(new Scalar[0], rnd)); }
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 SyntheticNoncesVectorTest(int size) { var protocol = Encoding.UTF8.GetBytes("witness size"); var rnd = new SecureRandom(); var witness = new Scalar[size]; var transcript = new Transcript(protocol); var secretNonceProvider = transcript.CreateSyntheticSecretNonceProvider(witness, rnd); var secretNonce = secretNonceProvider.Sequence.First(); Assert.Equal(secretNonce.Count(), witness.Length); }
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))); }