Beispiel #1
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));
        }
Beispiel #2
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);
        }
Beispiel #3
0
 /// <summary>
 /// Returns numerator/denominator.
 /// </summary>
 /// <param name="numerator">Numerator</param>
 /// <param name="denominator">Denominator</param>
 /// <returns></returns>
 public GroupElement Divide(GroupElement numerator, GroupElement denominator)
 {
     return(numerator.Multiply(this.Invert(denominator)));
 }