Exemplo n.º 1
0
        /// <summary>
        /// Verifies a U-Prove token signature.
        /// </summary>
        /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param>
        /// <param name="upt">The U-Prove token to verify.</param>
        /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception>
        public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (upt.H == Gq.Identity)
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)");
            }
            GroupElement[]   bases     = new GroupElement[2];
            FieldZqElement[] exponents = new FieldZqElement[2];

            HashFunction hash = ip.HashFunction;

            hash.Hash(upt.H);
            hash.Hash(upt.PI);
            hash.Hash(upt.SigmaZPrime);
            bases[0] = Gq.G; exponents[0] = upt.SigmaRPrime;
            bases[1] = ip.G[0]; exponents[1] = upt.SigmaCPrime.Negate();
            hash.Hash(Gq.MultiExponentiate(bases, exponents));
            bases[0] = upt.H; exponents[0] = upt.SigmaRPrime;
            bases[1] = upt.SigmaZPrime; exponents[1] = upt.SigmaCPrime.Negate();
            hash.Hash(Gq.MultiExponentiate(bases, exponents));
            if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest))
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token signature");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Verifies a non-revocation proof.
        /// </summary>
        /// <param name="ip">The issuer parameters associated with the proof.</param>
        /// <param name="revocationCommitmentIndex">The 0-based index corresponding to the revocation commitment in the proof.</param>
        /// <param name="proof">The presentation proof.</param>
        /// <param name="nrProof">The non-revocation proof.</param>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public void VerifyNonRevocationProof(IssuerParameters ip, int revocationCommitmentIndex, PresentationProof proof, NonRevocationProof nrProof)
        {
            Group        Gq       = ip.Gq;
            FieldZq      Zq       = Gq.FieldZq;
            GroupElement tildeCid = proof.Commitments[revocationCommitmentIndex].TildeC;
            // T1 = (V Y^-1 Cd^-1)^c' * X^s1 * (tildeCid K)^-s2 * g1^s3
            GroupElement T1 = Gq.MultiExponentiate(
                new GroupElement[] {
                Accumulator *nrProof.Y.Exponentiate(Zq.NegativeOne) * nrProof.Cd.Exponentiate(Zq.NegativeOne),      // TODO: is there a better way to calculate this
                nrProof.X,
                tildeCid * RAParameters.K,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[0],          // s1
                nrProof.s[1].Negate(), // s2
                nrProof.s[2]           // s3
            });
            // T2 = tildeCid^c' g^s1 g1^s4
            GroupElement T2 = Gq.MultiExponentiate(
                new GroupElement[] {
                tildeCid,
                RAParameters.g,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[0],     // s1
                nrProof.s[3],     // s4
            });
            // T3 = gt^c' Cd^s5 g1^s6
            GroupElement T3 = Gq.MultiExponentiate(
                new GroupElement[] {
                RAParameters.gt,
                nrProof.Cd,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[4],     // s5
                nrProof.s[5],     // s6
            });

            if (!nrProof.cPrime.Equals(Zq.GetElementFromDigest(RAParameters.ComputeChallenge(tildeCid, nrProof.X, nrProof.Y, nrProof.Cd, T1, T2, T3))) ||
                !nrProof.Y.Equals(nrProof.X.Exponentiate(PrivateKey)))
            {
                throw new InvalidUProveArtifactException("Invalid non-revocation proof");
            }
        }
