/// <summary>
        /// Compare two <c>IDEscrowProof</c> objects.
        /// </summary>
        /// <param name="proof2">The object to compare against.</param>
        /// <returns>True if equal, false otherwise.</returns>
        public bool Equals(IDEscrowProof proof2)
        {
            if (proof2 == null)
            {
                return(false);
            }
            if (!proof2.c.Equals(c))
            {
                return(false);
            }
            if (!proof2.rXb.Equals(rXb))
            {
                return(false);
            }
            if (!proof2.rR.Equals(rR))
            {
                return(false);
            }
            if (!proof2.rOb.Equals(rOb))
            {
                return(false);
            }

            return(true);
        }
Пример #2
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);
        }
Пример #3
0
        /// <summary>
        /// Create a verifiable encryption of a pseudonym.  The output IECiphertext
        /// object will contain the ciphertext and proof that it was formed correctly.
        /// The pseudonym that is encrypted is (param.Ge)^(x_b), where x_b is an attribute
        /// from the token.
        /// </summary>
        /// <param name="param"> Paramters of the ID escrow scheme.</param>
        /// <param name="pk"> Public key of the Auditor (the authority who can decrypt the output ciphertex).</param>
        /// <param name="tokenID"> The ID of the U-Prove token this ciphertext is assocaited with.</param>
        /// <param name="Cxb"> The commitment value (commitment to x_b, with bases g, g1).</param>
        /// <param name="x_b"> The attributed commited to by <c>Cxb</c></param>
        /// <param name="o_b"> The randomizer value used to create <c>Cxb</c></param>
        /// <param name="additionalInfo"> Arbitrary data that will be cryptographically bound to the ciphertext,
        ///   but <b>NOT</b> encrypted, and will be included with the output ciphertext.
        ///   The integrity of the <c>additionalInfo</c> is protected, i.e., modifying
        ///   the <c>additionalInfo</c> included in the ciphertext will cause verification/decryption to fail.
        ///   The <c>additionalInfo</c> field is sometimes referred to in the cryptographic literature
        ///   as a <i>label</i>. </param>
        /// <param name="preGenRandom">Optional pre-generated random values to be used in the protocol.
        /// Set to <c>null</c> if unused.  The primary use of this field is for testing with test vectors.</param>
        /// <returns>An <c>IECiphertext</c> object with the ciphertext and proof.</returns>
        /// <remarks>
        /// The additionalInfo field may be null to signify that there is no input, all other input
        /// paramters must be non-null.
        ///
        /// Input validation is limited to checking for non-null. We assume that all group & field elements are consistent
        /// with the parameters specified by the IdEscrowParams.
        /// </remarks>
        public static IDEscrowCiphertext VerifiableEncrypt(IDEscrowParams param, IDEscrowPublicKey pk, byte[] tokenID, GroupElement Cxb,
                                                           FieldZqElement x_b, FieldZqElement o_b, byte[] additionalInfo, IDEscrowProofGenerationRandomData preGenRandom = null)
        {
            // Notation & numbering follows draft spec -- subject to change.
            GroupElement g  = param.ip.Gq.G; // first base for commitment Cxb
            GroupElement g1 = param.ip.G[1]; // second base for Cxb

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

            Group   G = param.G;
            FieldZq F = param.Zq;

            if (preGenRandom == null || preGenRandom.HasNullValue())
            {
                preGenRandom = IDEscrowProofGenerationRandomData.Generate(F);
            }

            // [1.] Encrypt
            // Compute E1
            FieldZqElement r  = preGenRandom.R;
            GroupElement   E1 = param.Ge.Exponentiate(r);       // E1 = (g_e)^r

            // Compute E2 = (g_e)^x_b * H^r
            GroupElement E2 = G.MultiExponentiate(new GroupElement[] { pk.H, param.Ge }, new FieldZqElement[] { r, x_b });

            // [2.] Generate proof of correctness
            // [2.a]
            FieldZqElement xbPrime = preGenRandom.XbPrime;
            FieldZqElement rPrime  = preGenRandom.RPrime;
            FieldZqElement obPrime = preGenRandom.ObPrime;

            // [2.b]
            GroupElement CxbPrime = G.MultiExponentiate(new GroupElement[] { g, g1 }, new FieldZqElement[] { xbPrime, obPrime });         // Cxb' = (g^xb')*(g1^ob')
            GroupElement E1Prime  = param.Ge.Exponentiate(rPrime);                                                                        // E1' = (ge)^r'
            GroupElement E2Prime  = G.MultiExponentiate(new GroupElement[] { param.Ge, pk.H }, new FieldZqElement[] { xbPrime, rPrime }); // E2' = ((g_e)^xb')*(H^r')

            // [2.c]
            FieldZqElement c = ComputeChallenge(param.ip, tokenID, pk, Cxb, E1, E2, CxbPrime, E1Prime, E2Prime, additionalInfo);

            // [2.d]
            FieldZqElement rXb = ComputeResponse(xbPrime, c, x_b);
            FieldZqElement rR  = ComputeResponse(rPrime, c, r);
            FieldZqElement rOb = ComputeResponse(obPrime, c, o_b);

            IDEscrowProof      proof = new IDEscrowProof(c, rXb, rR, rOb);
            IDEscrowCiphertext ctext = new IDEscrowCiphertext(E1, E2, proof, additionalInfo);

            return(ctext);
        }
        /// <summary>
        /// Create a new combined ciphertext and proof object from computed values.
        /// Users of this library will not use this function, because ciphertexts will be created
        /// with the <c>VerifiableEncrypt</c> function, which creates the ciphertext.
        /// </summary>
        /// <seealso cref="IDEscrow.IDEscrowFunctions.VerifiableEncrypt"/>
        public IDEscrowCiphertext(GroupElement E1, GroupElement E2, IDEscrowProof proof, byte[] additionalInfo)
        {
            if (E1 == null || E2 == null || proof == null)
            {
                throw new ArgumentNullException("Null inputs IDEscrowCiphertext()");
            }

            this.E1             = E1;
            this.E2             = E2;
            this.proof          = proof;
            this.additionalInfo = additionalInfo;
        }