private void Precompute(GroupElement gamma, FieldZqElement[] preGenW) { IssuerParameters ip = ikap.IssuerParameters; Group Gq = ip.Gq; FieldZq Zq = ip.Zq; sigmaZ = gamma.Exponentiate(ikap.PrivateKey); if (preGenW == null) { w = Zq.GetRandomElements(numberOfTokens, false); } else { w = preGenW; } sigmaA = new GroupElement[numberOfTokens]; sigmaB = new GroupElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { sigmaA[i] = Gq.G.Exponentiate(w[i]); sigmaB[i] = gamma.Exponentiate(w[i]); } state = State.Initialized; }
private void Precompute(GroupElement gamma, ProverRandomData pregeneratedRandomData) { Group Gq = ip.Gq; FieldZq Zq = ip.Zq; if (pregeneratedRandomData == null) { alpha = Zq.GetRandomElements(numberOfTokens, true); beta1 = Zq.GetRandomElements(numberOfTokens, false); beta2 = Zq.GetRandomElements(numberOfTokens, false); } else { alpha = pregeneratedRandomData.Alpha; beta1 = pregeneratedRandomData.Beta1; beta2 = pregeneratedRandomData.Beta2; } h = new GroupElement[numberOfTokens]; t1 = new GroupElement[numberOfTokens]; t2 = new GroupElement[numberOfTokens]; ukat = new UProveKeyAndToken[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { ukat[i] = new UProveKeyAndToken(); h[i] = gamma.Exponentiate(alpha[i]); t1[i] = ip.G[0].Exponentiate(beta1[i]) * Gq.G.Exponentiate(beta2[i]); t2[i] = h[i].Exponentiate(beta2[i]); ukat[i].PrivateKey = alpha[i].Invert(); } state = State.Initialized; }
private void Precompute(GroupElement gamma, ProverRandomData pregeneratedRandomData) { Group Gq = ip.Gq; FieldZq Zq = ip.Zq; if (pregeneratedRandomData == null) { alpha = Zq.GetRandomElements(numberOfTokens, true); beta1 = Zq.GetRandomElements(numberOfTokens, false); beta2 = Zq.GetRandomElements(numberOfTokens, false); } else { alpha = pregeneratedRandomData.Alpha; beta1 = pregeneratedRandomData.Beta1; beta2 = pregeneratedRandomData.Beta2; } h = new GroupElement[numberOfTokens]; t1 = new GroupElement[numberOfTokens]; // we don't compute t2 in the precomputation since we prefer to // compute h^beta2 as part of the sigmaBPrime multi-exponentiation ukat = new UProveKeyAndToken[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { ukat[i] = new UProveKeyAndToken(); h[i] = gamma.Exponentiate(alpha[i].Multiply(beta0Inverse)); // remove collab issuance blind, if present t1[i] = Gq.MultiExponentiate(new GroupElement[] { ip.G[0], Gq.G }, new FieldZqElement[] { beta1[i], beta2[i] }); ukat[i].PrivateKey = alpha[i].Invert(); } state = State.Initialized; }
GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps) { if (this.device == null) { throw new DeviceException("Invalid context."); } if (this.wdPrime != null) { throw new DeviceException("Initial witness already calculated."); } this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false); // compute pseudonym apPrime = gs.Exponentiate(this.wdPrime); Ps = gs.Exponentiate(this.device.xd); // compute initial witness return(this.device.Gd.Exponentiate(this.wdPrime)); }
/// <summary> /// Generates the U-Prove key and tokens. /// </summary> /// <param name="message">The third issuance message.</param> /// <param name="skipTokenValidation">Set to <code>true</code> to skip token validation; /// <code>false</code> otherwise. Token validation SHOULD be performed before use, either /// by setting <code>skipTokenValidation</code> to <code>false</code>, or by later using the /// <code>ProtocolHelper.VerifyTokenSignature</code> method. /// </param> /// <exception cref="InvalidUProveArtifactException">If the token signature is invalid.</exception> /// <returns>An array of U-Prove keys and tokens</returns> public UProveKeyAndToken[] GenerateTokens(ThirdIssuanceMessage message, bool skipTokenValidation = false) { if (state != State.Second) { throw new InvalidOperationException("GenerateSecondMessage must be called first"); } bool doBatchValidation = !skipTokenValidation && batchValidationSecurityLevel > 0; bool doNormalValidation = !skipTokenValidation && batchValidationSecurityLevel <= 0; Group Gq = ip.Gq; FieldZq Zq = ip.Zq; FieldZqElement[] sigmaRPrime = new FieldZqElement[numberOfTokens]; FieldZqElement phoAR = Zq.Zero, phoR = Zq.Zero, phoAC = Zq.Zero, phoC = Zq.Zero; GroupElement batchAcc = Gq.Identity; for (int i = 0; i < numberOfTokens; i++) { sigmaRPrime[i] = message.sigmaR[i] + beta2[i]; if (doBatchValidation) { FieldZqElement s = Zq.GetRandomElement(true, batchValidationSecurityLevel); phoAR += (s * alpha[i] * sigmaRPrime[i]); phoR += (s * sigmaRPrime[i]); phoAC += (s * alpha[i] * sigmaCPrime[i]); phoC += (s * sigmaCPrime[i]); batchAcc *= (sigmaAPrime[i] * sigmaBPrime[i]).Exponentiate(s); } else if (doNormalValidation) { if (!(sigmaAPrime[i] * sigmaBPrime[i]).Equals( ((Gq.G * h[i]).Exponentiate(sigmaRPrime[i]) * (ip.G[0] * sigmaZPrime[i]).Exponentiate(sigmaCPrime[i].Negate())))) { throw new InvalidUProveArtifactException("Invalid token signature: " + i); } } ukat[i].Token = new UProveToken(ip.UidP, h[i], TI, PI, sigmaZPrime[i], sigmaCPrime[i], sigmaRPrime[i], isDeviceProtected); } if (doBatchValidation && (batchAcc != Gq.G.Exponentiate(phoR) * gamma.Exponentiate(phoAR) * ip.G[0].Exponentiate(phoC.Negate()) * sigmaZ.Exponentiate(phoAC.Negate()))) { throw new InvalidUProveArtifactException("Invalid token signature"); } state = State.Tokens; return(ukat); }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { 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 // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; GroupElement dAccumulator = ip.G[0] * ip.G[n + 1].Exponentiate(ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected)); // g0 * gt^xt GroupElement uAccumulator = upt.H.Exponentiate(this.r[0]); int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dAccumulator = dAccumulator * ip.G[i].Exponentiate(disclosedX[dIndex]); dIndex++; } else { uAccumulator = uAccumulator * ip.G[i].Exponentiate(this.r[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); HashFunction hash = ip.HashFunction; hash.Hash((dAccumulator.Exponentiate(c.Negate()) * uAccumulator * (upt.IsDeviceProtected ? ip.Gd.Exponentiate(this.r[this.r.Length -1]) : Gq.Identity))); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(this.ps.Exponentiate(c).Multiply(gs.Exponentiate(this.r[pseudonymResponseIndex]))); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; hash.Hash(commitment.TildeC.Exponentiate(c).Multiply(ip.Gq.G.Exponentiate(this.r[commitmentResponseIndices[i]])).Multiply(ip.G[1].Exponentiate(commitment.TildeR))); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation 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; 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; }
GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps) { if (this.device == null) { throw new DeviceException("Invalid context."); } if (this.wdPrime != null) { throw new DeviceException("Initial witness already calculated."); } this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false); // compute pseudonym apPrime = gs.Exponentiate(this.wdPrime); Ps = gs.Exponentiate(this.device.xd); // compute initial witness return this.device.Gd.Exponentiate(this.wdPrime); }
/// <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); }
/// <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)); }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { 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 // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; GroupElement dAccumulator = ip.G[0] * ip.G[n + 1].Exponentiate(ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected)); // g0 * gt^xt GroupElement uAccumulator = upt.H.Exponentiate(this.r[0]); int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dAccumulator = dAccumulator * ip.G[i].Exponentiate(disclosedX[dIndex]); dIndex++; } else { uAccumulator = uAccumulator * ip.G[i].Exponentiate(this.r[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); HashFunction hash = ip.HashFunction; hash.Hash((dAccumulator.Exponentiate(c.Negate()) * uAccumulator * (upt.IsDeviceProtected ? ip.Gd.Exponentiate(this.r[this.r.Length - 1]) : Gq.Identity))); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(this.ps.Exponentiate(c).Multiply(gs.Exponentiate(this.r[pseudonymResponseIndex]))); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; hash.Hash(commitment.TildeC.Exponentiate(c).Multiply(ip.Gq.G.Exponentiate(this.r[commitmentResponseIndices[i]])).Multiply(ip.G[1].Exponentiate(commitment.TildeR))); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } }
/// <summary> /// Returns g^{-1}. /// </summary> /// <param name="g">Group element to invert.</param> /// <returns></returns> public GroupElement Invert(GroupElement g) { return(g.Exponentiate(this.FieldZq.NegativeOne)); }