public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO) { CommitmentPrivateValues cpv; PresentationProof proof = Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out cpv); tildeO = cpv.TildeO; return(proof); }
public PresentationProof presentation; // presentation for carry-over attribute commitments // This is private because everyone should use CreateProof private PreIssuanceProof(GroupElement h0, GroupElement CGamma, GroupElement Ch0, byte[] c, Dictionary <String, FieldZqElement> responses, PresentationProof presentation) { this.h0 = h0; this.CGamma = CGamma; this.Ch0 = Ch0; this.c = c; this.responses = responses; this.presentation = presentation; }
/// <summary> /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values. /// </summary> /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param> /// <param name="disclosed">An ordered array of disclosed attribute indices.</param> /// <param name="committed">An ordered array of committed attribute indices.</param> /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param> /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param> /// <param name="message">The presentation message.</param> /// <param name="messageD">The message for the Device, or null.</param> /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param> /// <param name="upkt">The U-Proke key and token.</param> /// <param name="attributes">The token attributes.</param> /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param> /// <param name="cpv">Returned commitment private values if commitments are computed.</param> /// <returns>A presentation proof.</returns> internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv) { if (upkt.Token.IsDeviceProtected && deviceContext == null) { throw new ArgumentNullException("Device context is not initialized"); } bool generateCommitments = (committed != null && committed.Length > 0); FieldZqElement[] tildeO = null; // make sure disclosed and committed lists are sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); if (generateCommitments) { Array.Sort(committed); } int n = 0; if (ip.E != null) n = ip.E.Length; bool presentPseudonym = false; if (gs != null) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else if (pseudonymAttribIndex > 0) { throw new ArgumentNullException("gs is null"); } else { pseudonymAttribIndex = 0; } Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected); ProofGenerationRandomData random; if (preGenW == null) { random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected); } else { random = preGenW; } FieldZqElement[] x = new FieldZqElement[n]; GroupElement temp = upkt.Token.H.Exponentiate(random.W0); int uIndex = 0; int dIndex = 0; int cIndex = 0; PresentationProof proof = new PresentationProof(); proof.DisclosedAttributes = new byte[disclosed.Length][]; int pseudonymRandomizerIndex = 0; if (generateCommitments) { proof.Commitments = new CommitmentValues[committed.Length]; tildeO = new FieldZqElement[committed.Length]; } HashFunction hash = ip.HashFunction; for (int i = 0; i < n; i++) { x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]); if (!disclosed.Contains(i + 1)) { temp = temp * ip.G[i + 1].Exponentiate(random.W[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == (i + 1)) { pseudonymRandomizerIndex = uIndex; } } if (generateCommitments && committed.Contains(i + 1)) { GroupElement tildeC = ip.Gq.G.Exponentiate(x[i]) * ip.G[1].Exponentiate(random.TildeO[cIndex]); tildeO[cIndex] = random.TildeO[cIndex]; GroupElement temp2 = ip.Gq.G.Exponentiate(random.W[uIndex]) * ip.G[1].Exponentiate(random.TildeW[cIndex]); hash.Hash(temp2); byte[] tildeA = hash.Digest; proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null); cIndex++; } uIndex++; } else if (generateCommitments && committed.Contains(i + 1)) { throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed"); } else { proof.DisclosedAttributes[dIndex] = attributes[i]; dIndex++; } } if (upkt.Token.IsDeviceProtected) { GroupElement ad; // pseudonym computed by device if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex) { GroupElement apPrime; GroupElement Ps; ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps); hash.Hash(apPrime * gs.Exponentiate(random.Wd)); proof.Ap = hash.Digest; proof.Ps = Ps; } else { ad = deviceContext.GetInitialWitness(); } temp = temp * ip.Gd.Exponentiate(random.Wd) * ad; } hash.Hash(temp); proof.a = hash.Digest; // pseudonym derived from one token attribute if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex) { hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex])); proof.Ap = hash.Digest; proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]); } byte[] mdPrime; FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime); proof.r = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d proof.r[0] = c * upkt.PrivateKey + random.W0; uIndex = 1; for (int i = 1; i <= n; i++) { if (!disclosed.Contains(i)) { proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1]; uIndex++; } } if (upkt.Token.IsDeviceProtected) { proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd; } if (generateCommitments) { for (int i = 0; i < committed.Length; i++) { proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i]; } } random.Clear(); cpv = new CommitmentPrivateValues(tildeO); return proof; }
/// <summary> /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values. /// </summary> /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param> /// <param name="disclosed">An ordered array of disclosed attribute indices.</param> /// <param name="committed">An ordered array of committed attribute indices.</param> /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param> /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param> /// <param name="message">The presentation message.</param> /// <param name="messageD">The message for the Device, or null.</param> /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param> /// <param name="upkt">The U-Proke key and token.</param> /// <param name="attributes">The token attributes.</param> /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param> /// <param name="cpv">Returned commitment private values if commitments are computed.</param> /// <returns>A presentation proof.</returns> internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv) { if (upkt.Token.IsDeviceProtected && deviceContext == null) { throw new ArgumentNullException("Device context is not initialized"); } bool generateCommitments = (committed != null && committed.Length > 0); FieldZqElement[] tildeO = null; // make sure disclosed and committed lists are sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); if (generateCommitments) { Array.Sort(committed); } int n = 0; if (ip.E != null) { n = ip.E.Length; if (n != attributes.Length) { throw new ArgumentException("number of attributes is inconsistent with issuer parameters"); } } bool presentPseudonym = false; if (gs != null) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else if (pseudonymAttribIndex > 0) { throw new ArgumentNullException("gs is null"); } else { pseudonymAttribIndex = 0; } Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected); ProofGenerationRandomData random; if (preGenW == null) { random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected); } else { random = preGenW; } // set up the multi-exponentiation arrays, with h^w0 as the first term int multiExpArraySize = 1 + (n - disclosed.Length) + (upkt.Token.IsDeviceProtected ? 1 : 0); GroupElement[] bases = new GroupElement[multiExpArraySize]; FieldZqElement[] exponents = new FieldZqElement[multiExpArraySize]; int multiExpIndex = 0; bases[multiExpIndex] = upkt.Token.H; exponents[multiExpIndex++] = random.W0; FieldZqElement[] x = new FieldZqElement[n]; int uIndex = 0; int dIndex = 0; int cIndex = 0; PresentationProof proof = new PresentationProof(); proof.DisclosedAttributes = new byte[disclosed.Length][]; int pseudonymRandomizerIndex = 0; if (generateCommitments) { proof.Commitments = new CommitmentValues[committed.Length]; tildeO = new FieldZqElement[committed.Length]; } HashFunction hash = ip.HashFunction; GroupElement[] cBases = new GroupElement[2] { Gq.G, ip.G[1] }; for (int i = 0; i < n; i++) { x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]); if (!disclosed.Contains(i + 1)) { bases[multiExpIndex] = ip.G[i + 1]; exponents[multiExpIndex++] = random.W[uIndex]; if (presentPseudonym) { if (pseudonymAttribIndex == (i + 1)) { pseudonymRandomizerIndex = uIndex; } } if (generateCommitments && committed.Contains(i + 1)) { GroupElement tildeC = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] { x[i], random.TildeO[cIndex] }); tildeO[cIndex] = random.TildeO[cIndex]; GroupElement temp2 = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] { random.W[uIndex], random.TildeW[cIndex] }); hash.Hash(temp2); byte[] tildeA = hash.Digest; proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null); cIndex++; } uIndex++; } else if (generateCommitments && committed.Contains(i + 1)) { throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed"); } else { proof.DisclosedAttributes[dIndex] = attributes[i]; dIndex++; } } GroupElement aPreImage; if (upkt.Token.IsDeviceProtected) { GroupElement ad; // pseudonym computed by device if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex) { GroupElement apPrime; GroupElement Ps; ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps); hash.Hash(apPrime * gs.Exponentiate(random.Wd)); proof.Ap = hash.Digest; proof.Ps = Ps; } else { ad = deviceContext.GetInitialWitness(); } bases[multiExpIndex] = ip.Gd; exponents[multiExpIndex++] = random.Wd; aPreImage = Gq.MultiExponentiate(bases, exponents) * ad; } else { aPreImage = Gq.MultiExponentiate(bases, exponents); } hash.Hash(aPreImage); proof.a = hash.Digest; // pseudonym derived from one token attribute if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex) { hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex])); proof.Ap = hash.Digest; proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]); } byte[] mdPrime; FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime); proof.r = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d proof.r[0] = c * upkt.PrivateKey + random.W0; uIndex = 1; for (int i = 1; i <= n; i++) { if (!disclosed.Contains(i)) { proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1]; uIndex++; } } if (upkt.Token.IsDeviceProtected) { proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd; } if (generateCommitments) { for (int i = 0; i < committed.Length; i++) { proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i]; } } random.Clear(); cpv = new CommitmentPrivateValues(tildeO); return(proof); }
public static PresentationProofComposite convertPresentationProof(PresentationProof p, BigInteger[] commitmentValues, byte[] tokenId, byte[] proofSession) { PresentationProofComposite pc = new PresentationProofComposite(); pc.A = p.A; pc.Ap = (p.Ap == null ? null : p.Ap); pc.DisclosedAttributes = p.DisclosedAttributes; pc.Ps = (p.Ps == null ? null : p.Ps.GetEncoded()); byte[][] byteArray = new byte[p.R.Length][]; for (int i = 0; i < byteArray.Length; i++) { byteArray[i] = p.R[i].ToByteArray(); } pc.R = byteArray; if (p.Commitments != null) { pc.TildeValues = new byte[3 * p.Commitments.Length][]; for (int i = 0; i < p.Commitments.Length; i++) { pc.TildeValues[(i * 3)] = p.Commitments[i].TildeC.GetEncoded(); pc.TildeValues[(i * 3) + 1] = p.Commitments[i].TildeA; pc.TildeValues[(i * 3) + 2] = p.Commitments[i].TildeR.ToByteArray(); } } if (commitmentValues != null) { if (commitmentValues.Length != p.Commitments.Length) { throw new ArgumentException("inconsistent commitment values"); } pc.TildeO = new byte[commitmentValues.Length][]; for (int i = 0; i < commitmentValues.Length; i++) { pc.TildeO[i] = commitmentValues[i].ToByteArray(); } } pc.TokenID = tokenId; pc.MessageD = (proofSession == null ? null : proofSession); return pc; }
public static PresentationProof convertPresentationProofComposite(IssuerParameters ip, PresentationProofComposite pc, out byte[] tokenID, out byte[] proofSession) { PresentationProof p = new PresentationProof(); p.A = (pc.A == null ? null : pc.A); p.Ap = (pc.Ap == null ? null : pc.Ap); p.DisclosedAttributes = pc.DisclosedAttributes; p.Ps = (pc.Ps == null ? null : ip.Gq.CreateGroupElement(pc.Ps)); BigInteger[] biArray = new BigInteger[pc.R.Length]; for (int i = 0; i < biArray.Length; i++) { biArray[i] = new BigInteger(1, pc.R[i]); } p.R = biArray; if (pc.TildeValues != null) { int numCommitments = pc.TildeValues.Length / 3; p.Commitments = new CommitmentValues[numCommitments]; for (int i = 0; i < numCommitments; i++) { p.Commitments[i] = new CommitmentValues( ip.Gq.CreateGroupElement(pc.TildeValues[(i * 3)]), // tildeC pc.TildeValues[(i * 3) + 1], // tildaA new BigInteger(1, pc.TildeValues[(i * 3) + 2]) // tildeR ); } // we ignore the tildeO values. This method is called by the verifier, and // the tildeO values should never be sent to the verifier. } tokenID = pc.TokenID; proofSession = (pc.MessageD == null ? null : pc.MessageD); return p; }
/// <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)); }