Esempio n. 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));
        }
Esempio n. 2
0
        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)));
        }