Example #1
0
        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));
        }
Example #2
0
        private Proof Respond(Transcript transcript, GroupElementVector nonces, IEnumerable <ScalarVector> 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.
            var challenge = transcript.GenerateChallenge();
            var responses = Knowledge.RespondToChallenge(challenge, secretNonces);

            return(new Proof(nonces, responses));
        }
Example #3
0
        private bool VerifyResponse(Transcript transcript, Proof proof)
        {
            // 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(Statement.CheckVerificationEquation(proof.PublicNonces, challenge, proof.Responses));
        }
Example #4
0
        public void SimpleEquivalenceTest()
        {
            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 });

            var realChallenge = realTranscript.GenerateChallenge();
            var testChallenge = testTranscript.GenerateChallenge();

            Assert.Equal(realChallenge, testChallenge);
        }
    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)));
    }