Exemplo n.º 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));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Verifies a U-Prove token signature.
        /// </summary>
        /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param>
        /// <param name="upt">The U-Prove token to verify.</param>
        /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception>
        public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (upt.H == Gq.Identity)
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)");
            }

            HashFunction hash = ip.HashFunction;

            hash.Hash(upt.H);
            hash.Hash(upt.PI);
            hash.Hash(upt.SigmaZPrime);
            hash.Hash(Gq.G.Exponentiate(upt.SigmaRPrime) * ip.G[0].Exponentiate(upt.SigmaCPrime.Negate()));
            hash.Hash(upt.H.Exponentiate(upt.SigmaRPrime) * upt.SigmaZPrime.Exponentiate(upt.SigmaCPrime.Negate()));
            if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest))
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token signature");
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Generates a non-revocation proof.
        /// </summary>
        /// <param name="rap">The Revocation Authority parameters.</param>
        /// <param name="rw">The user's revocation witness.</param>
        /// <param name="tildeCid">The revocation attribute commitment.</param>
        /// <param name="xid">The revocation attribute.</param>
        /// <param name="tildeOid">The revocation attribute commitment's opening value.</param>
        /// <param name="preGenRandom">The optional pre-generated random values for the proof, or <c>null</c>.</param>
        /// <returns></returns>
        public static NonRevocationProof GenerateNonRevocationProof(RAParameters rap, RevocationWitness rw, GroupElement tildeCid, FieldZqElement xid, FieldZqElement tildeOid, NonRevocationProofGenerationRandomData preGenRandom = null)
        {
            if (rap == null || rw == null || tildeCid == null || xid == null || tildeOid == null)
            {
                throw new ArgumentNullException("null input to GenerateNonRevocationProof");
            }

            Group   Gq = rap.group;
            FieldZq Zq = Gq.FieldZq;
            NonRevocationProofGenerationRandomData rand = preGenRandom;

            if (rand == null)
            {
                rand = NonRevocationProofGenerationRandomData.Generate(Zq);
            }
            GroupElement   X            = rw.W * rap.g.Exponentiate(rand.t1);
            GroupElement   Y            = rw.Q * rap.K.Exponentiate(rand.t1);
            GroupElement   Cd           = rap.gt.Exponentiate(rw.d) * rap.g1.Exponentiate(rand.t2);
            FieldZqElement w            = rw.d.Invert();
            FieldZqElement z            = rand.t1 * tildeOid - rand.t2;
            FieldZqElement zPrime       = rand.t2.Negate() * w;
            GroupElement   T1           = Gq.MultiExponentiate(new GroupElement[] { X, tildeCid * rap.K, rap.g1 }, new FieldZqElement[] { rand.k1, rand.k2.Negate(), rand.k3 });
            GroupElement   T2           = Gq.MultiExponentiate(new GroupElement[] { rap.g, rap.g1 }, new FieldZqElement[] { rand.k1, rand.k4 });
            GroupElement   T3           = Gq.MultiExponentiate(new GroupElement[] { Cd, rap.g1 }, new FieldZqElement[] { rand.k5, rand.k6 });
            FieldZqElement cPrime       = Zq.GetElementFromDigest(rap.ComputeChallenge(tildeCid, X, Y, Cd, T1, T2, T3));
            FieldZqElement cPrimeNegate = cPrime.Negate();
            FieldZqElement s1           = cPrimeNegate * xid + rand.k1;
            FieldZqElement s2           = cPrimeNegate * rand.t1 + rand.k2;
            FieldZqElement s3           = cPrimeNegate * z + rand.k3;
            FieldZqElement s4           = cPrimeNegate * tildeOid + rand.k4;
            FieldZqElement s5           = cPrimeNegate * w + rand.k5;
            FieldZqElement s6           = cPrimeNegate * zPrime + rand.k6;

            rand.Clear();
            return(new NonRevocationProof(cPrime, new FieldZqElement[] { s1, s2, s3, s4, s5, s6 }, X, Y, Cd));
        }
Exemplo n.º 6
0
 internal static FieldZqElement GenerateChallengeForDevice(FieldZq zq, HashFunction hash, byte[] md, byte[] mdPrime)
 {
     hash.Hash(md);
     hash.Hash(mdPrime);
     return(zq.GetElementFromDigest(hash.Digest));
 }
Exemplo n.º 7
0
 internal static FieldZqElement GenerateChallengeForDevice(FieldZq zq, HashFunction hash, byte[] md, byte[] cp)
 {
     hash.Hash(new byte[][] { cp, md });
     return(zq.GetElementFromDigest(hash.Digest));
 }
