예제 #1
0
        /// <summary>
        /// Verifies that an <c>IECiphertext</c> was computed correctly.
        /// </summary>
        /// <param name="param">Paramters of the ID escrow scheme.</param>
        /// <param name="ctext"> A ciphertext created with <c>param</c> and <c>pk</c>.</param>
        /// <param name="tokenID">The ID of the U-Prove token this ciphertext is assocaited with.</param>
        /// <param name="pk">Public key of the Auditor (the authority who can decrypt <c>ctext</c>).</param>
        /// <param name="Cxb"> The commitment value (commitment to x_b, with bases g, g1).</param>
        /// <returns><c>true</c> if the ciphertext is valid, and <c>false</c> otherwise.</returns>
        /// <remarks>
        /// The input <c>pk</c> is assumed to be valid, coming from a
        /// trusted source (e.g., a certificate or a trusted store of parameters), and that they
        /// are consistent with the group specified by <c>param</c>.
        /// </remarks>
        public static bool Verify(IDEscrowParams param, IDEscrowCiphertext ctext, byte[] tokenID, IDEscrowPublicKey pk, GroupElement Cxb)
        {
            GroupElement g  = param.ip.Gq.G;   // first base for commitment
            GroupElement g1 = param.ip.G[1];   // second base for commitment

            if (param == null || ctext == null || tokenID == null || pk == null || Cxb == null || g == null || g1 == null)
            {
                throw new ArgumentNullException("null input to Verify");
            }
            if (tokenID.Length == 0)
            {
                throw new ArgumentOutOfRangeException("tokenID has length 0");
            }

            Group         G     = param.ip.Gq;
            FieldZq       F     = param.Zq;
            IDEscrowProof proof = ctext.proof;

            // [1.]Checks on inputs.  These should be done during deserialization -- but we do
            // them explicitly anyway, in case they were missed
            if (!IsGroupElement(G, ctext.E1) || !IsGroupElement(G, ctext.E2) || !IsGroupElement(G, Cxb))
            {
                return(false);
            }

            if (!F.IsElement(proof.c) || !F.IsElement(proof.rOb) ||
                !F.IsElement(proof.rR) || !F.IsElement(proof.rXb))
            {
                return(false);
            }

            // [2.] Recompute inputs to hash (using tilde{x} instead of x'' for this section.)
            GroupElement tildeCxb = G.MultiExponentiate(
                new GroupElement[] { g, g1, Cxb },
                new FieldZqElement[] { proof.rXb, proof.rOb, proof.c }); // tildeCxb = (g^rXb)*(g1^rOb)*(Cxb^c)


            GroupElement tildeE1 = G.MultiExponentiate(
                new GroupElement[] { param.Ge, ctext.E1 },
                new FieldZqElement[] { proof.rR, proof.c }); // tildeE1 = (E1^c)*(ge^rR)

            GroupElement tildeE2 = G.MultiExponentiate(
                new GroupElement[] { param.Ge, pk.H, ctext.E2 },
                new FieldZqElement[] { proof.rXb, proof.rR, proof.c }); // tildeE2 = (ge^rXb)*(H^rR)*(E2^c)

            // [3.]
            FieldZqElement cPrime = ComputeChallenge(param.ip, tokenID, pk, Cxb, ctext.E1, ctext.E2, tildeCxb, tildeE1, tildeE2, ctext.additionalInfo);

            // [4.]
            if (cPrime.Equals(proof.c))
            {
                return(true);
            }

            return(false);
        }