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));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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 });
            }
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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)));
    }
Exemple #8
0
        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);
        }