Example #1
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>
        /// Compare two <c>IDEscrowPublicKey</c> objects
        /// </summary>
        /// <param name="pk2">To be compared to this object</param>
        /// <returns>True if equal, false otherwise.</returns>
        public bool Equals(IDEscrowPublicKey pk2)
        {
            if (pk2 == null)
            {
                return(false);
            }

            if (!pk2.H.Equals(this.h))
            {
                return(false);
            }

            return(true);
        }
Example #3
0
        // Compute c = H(IP, T, H, Cxb, E1, E2, Cxb', E1', E2', additionalInfo)
        private static FieldZqElement ComputeChallenge(IssuerParameters ip, byte[] tokenID, IDEscrowPublicKey pk, GroupElement Cxb, GroupElement E1, GroupElement E2, GroupElement CxbPrime, GroupElement E1Prime, GroupElement E2Prime, byte[] additionalInfo)
        {
            HashFunction hasher = ip.HashFunction;
            FieldZq      F      = ip.Zq;

            hasher.Hash(ip.UidP);
            hasher.Hash(tokenID);
            hasher.Hash(pk.H);
            hasher.Hash(Cxb);
            hasher.Hash(E1);
            hasher.Hash(E2);
            hasher.Hash(CxbPrime);
            hasher.Hash(E1Prime);
            hasher.Hash(E2Prime);
            hasher.Hash(additionalInfo);   // additionalInfo may be null, and Hash() will handle this correctly.

            return(F.GetElementFromDigest(hasher.Digest));
        }
Example #4
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);
        }
Example #5
0
        /// <summary>
        ///  Verifies that an <c>IECiphertext</c> was computed correctly.
        ///  This is a wrapper around <c>IEFunctions.Verify</c> for use with U-Prove.
        /// </summary>
        /// <param name="escrowParams">Parameters of the ID escrow scheme</param>
        /// <param name="ctext">A ciphertext created with <c>param</c> and <c>pk</c>. </param>
        /// <param name="proof">The associated U-Prove presentation proof.</param>
        /// <param name="token">The associated U-Prove token.</param>
        /// <param name="pk">The auditor's public key</param>
        /// <returns> True if the ciphertext is valid, false if it is invalid.</returns>
        /// <remarks>The identity <b>must be</b> the first committed attribute in the proof (as
        /// in <c>UProveVerifiableEncrypt</c>).</remarks>
        public static bool UProveVerify(IDEscrowParams escrowParams, IDEscrowCiphertext ctext, PresentationProof proof, UProveToken token, IDEscrowPublicKey pk)
        {
            if (escrowParams == null || ctext == null || proof == null || token == null || pk == null)
            {
                throw new ArgumentException("null input to UProveVerify");
            }

            if (proof.Commitments == null || proof.Commitments.Length < 1)
            {
                throw new InvalidUProveArtifactException("invalid inputs to UProveVerifiableEncrypt");
            }

            GroupElement Cx1 = proof.Commitments[0].TildeC;

            byte[] tokenId = ProtocolHelper.ComputeTokenID(escrowParams.ip, token);
            return(IDEscrowFunctions.Verify(escrowParams, ctext, tokenId, pk, Cx1));
        }
Example #6
0
        /// <summary>
        /// Create a verifiable encryption of a pseudonym based on a U-Prove presentation proof.  This is a wrapper
        /// of <c>VerifiableEncrypt</c>.
        ///
        /// </summary>
        /// <param name="escrowParams"> Parameters of the ID escrow scheme</param>
        /// <param name="escrowPublicKey">  Public key of the Auditor (the authority who can decrypt the output ciphertex).</param>
        /// <param name="token"> The U-Prove token corresponding to the <c>proof</c>. </param>
        /// <param name="additionalInfo">See documentation of <c>VerifiableEncrypt</c></param>
        /// <param name="proof">A U-Prove prsentation proof.</param>
        /// <param name="cpv">Commitment opening information, output when generating <c>proof</c>.</param>
        /// <param name="idAttributeIndex"> Index of the attribute to use for identity escrow (1-based indexing). This attribute <b>must be</b>
        ///                                 the first commited attribute (take care if using multiple extensions). </param>
        /// <param name="attributes"> Attributes in <c>token</c>.</param>

        /// <returns></returns>
        public static IDEscrowCiphertext UProveVerifableEncrypt(IDEscrowParams escrowParams, IDEscrowPublicKey escrowPublicKey,
                                                                UProveToken token, byte[] additionalInfo, PresentationProof proof,
                                                                CommitmentPrivateValues cpv, int idAttributeIndex, byte[][] attributes)
        {
            if (token == null || escrowParams == null || proof == null || cpv == null)
            {
                throw new ArgumentNullException("null input to UProveVerifiableEncrypt");
            }

            if (proof.Commitments == null || proof.Commitments.Length < 1 ||
                attributes.Length < idAttributeIndex || cpv.TildeO == null || cpv.TildeO.Length < 1)
            {
                throw new InvalidUProveArtifactException("invalid inputs to UProveVerifiableEncrypt");
            }


            byte[]         tokenId = ProtocolHelper.ComputeTokenID(escrowParams.ip, token);
            GroupElement   Cx1     = proof.Commitments[0].TildeC;                                                                       // x1 is the first committed attribute
            FieldZqElement x1      = ProtocolHelper.ComputeXi(escrowParams.ip, idAttributeIndex - 1, attributes[idAttributeIndex - 1]); // arrays are 0-based
            FieldZqElement tildeO1 = cpv.TildeO[0];

            return(IDEscrowFunctions.VerifiableEncrypt(escrowParams, escrowPublicKey, tokenId, Cx1, x1, tildeO1, additionalInfo));
        }