public void TestIEWithSerialized() { // Does a complete encrypt/decrypt sequence from serialized values. // Kind of redundant because each of the testmethods above test serialization // of individual data types //Serialize and deserialize all objects IDEscrowParams ieParam2 = ip.Deserialize <IDEscrowParams>(ip.Serialize(ieParam)); IDEscrowPublicKey pk2 = ip.Deserialize <IDEscrowPublicKey>(ip.Serialize(pk)); IDEscrowPrivateKey sk2 = ip.Deserialize <IDEscrowPrivateKey>(ip.Serialize(sk)); // Encrypt FieldZq F = ip.Zq; FieldZqElement xb2 = F.GetRandomElement(true); FieldZqElement ob2 = F.GetRandomElement(true); GroupElement Cxb2 = ip.Gq.G.Exponentiate(xb2); // Cxb = g^xb Cxb2 = Cxb2.Multiply(ip.G[1].Exponentiate(ob2)); // Cxb = (g^xb)*(g1^ob) GroupElement PE2 = ieParam2.Ge.Exponentiate(xb2); IDEscrowCiphertext ctext2 = IDEscrowFunctions.VerifiableEncrypt(ieParam2, pk2, tokenID, Cxb2, xb2, ob2, additionalInfo); ctext2 = ip.Deserialize <IDEscrowCiphertext>(ip.Serialize(ctext2)); // Verify bool isValid = IDEscrowFunctions.Verify(ieParam2, ctext2, tokenID, pk2, Cxb2); Assert.IsTrue(isValid); // Decrypt GroupElement PEPrime = IDEscrowFunctions.Decrypt(ieParam2, ctext2, sk2); Assert.IsTrue(PE2.Equals(PEPrime)); }
public void TestIEEncrypt() { // Create a commitment and attribute value. // Need g, g1, Cxb, xb, ob FieldZq F = ip.Zq; FieldZqElement xb = F.GetRandomElement(true); FieldZqElement ob = F.GetRandomElement(true); Cxb = ip.Gq.G.Exponentiate(xb); // Cxb = g^xb Cxb = Cxb.Multiply(ip.G[1].Exponentiate(ob)); // Cxb = (g^xb)*(g1^ob) // Create the pseudonym (which will be used later to check that decryption is correct) PE = ieParam.Ge.Exponentiate(xb); // Encrypt ctext = IDEscrowFunctions.VerifiableEncrypt(ieParam, pk, tokenID, Cxb, xb, ob, additionalInfo); // Serialize string ctextStr = ip.Serialize(ctext); Assert.IsFalse(ctextStr.Contains(":null")); // deserialize and compare IDEscrowCiphertext ctext2 = ip.Deserialize <IDEscrowCiphertext>(ctextStr); Assert.IsTrue(ctext.Equals(ctext2)); }
/// <summary> /// Generates a <code>IDEscrowProofGenerationRandomData</code> instance using the internal RNG. /// </summary> /// <param name="Zq">Field Zq</param> /// <returns>A pregenerated set of random values.</returns> internal static IDEscrowProofGenerationRandomData Generate(FieldZq Zq) { return(new IDEscrowProofGenerationRandomData( Zq.GetRandomElement(false), Zq.GetRandomElement(false), Zq.GetRandomElement(false), Zq.GetRandomElement(false) )); }
/// <summary> /// Generates a <code>ProofGenerationRandomData</code> instance using the internal RNG. /// </summary> /// <param name="numUndisclosed">Number of undisclosed attributes.</param> /// <param name="numCommitted">Number of committed attributes.</param> /// <param name="Zq">Field Zq</param> /// <param name="isDeviceProtected">True if a toke is device-protected.</param> /// <returns>A pregenerated set of random values.</returns> internal static ProofGenerationRandomData Generate(int numUndisclosed, int numCommitted, FieldZq Zq, bool isDeviceProtected) { return(new ProofGenerationRandomData( Zq.GetRandomElement(false), Zq.GetRandomElements(numUndisclosed, false), isDeviceProtected ? Zq.GetRandomElement(false) : null, numCommitted > 0 ? Zq.GetRandomElements(numCommitted, false) : null, numCommitted > 0 ? Zq.GetRandomElements(numCommitted, false) : null )); }
/// <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 ProverSetMembershipParameters GeneratePSMParameters(int indexOfCommittedValue, int memberSetLength) { if (indexOfCommittedValue >= memberSetLength) { throw new ArgumentException("indexOfCommittedValue should be less than memberSetLength"); } FieldZq fieldZq = FieldZq.CreateFieldZq(_cryptoParameters.Group.Q); FieldZqElement committedValue = fieldZq.GetRandomElement(true); PedersenCommitment ped = new PedersenCommitment(committedValue, _cryptoParameters); FieldZqElement[] memberSet = fieldZq.GetRandomElements(memberSetLength, true); memberSet[indexOfCommittedValue] = committedValue; return(new ProverSetMembershipParameters(ped, memberSet, _cryptoParameters)); }
public void EncodingTest() { // a large value byte[] modulus = new byte[] { 0xef, 0x09, 0x90, 0x06, 0x1d, 0xb6, 0x7a, 0x9e, 0xae, 0xba, 0x26, 0x5f, 0x1b, 0x8f, 0xa1, 0x2b, 0x55, 0x33, 0x90, 0xa8, 0x17, 0x5b, 0xcb, 0x3d, 0x0c, 0x2e, 0x5e, 0xe5, 0xdf, 0xb8, 0x26, 0xe2, 0x29, 0xad, 0x37, 0x43, 0x11, 0x48, 0xce, 0x31, 0xf8, 0xb0, 0xe5, 0x31, 0x77, 0x7f, 0x19, 0xc1, 0xe3, 0x81, 0xc6, 0x23, 0xe6, 0x00, 0xbf, 0xf7, 0xc5, 0x5a, 0x23, 0xa8, 0xe6, 0x49, 0xcc, 0xbc, 0xf8, 0x33, 0xf2, 0xdb, 0xa9, 0x9e, 0x6a, 0xd6, 0x6e, 0x52, 0x37, 0x8e, 0x92, 0xf7, 0x49, 0x2b, 0x24, 0xff, 0x8c, 0x1e, 0x6f, 0xb1, 0x89, 0xfa, 0x84, 0x34, 0xf5, 0x40, 0x2f, 0xe4, 0x15, 0x24, 0x9a, 0xe0, 0x2b, 0xf9, 0x2b, 0x3e, 0xd8, 0xea, 0xaa, 0xa2, 0x20, 0x2e, 0xc3, 0x41, 0x7b, 0x20, 0x79, 0xda, 0x4f, 0x35, 0xe9, 0x85, 0xbb, 0x42, 0xa4, 0x21, 0xcf, 0xab, 0xa8, 0x16, 0x0b, 0x66, 0x94, 0x99, 0x83, 0x38, 0x4e, 0x56, 0x36, 0x5a, 0x44, 0x86, 0xc0, 0x46, 0x22, 0x9f, 0xc8, 0xc8, 0x18, 0xf9, 0x30, 0xb8, 0x0a, 0x60, 0xd6, 0xc2, 0xc2, 0xe2, 0x0c, 0x5d, 0xf8, 0x80, 0x53, 0x4d, 0x42, 0x40, 0xd0, 0xd8, 0x1e, 0x9a, 0x37, 0x0e, 0xef, 0x67, 0x6a, 0x1c, 0x3b, 0x0e, 0xd1, 0xd8, 0xff, 0x30, 0x34, 0x0a, 0x96, 0xb2, 0x1b, 0x89, 0xf6, 0x9c, 0x54, 0xce, 0xb8, 0xf3, 0xdf, 0x17, 0xe3, 0x1b, 0xc2, 0x0c, 0x5b, 0x60, 0x1e, 0x99, 0x44, 0x45, 0xa1, 0xd3, 0x47, 0xa4, 0x5d, 0x95, 0xf4, 0x1a, 0xe0, 0x71, 0x76, 0xc7, 0x38, 0x0c, 0x60, 0xdb, 0x2a, 0xce, 0xdd, 0xee, 0xda, 0x5c, 0x59, 0x80, 0x96, 0x43, 0x62, 0xe3, 0xa8, 0xdd, 0x3f, 0x97, 0x3d, 0x6d, 0x4b, 0x24, 0x1b, 0xcf, 0x91, 0x0c, 0x7f, 0x7a, 0x02, 0xed, 0x3b, 0x60, 0x38, 0x3a, 0x01, 0x02, 0xd8, 0x06, 0x0c, 0x27 }; FieldZq field = FieldZq.CreateFieldZq(modulus); for (int i = 0; i < 20; i++) { FieldZqElement r = field.GetRandomElement(false); FieldZqElement r2 = field.GetElement(r.ToByteArray()); Assert.AreEqual <FieldZqElement>(r, r2); } }
private void RandomElementTest(int fieldSize, bool nonZero, bool checkDistribution) { byte[] modulusBytes = BitConverter.GetBytes(fieldSize); Array.Reverse(modulusBytes); // need big endian FieldZq field = FieldZq.CreateFieldZq(modulusBytes); Dictionary <FieldZqElement, int> counts = new Dictionary <FieldZqElement, int>(); int rangeSize = (nonZero) ? fieldSize - 1 : fieldSize; int iters = (checkDistribution) ? 1000 * rangeSize : 5 * rangeSize; for (int i = 0; i < iters; i++) { FieldZqElement el = field.GetRandomElement(nonZero); if (counts.ContainsKey(el)) { int val = counts[el]; val++; counts.Remove(el); counts.Add(el, val); } else { counts.Add(el, 1); } if (nonZero) { Assert.AreNotEqual(el, field.Zero); } } double expectedHitRate = 1.0f / (double)rangeSize; double errorMargin = .3 * expectedHitRate; foreach (KeyValuePair <FieldZqElement, int> kvp in counts) { double hitRate = (double)kvp.Value / (double)iters; if (Math.Abs(hitRate - expectedHitRate) > errorMargin) { Assert.Fail("Random number generator did not produce a good distribution"); } } }
public void BDDecompositionTest() { FieldZqElement zero; FieldZqElement one; FieldZqElement two; FieldZqElement five; FieldZqElement ten; BitArray dec; FieldZqElement recompose; for (int paramIndex = 0; paramIndex < _parameters.Length; ++paramIndex) { FieldZq field = _parameters[paramIndex].FieldZq; zero = field.Zero; one = field.One; two = field.GetElement(2); five = field.GetElement(5); ten = field.GetElement(10); dec = VerifierBitDecompositionParameters.GetBitDecomposition(one, 10, field); recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field); Assert.AreEqual(one, recompose); Assert.AreEqual(true, dec.Get(0), "first bit should be one"); Assert.AreEqual(false, dec.Get(1), "second bit should be zero"); Assert.AreEqual(10, dec.Length, "decomposition length should be 10"); dec = VerifierBitDecompositionParameters.GetBitDecomposition(two, 20, field); recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field); Assert.AreEqual(20, dec.Length, "decomposition length should be 10"); Assert.AreEqual(two, recompose); Assert.AreEqual(false, dec[0], "first bit is 0"); Assert.AreEqual(true, dec[1], "second bit is 1"); Assert.AreEqual(false, dec[2], "third bit is 0"); Assert.AreEqual(false, dec[19], "last bit is 0"); dec = VerifierBitDecompositionParameters.GetBitDecomposition(five, 30, field); recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field); Assert.AreEqual(30, dec.Length, "decomposition length should be 30"); Assert.AreEqual(five, recompose); Assert.AreEqual(true, dec[0], "first bit is 1"); Assert.AreEqual(false, dec[1], "second bit is 0"); Assert.AreEqual(true, dec[2], "third bit is 1"); Assert.AreEqual(false, dec[3], "fourth bit is 0"); Assert.AreEqual(false, dec[4], "fifth bit is 0"); Assert.AreEqual(false, dec[29], "last bit is 0"); dec = VerifierBitDecompositionParameters.GetBitDecomposition(ten, 30, field); recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field); Assert.AreEqual(30, dec.Length, "decomposition length should be 30"); Assert.AreEqual(ten, recompose); Assert.AreEqual(false, dec[0], "first bit is 0"); Assert.AreEqual(true, dec[1], "second bit is 1"); Assert.AreEqual(false, dec[2], "third bit is 0"); Assert.AreEqual(true, dec[3], "fourth bit is 1"); Assert.AreEqual(false, dec[4], "fifth bit is 0"); Assert.AreEqual(false, dec[29], "last bit is 0"); FieldZqElement random = field.GetRandomElement(true); dec = VerifierBitDecompositionParameters.GetBitDecomposition(random, 0, field); recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field); Assert.AreEqual(random, recompose, "recomposition failed"); } }
/// <summary> /// Generates a <code>SetMembershipProofGenerationRandomData</code> instance using the internal RNG. /// </summary> /// <param name="Zq">Field Zq.</param> /// <param name="length">Desired length of the <c>c</c> and <c>r</c> arrays.</param> /// <returns>A pregenerated set of random values.</returns> public static SetMembershipProofGenerationRandomData Generate(FieldZq Zq, int length) { return(new SetMembershipProofGenerationRandomData(Zq.GetRandomElements(length, false), Zq.GetRandomElements(length, false), Zq.GetRandomElement(false))); }
/// <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)); }