Exemplo n.º 8
0
        // Verifies the pre-issuance proof, and returns the element gamma needed for the token issuance.
        /// <summary>
        /// Verifies a pre-issuance proof and returns the element gamma needed for collaborative issuance.
        /// </summary>
        /// <param name="ipip">The pre-issuance proof parameters for the Issuer</param>
        /// <param name="proof">The proof to be verified</param>
        /// <param name="message">An optional message to be verified (must match the one signed by the prover)</param>
        /// <returns>The group element <c>gamma^beta0</c>, a blinded version of the element gamma used during token issuance.</returns>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public static GroupElement VerifyProof(IssuerPreIssuanceParameters ipip, PreIssuanceProof proof, byte[] message)
        {
            // Validate paramters first
            ipip.Validate();

            // extension by Fablei -> need to know the number of attributes involved in this proof -> ip.G.length
            int ipGLength = proof.na + 2;

            IssuerParameters ip = ipip.IP;
            FieldZq          Zq = ip.Zq;
            Group            Gq = ip.Gq;

            List <GroupElement>   bases     = new List <GroupElement>();
            List <FieldZqElement> exponents = new List <FieldZqElement>();

            GroupElement[] C      = null;
            GroupElement[] CPrime = null;

            FieldZqElement c = Zq.GetElementFromDigest(proof.c);

            if (ipip.HasCarryOverAttributes)
            {
                // validate presentation proof
                int[] disclosed = new int[] {};
                VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ipip.SourceIP, disclosed, message, ipip.Tokens);
                vppp.Committed = ipip.Corig;

                try
                {
                    proof.presentation.Verify(vppp);
                }
                catch (InvalidUProveArtifactException e)
                {
                    throw new InvalidUProveArtifactException("Failed to verify pre-Issuance proof, presentation proof " + 0 + " failed to verify (" + e.ToString() + ")");
                }

                // extract the commitments
                C      = new GroupElement[ipip.C.Length];
                CPrime = new GroupElement[ipip.C.Length];
                for (int i = 0; i < C.Length; i++)
                {
                    C[i] = proof.presentation.Commitments[i].TildeC;

                    // Compute the CPrime[i] values.
                    bases     = new List <GroupElement>();
                    exponents = new List <FieldZqElement>();
                    bases.Add(C[i]);
                    exponents.Add(c);
                    bases.Add(Gq.G);
                    exponents.Add(proof.GetResponse("sx" + ipip.C[i]));
                    bases.Add(ip.G[1]);
                    exponents.Add(proof.GetResponse("sR" + i));
                    CPrime[i] = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());
                    //Debug.WriteLine("CPrime[i] = " + BitConverter.ToString(CPrime[i].GetEncoded()));
                }
            }

            // Compute D'
            FieldZqElement sd     = proof.GetResponse("sD");
            GroupElement   DPrime = Gq.MultiExponentiate(proof.Ch0, proof.h0, c, c.Negate()); // TODO: add Inverse() to group element to simplify this

            DPrime = DPrime.Multiply(Gq.G.Exponentiate(sd));
            //Debug.WriteLine("DPrime = " + BitConverter.ToString(DPrime.GetEncoded()));

            // Compute T'
            FieldZqElement sBeta0 = proof.GetResponse("sBeta0");
            GroupElement   TPrime = Gq.MultiExponentiate(proof.Ch0, proof.CGamma, c, sBeta0);

            //Debug.WriteLine("TPrime = " + BitConverter.ToString(TPrime.GetEncoded()));

            // Compute gammaK (product of known attributes)
            bases     = new List <GroupElement>();
            exponents = new List <FieldZqElement>();
            //int t = ip.G.Length-1;
            // extension by Fablei
            int            t  = ipGLength - 1;
            FieldZqElement xt = ProtocolHelper.ComputeXt(ip, ipip.TI, ipip.DeviceProtected);

            bases.Add(ip.G[0]);
            exponents.Add(ip.Zq.One);
            bases.Add(ip.G[t]);
            exponents.Add(xt);  // gammaK = g0*(gt^xt)
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (ipip.K.Contains(i))
                {
                    FieldZqElement xi = ProtocolHelper.ComputeXi(ip, i - 1, ipip.Attributes[i - 1]);
                    bases.Add(ip.G[i]);
                    exponents.Add(xi);
                }
            }
            GroupElement gammaK = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // Compute Cgamma'
            bases     = new List <GroupElement>();
            exponents = new List <FieldZqElement>();
            bases.Add(proof.CGamma);
            exponents.Add(c);
            bases.Add(gammaK);
            exponents.Add(c.Negate());  // TODO: do with one exp; i.e., (CGamma/gammaK)^c
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!ipip.K.Contains(i))
                {
                    FieldZqElement sxi = proof.GetResponse("sx" + i);
                    bases.Add(ip.G[i]);
                    exponents.Add(sxi);
                }
            }
            bases.Add(Gq.G);
            exponents.Add(proof.GetResponse("sRho"));
            GroupElement CgammaPrime = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // TODO: if deviceprotected multiply device base/response.
            //Debug.WriteLine("CgammaPrime = " + BitConverter.ToString(CgammaPrime.GetEncoded()));

            // Recompute challenge
            byte[] cPrime = ComputeChallenge(ip, proof.h0, proof.CGamma, proof.Ch0, C, DPrime, CgammaPrime, TPrime, CPrime, message);
            //Debug.WriteLine("c' = " + BitConverter.ToString(cPrime));

            if (!cPrime.SequenceEqual <byte>(proof.c))
            {
                throw new InvalidUProveArtifactException("invalid proof");
            }

            return(proof.h0);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Create a new pre-issuance proof.
        /// </summary>
        /// <param name="pipp">The prover parameters.</param>
        /// <param name="beta0">The random blinding value used to create the proof, output so that the prover can use it during the issuance protocol</param>
        /// <param name="message">An optional message to sign while creating the proof.</param>
        /// <returns></returns>
        public static PreIssuanceProof CreateProof(ProverPreIssuanceParameters pipp, out FieldZqElement beta0, byte[] message)
        {
            // validate paramters first
            pipp.Validate();

            bool supportDevice = (pipp.DevicePublicKey == null) ? false : true;

            IssuerParameters ip = pipp.IP;
            FieldZq          Zq = ip.Zq;
            Group            Gq = ip.Gq;
            Dictionary <string, FieldZqElement> responses = new Dictionary <string, FieldZqElement>();

            // these will be used if there is a carry-over attribute
            CommitmentPrivateValues cpv       = null;
            PresentationProof       presProof = null;

            GroupElement[]   C      = null;
            GroupElement[]   tildeC = null;
            FieldZqElement[] tildeR = null;

            // extension by Fablei -> needs to calculate the ip.G.Length -> pipp.Attributes.Length + 2
            int ipGLength = pipp.Attributes.Length + 2;

            // Generate random values
            beta0 = Zq.GetRandomElement(true);
            FieldZqElement tildeBeta0 = Zq.GetRandomElement(true);
            FieldZqElement rho        = Zq.GetRandomElement(true);
            FieldZqElement tildeRho   = Zq.GetRandomElement(true);
            FieldZqElement tilde_d    = Zq.GetRandomElement(true);

            FieldZqElement[] tildeX = new FieldZqElement[ipGLength - 1];
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i))
                {
                    tildeX[i] = Zq.GetRandomElement(true);
                }
            }

            // Compute the U-Prove presentation proof, if there are carry-over attributes
            if (pipp.HasCarryOverAttributes)
            {
                // generate the presentation proof
                int[] disclosed = new int[] { };
                ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(pipp.SourceIP, disclosed, message, pipp.KeyAndToken, pipp.SourceAttributes);
                pppp.Committed = pipp.Corig;

                // TODO: What if the source token is device protected?  need to handle this as well. (a pointer to the device should be included in pipp
                //if (device != null)
                //{
                //    pppp.SetDeviceData(deviceMessage, device.GetPresentationContext());
                //}-
                // For now just fail:
                if (pipp.KeyAndToken.Token.IsDeviceProtected)
                {
                    throw new NotImplementedException("Device protected tokens may not be used for carry-over attributes");
                }

                presProof = PresentationProof.Generate(pppp, out cpv);

                //set C
                C = new GroupElement[pipp.C.Length];
                // Generate random values for the commitment randomizers
                tildeR = Zq.GetRandomElements(pipp.C.Length, true);
                tildeC = new GroupElement[C.Length];
                for (int i = 0; i < C.Length; i++)
                {
                    C[i]      = presProof.Commitments[i].TildeC;
                    tildeC[i] = Gq.MultiExponentiate(Gq.G, ip.G[1], tildeX[pipp.C[i]], tildeR[i]);
                }
            }   // end if cary-over attributes

            // Compute gamma
            GroupElement gamma = ProtocolHelper.ComputeIssuanceInput(ip, pipp.Attributes, pipp.TI, pipp.DevicePublicKey);

            // Compute h0, Cgamma, Ch0, tildeD, tildeT:
            GroupElement h0     = gamma.Exponentiate(beta0);
            GroupElement Cgamma = gamma.Multiply(Gq.G.Exponentiate(rho));        // Cgamma = gamma*(g^rho)
            GroupElement Ch0    = Cgamma.Exponentiate(beta0);
            GroupElement tildeD = Gq.G.Exponentiate(tilde_d);

            GroupElement tildeT = Cgamma.Exponentiate(tildeBeta0);

            // Compute tildeCgamma:
            List <GroupElement>   bases     = new List <GroupElement>();
            List <FieldZqElement> exponents = new List <FieldZqElement>();

            bases.Add(Gq.G);
            exponents.Add(tildeRho);
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i))     // i \not\in K
                {
                    bases.Add(ip.G[i]);
                    exponents.Add(tildeX[i]);
                }
            }
            GroupElement tildeCgamma = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // TODO: if device protected, then multiply tildeCgamma by the public key
            // Note: We leave TI out, (i.e., (g_t)^(x_t) because t \in K implicitly.

            // Compute the challenge
            byte[]         c    = ComputeChallenge(ip, h0, Cgamma, Ch0, C, tildeD, tildeCgamma, tildeT, tildeC, message);
            FieldZqElement negc = Zq.GetElementFromDigest(c).Negate();

            // Compute the responses
            responses.Add("sBeta0", tildeBeta0.Add(beta0.Multiply(negc)));          // sBeta0 = tildeBeta0 - beta0*c
            responses.Add("sD", tilde_d.Add(beta0.Multiply(rho).Multiply(negc)));   // sD = tilde_d - beta0*rho*c
            responses.Add("sRho", tildeRho.Add(rho.Multiply(negc)));                // sRho = tildeRho - rho*c

            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i)) // in \not\in K
                {
                    FieldZqElement xi = ProtocolHelper.ComputeXi(ip, i - 1, pipp.Attributes[i - 1]);
                    responses.Add("sx" + i, tildeX[i].Add(xi.Multiply(negc)));          // sxi = tildeX[i] - xi*c
                }
            }

            if (pipp.HasCarryOverAttributes)
            {
                for (int i = 0; i < C.Length; i++)
                {
                    responses.Add("sR" + i, tildeR[i].Add(cpv.TildeO[i].Multiply(negc)));      // sRi = tildeR[i] - tildeO[i]*c
                }
            }

            return(new PreIssuanceProof(h0, Cgamma, Ch0, c, responses,
                                        pipp.HasCarryOverAttributes ? presProof : null, pipp.Attributes.Length));
        }