// return r - c*x private static FieldZqElement ComputeResponse(FieldZqElement r, FieldZqElement c, FieldZqElement x) { return(r.Add(c.Multiply(x).Negate())); }
/// <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)); }