public PseudonymComposite presentPseudonym(string messageParam, string verifierScopeParam, string sessionID) { // invoke the device to compute the pseudonym value and response. // if a scope-exclusive pseudonym is requested (when scope != null) then // the device-computed scope-exclusive pseudonym is used. Otherwise, the // device's public key and initial witness are used in lieu of the pseudonym // value and commitment, respectively. cOut.write("presentPseudonym()"); VerifySessionId(sessionID); GroupElement A = null; GroupElement P = null; BigInteger R = null; try { DeviceManager dManager = sessionDB[sessionID].deviceManager; bool scopeExclusive = (verifierScopeParam != null && verifierScopeParam != "null" && verifierScopeParam.Length > 0); IDevicePresentationContext ctx = dManager.GetDevice().GetPresentationContext(); byte[] proofSession = null; if (!dManager.IsVirtualDevice) { SmartCardDevice smartDevice = (SmartCardDevice)dManager.GetDevice(); smartDevice.ProofSession = smartDevice.Device.BeginCommitment(1); proofSession = smartDevice.ProofSession; } if (scopeExclusive) { ctx.GetInitialWitnessesAndPseudonym(encoding.GetBytes(verifierScopeParam), out A, out P); } else { P = dManager.GetDevice().GetDevicePublicKey(); A = ctx.GetInitialWitness(); } if (dManager.IsVirtualDevice) { R = ctx.GetDeviceResponse(encoding.GetBytes(messageParam), null, dManager.HashFunctionOID); } else { R = ctx.GetDeviceResponse(proofSession, encoding.GetBytes(messageParam), dManager.HashFunctionOID); } } catch (Exception e) { cOut.write("Exception caught: " + e.Message); DebugUtils.DebugPrint(e.StackTrace.ToString()); return(new PseudonymComposite()); } return(ConvertUtils.convertPseudonym(new Pseudonym(A, P, R))); }
/// <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 void ProtocolTest() { Stopwatch sw = new Stopwatch(); sw.Start(); bool[] bools = new bool[] { true, false }; foreach (bool isSubgroupConstruction in bools) { foreach (bool supportDevice in bools) { foreach (int DSize in new int[] { 0, 2, 5 }) { foreach (bool isLite in bools) { string filename = "TestVectorData\\testvectors_"; if (isSubgroupConstruction) { filename += "SG"; } else { filename += "EC"; } if (supportDevice) { filename += "_Device"; } filename += ("_D" + DSize); if (isLite) { filename += "_lite"; } filename += "_doc.txt"; var vectors = GetTestVectors(filename); IssuerKeyAndParameters ikap = LoadIssuerKeyAndParameters(isSubgroupConstruction, vectors["GroupName"], supportDevice, vectors); FieldZq Zq = ikap.IssuerParameters.Zq; // replace random y0/g0 with test vector values ikap.PrivateKey = Zq.GetElement(HexToBytes(vectors["y0"])); ikap.IssuerParameters.G[0] = CreateGroupElement(ikap.IssuerParameters.Gq, vectors["g0"]); Assert.AreEqual(ikap.IssuerParameters.G[0], ikap.IssuerParameters.Gq.G.Exponentiate(ikap.PrivateKey), "g0 computation"); IssuerParameters ip = ikap.IssuerParameters; ip.Verify(); /* * issuance */ byte[][] A = new byte[][] { HexToBytes(vectors["A1"]), HexToBytes(vectors["A2"]), HexToBytes(vectors["A3"]), HexToBytes(vectors["A4"]), HexToBytes(vectors["A5"]) }; Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x1"])), ProtocolHelper.ComputeXi(ip, 0, A[0]), "x1"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x2"])), ProtocolHelper.ComputeXi(ip, 1, A[1]), "x2"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x3"])), ProtocolHelper.ComputeXi(ip, 2, A[2]), "x3"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x4"])), ProtocolHelper.ComputeXi(ip, 3, A[3]), "x4"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x5"])), ProtocolHelper.ComputeXi(ip, 4, A[4]), "x5"); byte[] TI = HexToBytes(vectors["TI"]); Assert.IsTrue(HexToBytes(vectors["P"]).SequenceEqual(ip.Digest(supportDevice)), "P"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["xt"])), ProtocolHelper.ComputeXt(ip, TI, supportDevice), "xt"); IDevice device = null; GroupElement hd = null; if (supportDevice) { device = new VirtualDevice(ip, Zq.GetElement(HexToBytes(vectors["xd"])), Zq.GetElement(HexToBytes(vectors["wdPrime"]))); IDevicePresentationContext context = device.GetPresentationContext(); // Test device responses Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["hd"]), device.GetDevicePublicKey(), "hd"); Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["ad"]), context.GetInitialWitness(), "ad"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["rdPrime"])), context.GetDeviceResponse(HexToBytes(vectors["md"]), HexToBytes(vectors["cp"]), ip.HashFunctionOID), "rdPrime"); hd = CreateGroupElement(ip.Gq, vectors["hd"]); } IssuerProtocolParameters ipp = new IssuerProtocolParameters(ikap); ipp.Attributes = A; ipp.NumberOfTokens = 1; ipp.TokenInformation = TI; ipp.DevicePublicKey = hd; ipp.PreGeneratedW = new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["w"])) }; Issuer issuer = ipp.CreateIssuer(); byte[] PI = HexToBytes(vectors["PI"]); ProverProtocolParameters ppp = new ProverProtocolParameters(ip); ppp.Attributes = A; ppp.NumberOfTokens = 1; ppp.TokenInformation = TI; ppp.ProverInformation = PI; ppp.DevicePublicKey = hd; ppp.ProverRandomData = new ProverRandomData( new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["alpha"])) }, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta1"])) }, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta2"])) }); Prover prover = ppp.CreateProver(); FirstIssuanceMessage msg1 = issuer.GenerateFirstMessage(); Assert.AreEqual(msg1.sigmaZ, CreateGroupElement(ip.Gq, vectors["sigmaZ"]), "sigmaZ"); Assert.AreEqual(msg1.sigmaA[0], CreateGroupElement(ip.Gq, vectors["sigmaA"]), "sigmaA"); Assert.AreEqual(msg1.sigmaB[0], CreateGroupElement(ip.Gq, vectors["sigmaB"]), "sigmaB"); SecondIssuanceMessage msg2 = prover.GenerateSecondMessage(msg1); Assert.AreEqual(msg2.sigmaC[0], Zq.GetElement(HexToBytes(vectors["sigmaC"])), "sigmaC"); ThirdIssuanceMessage msg3 = issuer.GenerateThirdMessage(msg2); Assert.AreEqual(msg3.sigmaR[0], Zq.GetElement(HexToBytes(vectors["sigmaR"])), "sigmaR"); UProveKeyAndToken[] upkt = prover.GenerateTokens(msg3); Assert.AreEqual(upkt[0].PrivateKey, Zq.GetElement(HexToBytes(vectors["alphaInverse"])), "alphaInverse"); UProveToken token = upkt[0].Token; Assert.AreEqual(token.H, CreateGroupElement(ip.Gq, vectors["h"]), "h"); Assert.AreEqual(token.SigmaZPrime, CreateGroupElement(ip.Gq, vectors["sigmaZPrime"]), "sigmaZPrime"); Assert.AreEqual(token.SigmaCPrime, Zq.GetElement(HexToBytes(vectors["sigmaCPrime"])), "sigmaCPrime"); Assert.AreEqual(token.SigmaRPrime, Zq.GetElement(HexToBytes(vectors["sigmaRPrime"])), "sigmaRPrime"); Assert.IsTrue(HexToBytes(vectors["UIDt"]).SequenceEqual(ProtocolHelper.ComputeTokenID(ip, token)), "UIDt"); Assert.IsTrue(supportDevice == token.IsDeviceProtected); /* * presentation */ int[] disclosed = new int[] { }; if (vectors.ContainsKey("D") && vectors["D"].Length > 0) { disclosed = Array.ConvertAll <string, int>(vectors["D"].Split(','), new Converter <string, int>(stringToInt)); } int[] undisclosed = new int[5 - disclosed.Length]; int dIndex = 0, uIndex = 0; for (int i = 1; i <= 5; i++) { if (disclosed.Length > 0 && disclosed[dIndex] == i) { dIndex++; } else { undisclosed[uIndex++] = i; } } int[] committed = new int[] { }; if (vectors.ContainsKey("C") && vectors["C"].Length > 0) { committed = Array.ConvertAll <string, int>(vectors["C"].Split(','), new Converter <string, int>(stringToInt)); } byte[] m = HexToBytes(vectors["m"]); byte[] md = HexToBytes(vectors["md"]); IDevicePresentationContext deviceContext = null; if (supportDevice) { deviceContext = device.GetPresentationContext(); } int p = 0; if (vectors.ContainsKey("p") && !int.TryParse(vectors["p"], out p)) { p = PresentationProof.DeviceAttributeIndex; } byte[] s = vectors.ContainsKey("s") ? HexToBytes(vectors["s"]) : null; int commitmentIndex = committed.Length > 0 ? committed[0] : 0; ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(ip, disclosed, m, upkt[0], A); pppp.Committed = committed; pppp.PseudonymAttributeIndex = p; pppp.PseudonymScope = s; pppp.DeviceMessage = md; pppp.DeviceContext = deviceContext; FieldZqElement[] w = new FieldZqElement[undisclosed.Length]; for (int i = 0; i < undisclosed.Length; i++) { w[i] = Zq.GetElement(HexToBytes(vectors["w" + undisclosed[i]])); } FieldZqElement[] tildeO = new FieldZqElement[committed.Length]; FieldZqElement[] tildeW = new FieldZqElement[committed.Length]; for (int i = 0; i < committed.Length; i++) { tildeO[i] = Zq.GetElement(HexToBytes(vectors["tildeO" + committed[i]])); tildeW[i] = Zq.GetElement(HexToBytes(vectors["tildeW" + committed[i]])); } pppp.RandomData = new ProofGenerationRandomData( Zq.GetElement(HexToBytes(vectors["w0"])), w, supportDevice ? Zq.GetElement(HexToBytes(vectors["wd"])) : null, tildeO, tildeW); CommitmentPrivateValues cpv; PresentationProof proof = PresentationProof.Generate(pppp, out cpv); Assert.IsTrue(HexToBytes(vectors["a"]).SequenceEqual(proof.A), "a"); if (vectors.ContainsKey("gs")) { Assert.AreEqual(ProtocolHelper.GenerateScopeElement(ip.Gq, s), CreateGroupElement(ip.Gq, vectors["gs"])); Assert.IsTrue(HexToBytes(vectors["ap"]).SequenceEqual(proof.Ap), "ap"); Assert.AreEqual(proof.Ps, CreateGroupElement(ip.Gq, vectors["Ps"]), "Ps"); } for (int i = 0; i < disclosed.Length; i++) { Assert.IsTrue(HexToBytes(vectors["A" + disclosed[i]]).SequenceEqual(proof.DisclosedAttributes[i]), "A" + disclosed[i]); } Assert.AreEqual(proof.R[0], Zq.GetElement(HexToBytes(vectors["r0"])), "r0"); for (int i = 0; i < undisclosed.Length; i++) { Assert.AreEqual(proof.R[i + 1], Zq.GetElement(HexToBytes(vectors["r" + undisclosed[i]])), "r" + undisclosed[i]); } if (supportDevice) { Assert.AreEqual(proof.R[proof.R.Length - 1], Zq.GetElement(HexToBytes(vectors["rd"])), "rd"); } for (int i = 0; i < committed.Length; i++) { Assert.AreEqual(proof.Commitments[i].TildeR, Zq.GetElement(HexToBytes(vectors["tildeR" + committed[i]])), "tildeR" + committed[i]); Assert.IsTrue(cpv.TildeO.Length == committed.Length); Assert.AreEqual(cpv.TildeO[i], Zq.GetElement(HexToBytes(vectors["tildeO" + committed[i]])), "tildeO" + committed[i]); } VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ip, disclosed, m, upkt[0].Token); vppp.Committed = committed; vppp.PseudonymAttributeIndex = p; vppp.PseudonymScope = s; vppp.DeviceMessage = md; proof.Verify(vppp); #if TEST_ID_ESCROW if (committed.Length > 0) { IDEscrowParams escrowParams = new IDEscrowParams(ip); IDEscrowPrivateKey escrowPrivateKey = new IDEscrowPrivateKey(Zq.GetElement(HexToBytes(vectors["ie_x"]))); IDEscrowPublicKey escrowPublicKey = new IDEscrowPublicKey(escrowParams, escrowPrivateKey); Assert.AreEqual(escrowPublicKey.H, CreateGroupElement(ip.Gq, vectors["ie_H"]), "ie_H"); byte[] additionalInfo = HexToBytes(vectors["ie_additionalInfo"]); int ie_bIndex = int.Parse(vectors["ie_b"]); IDEscrowCiphertext ctext = IDEscrowFunctions.VerifiableEncrypt( escrowParams, escrowPublicKey, HexToBytes(vectors["UIDt"]), proof.Commitments[0].TildeC, ProtocolHelper.ComputeXi(ip, ie_bIndex - 1, A[ie_bIndex - 1]), cpv.TildeO[0], additionalInfo, new IDEscrowFunctions.IDEscrowProofGenerationRandomData( Zq.GetElement(HexToBytes(vectors["ie_r"])), Zq.GetElement(HexToBytes(vectors["ie_xbPrime"])), Zq.GetElement(HexToBytes(vectors["ie_rPrime"])), Zq.GetElement(HexToBytes(vectors["ie_obPrime"])))); Assert.IsTrue(IDEscrowFunctions.UProveVerify(escrowParams, ctext, proof, upkt[0].Token, escrowPublicKey)); Assert.AreEqual(ctext.E1, CreateGroupElement(ip.Gq, vectors["ie_E1"]), "ie_E1"); Assert.AreEqual(ctext.E2, CreateGroupElement(ip.Gq, vectors["ie_E2"]), "ie_E2"); Assert.AreEqual(ctext.proof.c, Zq.GetElement(HexToBytes(vectors["ie_c"])), "ie_c"); Assert.AreEqual(ctext.proof.rR, Zq.GetElement(HexToBytes(vectors["ie_rr"])), "ie_rr"); Assert.AreEqual(ctext.proof.rXb, Zq.GetElement(HexToBytes(vectors["ie_rxb"])), "ie_rxb"); Assert.AreEqual(ctext.proof.rOb, Zq.GetElement(HexToBytes(vectors["ie_rob"])), "ie_rob"); GroupElement PE = IDEscrowFunctions.Decrypt(escrowParams, ctext, escrowPrivateKey); } #endif #if TEST_DVA_REVOCATION if (committed.Length > 0) { RAParameters raParams = new RAParameters(ip.Gq.GroupName, CreateGroupElement(ip.Gq, vectors["r_K"]), ip.UidH); FieldZqElement delta = Zq.GetElement(HexToBytes(vectors["r_delta"])); RevocationAuthority RA = new RevocationAuthority(raParams, delta); HashSet <FieldZqElement> revoked = new HashSet <FieldZqElement>(); for (int i = 1; i <= 4; i++) { revoked.Add(Zq.GetElement(HexToBytes(vectors["r_R" + i]))); } RA.UpdateAccumulator(revoked, null); Assert.AreEqual(RA.Accumulator, CreateGroupElement(ip.Gq, vectors["r_V"]), "r_V"); int r_id = 0; int.TryParse(vectors["r_id"], out r_id); RevocationWitness witness = RA.ComputeRevocationWitness(revoked, Zq.GetElement(HexToBytes(vectors["x" + r_id]))); Assert.AreEqual(witness.d, Zq.GetElement(HexToBytes(vectors["r_d"])), "r_d"); Assert.AreEqual(witness.W, CreateGroupElement(ip.Gq, vectors["r_W"]), "r_W"); Assert.AreEqual(witness.Q, CreateGroupElement(ip.Gq, vectors["r_Q"]), "r_Q"); NonRevocationProof nrProof = RevocationUser.GenerateNonRevocationProof( raParams, witness, proof.Commitments[0].TildeC, ProtocolHelper.ComputeXi(ip, r_id - 1, A[r_id - 1]), cpv.TildeO[0], new NonRevocationProofGenerationRandomData(new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["r_t1"])), Zq.GetElement(HexToBytes(vectors["r_t2"])), Zq.GetElement(HexToBytes(vectors["r_k1"])), Zq.GetElement(HexToBytes(vectors["r_k2"])), Zq.GetElement(HexToBytes(vectors["r_k3"])), Zq.GetElement(HexToBytes(vectors["r_k4"])), Zq.GetElement(HexToBytes(vectors["r_k5"])), Zq.GetElement(HexToBytes(vectors["r_k6"])) })); Assert.AreEqual(nrProof.X, CreateGroupElement(ip.Gq, vectors["r_X"]), "r_X"); Assert.AreEqual(nrProof.Y, CreateGroupElement(ip.Gq, vectors["r_Y"]), "r_Y"); Assert.AreEqual(nrProof.Cd, CreateGroupElement(ip.Gq, vectors["r_Cd"]), "r_Cd"); Assert.AreEqual(nrProof.cPrime, Zq.GetElement(HexToBytes(vectors["r_cPrime"])), "r_cPrime"); Assert.AreEqual(nrProof.s[0], Zq.GetElement(HexToBytes(vectors["r_s1"])), "r_s1"); Assert.AreEqual(nrProof.s[1], Zq.GetElement(HexToBytes(vectors["r_s2"])), "r_s2"); Assert.AreEqual(nrProof.s[2], Zq.GetElement(HexToBytes(vectors["r_s3"])), "r_s3"); Assert.AreEqual(nrProof.s[3], Zq.GetElement(HexToBytes(vectors["r_s4"])), "r_s4"); Assert.AreEqual(nrProof.s[4], Zq.GetElement(HexToBytes(vectors["r_s5"])), "r_s5"); Assert.AreEqual(nrProof.s[5], Zq.GetElement(HexToBytes(vectors["r_s6"])), "r_s6"); // validate proof RA.VerifyNonRevocationProof(ip, 0, proof, nrProof); } #endif #if TEST_SET_MEMBERSHIP if (committed.Length > 0) { int sm_x_index = 0; int.TryParse(vectors["sm_x_index"], out sm_x_index); int sm_n = 0; int.TryParse(vectors["sm_n"], out sm_n); int sm_i = 0; int.TryParse(vectors["sm_i"], out sm_i); byte[][] setValues = new byte[sm_n][]; FieldZqElement[] sm_c = new FieldZqElement[sm_n - 1]; FieldZqElement[] sm_r = new FieldZqElement[sm_n - 1]; int randomIndex = 0; for (int i = 1; i <= sm_n; i++) { if (i == sm_i) { setValues[i - 1] = HexToBytes(vectors["A" + sm_x_index]); } else { setValues[i - 1] = HexToBytes(vectors["sm_s" + i]); sm_c[randomIndex] = Zq.GetElement(HexToBytes(vectors["sm_c" + i])); sm_r[randomIndex] = Zq.GetElement(HexToBytes(vectors["sm_r" + i])); randomIndex++; } } SetMembershipProofGenerationRandomData smRandom = new SetMembershipProofGenerationRandomData(sm_c, sm_r, Zq.GetElement(HexToBytes(vectors["sm_w"]))); SetMembershipProof setMembershipProof = SetMembershipProof.Generate(pppp, proof, cpv, sm_x_index, setValues, smRandom); for (int i = 1; i <= sm_n; i++) { Assert.AreEqual(setMembershipProof.a[i - 1], CreateGroupElement(ip.Gq, vectors["sm_a" + i]), "sm_a" + i); if (i < sm_n) // no c_n in the proof { Assert.AreEqual(setMembershipProof.c[i - 1], Zq.GetElement(HexToBytes(vectors["sm_c" + i])), "sm_c" + i); } Assert.AreEqual(setMembershipProof.r[i - 1], Zq.GetElement(HexToBytes(vectors["sm_r" + i])), "sm_r" + i); } if (!SetMembershipProof.Verify(vppp, proof, setMembershipProof, sm_x_index, setValues)) { throw new InvalidUProveArtifactException("Invalid set membership proof"); } } #endif } } } } sw.Stop(); Debug.WriteLine("Protocol Test Elapsed Time: " + sw.ElapsedMilliseconds + "ms"); }
public void ProtocolTest() { Stopwatch sw = new Stopwatch(); sw.Start(); bool[] bools = new bool[] { true, false }; foreach (bool isSubgroupConstruction in bools) { foreach (bool supportDevice in bools) { var vectors = supportDevice ? (isSubgroupConstruction ? GetTestVectors("testvectorssubgroup_Device_doc.txt") : GetTestVectors("testvectorsEC_Device_doc.txt")) : (isSubgroupConstruction ? GetTestVectors("testvectorssubgroup_doc.txt") : GetTestVectors("testvectorsEC_doc.txt")); IssuerKeyAndParameters ikap = LoadIssuerKeyAndParameters(isSubgroupConstruction, vectors["GroupName"], supportDevice, vectors); FieldZq Zq = ikap.IssuerParameters.Zq; // replace random y0/g0 with test vector values ikap.PrivateKey = Zq.GetElement(HexToBytes(vectors["y0"])); ikap.IssuerParameters.G[0] = CreateGroupElement(ikap.IssuerParameters.Gq, vectors["g0"]); Assert.AreEqual(ikap.IssuerParameters.G[0], ikap.IssuerParameters.Gq.G.Exponentiate(ikap.PrivateKey), "g0 computation"); IssuerParameters ip = ikap.IssuerParameters; ip.Verify(); /* * issuance */ byte[][] A = new byte[][] { HexToBytes(vectors["A1"]), HexToBytes(vectors["A2"]), HexToBytes(vectors["A3"]), HexToBytes(vectors["A4"]), HexToBytes(vectors["A5"]) }; Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x1"])), ProtocolHelper.ComputeXi(ip, 0, A[0]), "x1"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x2"])), ProtocolHelper.ComputeXi(ip, 1, A[1]), "x2"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x3"])), ProtocolHelper.ComputeXi(ip, 2, A[2]), "x3"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x4"])), ProtocolHelper.ComputeXi(ip, 3, A[3]), "x4"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x5"])), ProtocolHelper.ComputeXi(ip, 4, A[4]), "x5"); byte[] TI = HexToBytes(vectors["TI"]); Assert.IsTrue(HexToBytes(vectors["P"]).SequenceEqual(ip.Digest(supportDevice)), "P"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["xt"])), ProtocolHelper.ComputeXt(ip, TI, supportDevice), "xt"); IDevice device = null; GroupElement hd = null; if (supportDevice) { device = new VirtualDevice(ip, Zq.GetElement(HexToBytes(vectors["xd"])), Zq.GetElement(HexToBytes(vectors["wdPrime"]))); IDevicePresentationContext context = device.GetPresentationContext(); // Test device responses Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["hd"]), device.GetDevicePublicKey(), "hd"); Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["ad"]), context.GetInitialWitness(), "ad"); Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["rdPrime"])), context.GetDeviceResponse(HexToBytes(vectors["md"]), HexToBytes(vectors["mdPrime"]), ip.HashFunctionOID), "rdPrime"); hd = CreateGroupElement(ip.Gq, vectors["hd"]); } IssuerProtocolParameters ipp = new IssuerProtocolParameters(ikap); ipp.Attributes = A; ipp.NumberOfTokens = 1; ipp.TokenInformation = TI; ipp.DevicePublicKey = hd; ipp.PreGeneratedW = new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["w"])) }; Issuer issuer = ipp.CreateIssuer(); byte[] PI = HexToBytes(vectors["PI"]); ProverProtocolParameters ppp = new ProverProtocolParameters(ip); ppp.Attributes = A; ppp.NumberOfTokens = 1; ppp.TokenInformation = TI; ppp.ProverInformation = PI; ppp.DevicePublicKey = hd; ppp.ProverRandomData = new ProverRandomData( new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["alpha"])) }, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta1"])) }, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta2"])) }); Prover prover = ppp.CreateProver(); FirstIssuanceMessage msg1 = issuer.GenerateFirstMessage(); Assert.AreEqual(msg1.sigmaZ, CreateGroupElement(ip.Gq, vectors["sigmaZ"]), "sigmaZ"); Assert.AreEqual(msg1.sigmaA[0], CreateGroupElement(ip.Gq, vectors["sigmaA"]), "sigmaA"); Assert.AreEqual(msg1.sigmaB[0], CreateGroupElement(ip.Gq, vectors["sigmaB"]), "sigmaB"); SecondIssuanceMessage msg2 = prover.GenerateSecondMessage(msg1); Assert.AreEqual(msg2.sigmaC[0], Zq.GetElement(HexToBytes(vectors["sigmaC"])), "sigmaC"); ThirdIssuanceMessage msg3 = issuer.GenerateThirdMessage(msg2); Assert.AreEqual(msg3.sigmaR[0], Zq.GetElement(HexToBytes(vectors["sigmaR"])), "sigmaR"); UProveKeyAndToken[] upkt = prover.GenerateTokens(msg3); Assert.AreEqual(upkt[0].PrivateKey, Zq.GetElement(HexToBytes(vectors["alphaInverse"])), "alphaInverse"); UProveToken token = upkt[0].Token; Assert.AreEqual(token.H, CreateGroupElement(ip.Gq, vectors["h"]), "h"); Assert.AreEqual(token.SigmaZPrime, CreateGroupElement(ip.Gq, vectors["sigmaZPrime"]), "sigmaZPrime"); Assert.AreEqual(token.SigmaCPrime, Zq.GetElement(HexToBytes(vectors["sigmaCPrime"])), "sigmaCPrime"); Assert.AreEqual(token.SigmaRPrime, Zq.GetElement(HexToBytes(vectors["sigmaRPrime"])), "sigmaRPrime"); Assert.IsTrue(HexToBytes(vectors["UIDt"]).SequenceEqual(ProtocolHelper.ComputeTokenID(ip, token)), "UIDt"); Assert.IsTrue(supportDevice == token.IsDeviceProtected); /* * presentation */ int[] disclosed = Array.ConvertAll <string, int>(vectors["D"].Split(','), new Converter <string, int>(stringToInt)); int[] committed = Array.ConvertAll <string, int>(vectors["C"].Split(','), new Converter <string, int>(stringToInt)); byte[] m = HexToBytes(vectors["m"]); byte[] md = null; IDevicePresentationContext deviceContext = null; if (supportDevice) { md = HexToBytes(vectors["md"]); deviceContext = device.GetPresentationContext(); } int p; if (!int.TryParse(vectors["p"], out p)) { p = PresentationProof.DeviceAttributeIndex; } byte[] s = HexToBytes(vectors["s"]); int commitmentIndex = committed[0]; ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(ip, disclosed, m, upkt[0], A); pppp.Committed = committed; pppp.PseudonymAttributeIndex = p; pppp.PseudonymScope = s; pppp.DeviceMessage = md; pppp.DeviceContext = deviceContext; pppp.RandomData = new ProofGenerationRandomData( Zq.GetElement(HexToBytes(vectors["w0"])), new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["w1"])), Zq.GetElement(HexToBytes(vectors["w3"])), Zq.GetElement(HexToBytes(vectors["w4"])) }, supportDevice ? Zq.GetElement(HexToBytes(vectors["wd"])) : null, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["tildeO" + commitmentIndex])), }, new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["tildeW" + commitmentIndex])) }); CommitmentPrivateValues cpv; PresentationProof proof = PresentationProof.Generate(pppp, out cpv); Assert.IsTrue(HexToBytes(vectors["a"]).SequenceEqual(proof.A), "a"); Assert.AreEqual(ProtocolHelper.GenerateScopeElement(ip.Gq, s), CreateGroupElement(ip.Gq, vectors["gs"])); Assert.IsTrue(HexToBytes(vectors["ap"]).SequenceEqual(proof.Ap), "ap"); Assert.AreEqual(proof.Ps, CreateGroupElement(ip.Gq, vectors["Ps"]), "Ps"); Assert.IsTrue(HexToBytes(vectors["A2"]).SequenceEqual(proof.DisclosedAttributes[0]), "A2"); Assert.IsTrue(HexToBytes(vectors["A5"]).SequenceEqual(proof.DisclosedAttributes[1]), "A5"); Assert.AreEqual(proof.R[0], Zq.GetElement(HexToBytes(vectors["r0"])), "r0"); Assert.AreEqual(proof.R[1], Zq.GetElement(HexToBytes(vectors["r1"])), "r1"); Assert.AreEqual(proof.R[2], Zq.GetElement(HexToBytes(vectors["r3"])), "r3"); Assert.AreEqual(proof.R[3], Zq.GetElement(HexToBytes(vectors["r4"])), "r4"); if (supportDevice) { Assert.AreEqual(proof.R[4], Zq.GetElement(HexToBytes(vectors["rd"])), "rd"); } Assert.AreEqual(proof.Commitments[0].TildeR, Zq.GetElement(HexToBytes(vectors["tildeR" + commitmentIndex])), "tildeR" + commitmentIndex); Assert.IsTrue(cpv.TildeO.Length == 1); Assert.AreEqual(cpv.TildeO[0], Zq.GetElement(HexToBytes(vectors["tildeO" + commitmentIndex])), "tildeO" + commitmentIndex); VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ip, disclosed, m, upkt[0].Token); vppp.Committed = committed; vppp.PseudonymAttributeIndex = p; vppp.PseudonymScope = s; vppp.DeviceMessage = md; proof.Verify(vppp); } } sw.Stop(); Debug.WriteLine("Protocol Test Elapsed Time: " + sw.ElapsedMilliseconds + "ms"); }