/// <summary> /// Computes the revocation witness for a specific user attribute. /// </summary> /// <param name="revoked">Set of revoked values.</param> /// <param name="xid">The user attribute.</param> /// <returns>A revocation witness.</returns> public RevocationWitness ComputeRevocationWitness(HashSet <FieldZqElement> revoked, FieldZqElement xid) { if (revoked.Contains(xid)) { throw new ArgumentException("xid cannot be in revoked set"); } Group Gq = RAParameters.group; FieldZq Zq = Gq.FieldZq; FieldZqElement d = Zq.One; FieldZqElement deltaPlusXProd = Zq.One; foreach (var x in revoked) { if (x + this.PrivateKey == Zq.Zero) { throw new ArgumentException("revocationList cannot contain the negation of the private key"); } d *= (x - xid); deltaPlusXProd *= (this.PrivateKey + x); } GroupElement W = RAParameters.gt.Exponentiate((deltaPlusXProd - d) * (PrivateKey + xid).Invert()); GroupElement Q = Gq.MultiExponentiate(new GroupElement[] { Accumulator, W, RAParameters.gt }, new FieldZqElement[] { Zq.One, xid.Negate(), d.Negate() }); return(new RevocationWitness(d, W, Q)); }
/// <summary> /// Create a new object to hold the proof values. /// </summary> public IDEscrowProof(FieldZqElement c, FieldZqElement rXb, FieldZqElement rR, FieldZqElement rOb) { this.c = c; this.rXb = rXb; this.rR = rR; this.rOb = rOb; }
/// <summary> /// Returns verifier parameters corresponding to prover parameters generated by /// GetDateTimeProverParameters. /// </summary> /// <param name="crypto">Cryptographic parameters.</param> /// <param name="commitmentToDayOfYear">Prover supplied commitment to day of year in [0,365].</param> /// <param name="commitmentToYear">Prover supplied commitment to year in [minYear, maxYear].</param> /// <param name="rangeProofType">Range proof type.</param> /// <param name="verifierTargetDate">verifier target date in [minYear, maxYear+1).</param> /// <param name="minYear">Used to determine range. Must be same as used by prover.</param> /// <param name="maxYear">Used to determine range. Must be same as used by prover.</param> /// <returns></returns> public static VerifierRangeProofParameters GetDateTimeVerifierParameters(CryptoParameters crypto, GroupElement commitmentToYear, GroupElement commitmentToDayOfYear, VerifierRangeProofParameters.ProofType rangeProofType, DateTime verifierTargetDate, int minYear, int maxYear) { // Compute (commitmentToYear / G^minYear)^366 * commitmentToDayOfYear GroupElement[] bases = new GroupElement[] { commitmentToYear, crypto.G }; FieldZqElement[] exponents = new FieldZqElement[] { crypto.FieldZq.GetElement(366), crypto.FieldZq.GetElement((uint)(minYear * 366)).Negate() }; GroupElement commitmentToYearAndDay = crypto.Group.MultiExponentiate(bases, exponents) * commitmentToDayOfYear; int maxValue = (maxYear - minYear) * 366 + 365; int verifierYearAndDay = EncodeYearAndDay(verifierTargetDate, minYear); return(new VerifierRangeProofParameters( crypto, commitmentToYearAndDay, rangeProofType, verifierYearAndDay, 0, maxValue)); }
/// <summary> /// This setup method initializes the issuer, do it once and save the IssuerParameters they were used for verifying the issuer later (Verifier / Prover) /// and are used for initiate the issuer at another time /// </summary> /// <param name="UIDP">issuer identifier</param> /// <param name="appSpecification">description for the issuer</param> /// <param name="maxNumberOfAttributes">number of attributes which should be supported in a token -> max allowed attributes are 25</param> /// <param name="groupType">ECC or Subgroup</param> /// <param name="supportDevice">ture, if the issuer allows to protect a token with a hard tokens</param> public IssuingIssuer(string UIDP, string appSpecification, int maxNumberOfAttributes, GroupType groupType = GroupType.ECC, bool supportDevice = false) { isDeviceProtected = supportDevice; try { // max allowed are 50 attributes if (maxNumberOfAttributes > 50) { throw new Exception("General supported are max 25 attributes"); } IssuerSetupParameters isp = new IssuerSetupParameters(maxNumberOfAttributes); isp.UidP = encoding.GetBytes(UIDP); isp.S = encoding.GetBytes(appSpecification); isp.GroupConstruction = groupType; isp.UseRecommendedParameterSet = true; ikap = isp.Generate(isDeviceProtected); privateKey = ikap.PrivateKey; string pk = privateKey.ToBase64String(); string ipJSON = ikap.IssuerParameters.Serialize(); LogService.Log(LogService.LogType.Info, "IssuingIssuer - successfully set up. IssuerParameters are: '" + ipJSON + "'"); } catch (Exception e) { LogService.Log(LogService.LogType.FatalError, "IssuingIssuer - Error during issuer setup.", e); throw new CommunicationException("IssuingIssuer - Error during issuer setup", e); } }
/// <summary> /// Generates the second issuance message. /// </summary> /// <param name="message">The first issuance message.</param> /// <returns>The second issuance message.</returns> public SecondIssuanceMessage GenerateSecondMessage(FirstIssuanceMessage message) { if (state != State.Initialized) { throw new InvalidOperationException("Prover not initialized properly"); } Group Gq = ip.Gq; this.sigmaZ = message.sigmaZ.Exponentiate(beta0Inverse); // remove the blind that was included in gamma (if no blind beta0Inverse = 1) sigmaZPrime = new GroupElement[numberOfTokens]; sigmaAPrime = new GroupElement[numberOfTokens]; sigmaBPrime = new GroupElement[numberOfTokens]; sigmaCPrime = new FieldZqElement[numberOfTokens]; FieldZqElement[] sigmaC = new FieldZqElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { FieldZqElement sigmaBExponent = alpha[i].Multiply(beta0Inverse); // will remove the collab-issuance blind, if present sigmaZPrime[i] = this.sigmaZ.Exponentiate(alpha[i]); sigmaAPrime[i] = t1[i] * message.sigmaA[i]; sigmaBPrime[i] = Gq.MultiExponentiate(new GroupElement[] { sigmaZPrime[i], h[i], message.sigmaB[i] }, new FieldZqElement[] { beta1[i], beta2[i], sigmaBExponent }); HashFunction hash = ip.HashFunction; hash.Hash(h[i]); hash.Hash(PI); hash.Hash(sigmaZPrime[i]); hash.Hash(sigmaAPrime[i]); hash.Hash(sigmaBPrime[i]); sigmaCPrime[i] = ip.Zq.GetElementFromDigest(hash.Digest); sigmaC[i] = sigmaCPrime[i] + beta1[i]; } state = State.Second; return(new SecondIssuanceMessage(sigmaC)); }
public static void MyClassInitialize(TestContext testContext) { // // generate issuer parameters // IssuerSetupParameters isp = new IssuerSetupParameters(maxNumberOfAttributes); isp.UidP = new byte[] { (byte)0 }; //isp.NumberOfAttributes = 1; isp.E = new byte[] { (byte)0 }; // encode xid directly has an IssuerKeyAndParameters ikap = isp.Generate(); ip = ikap.IssuerParameters; // // issue a token // xid = ip.Gq.FieldZq.GetRandomElement(false); IssuerProtocolParameters ipp = new IssuerProtocolParameters(ikap); ProverProtocolParameters ppp = new ProverProtocolParameters(ip); attributes = new byte[][] { xid.ToByteArray() }; ipp.Attributes = ppp.Attributes = attributes; ipp.NumberOfTokens = ppp.NumberOfTokens = 1; Issuer issuer = ipp.CreateIssuer(); Prover prover = ppp.CreateProver(); upkt = prover.GenerateTokens(issuer.GenerateThirdMessage(prover.GenerateSecondMessage(issuer.GenerateFirstMessage())))[0]; }
/// <summary> /// Constructs a new <code>ProverRandomData</code> instance. /// </summary> /// <param name="alpha">An array of alpha values.</param> /// <param name="beta1">An array of beta1 values.</param> /// <param name="beta2">An array of beta2 values.</param> /// <param name="beta0">A beta0 value. Defaults to <code>null</code>.</param> public ProverRandomData(FieldZqElement[] alpha, FieldZqElement[] beta1, FieldZqElement[] beta2, FieldZqElement beta0 = null) { this.beta0 = beta0; this.alpha = alpha; this.beta1 = beta1; this.beta2 = beta2; }
/// <summary> /// Checks that the token public key is consistent with the other token values. /// </summary> /// <returns></returns> public bool Validate(GroupElement devicePublicKey) { // compute H from token manually FieldZqElement[] exponents = new FieldZqElement[this.G.Length]; exponents[0] = this.Alpha; for (int i = 0; i < this.NumberOfAttributesXI; ++i) { exponents[i + 1] = this.AttributeXI(i + 1) * this.Alpha; } exponents[exponents.Length - 1] = this.AttributeXT * this.Alpha; GroupElement expectedPublicKey = this.Group.MultiExponentiate(this.G, exponents); // factor in device public key if (devicePublicKey != null) { expectedPublicKey *= devicePublicKey; } // check public key (this also validates all other elements in token). if (this.PublicKey != expectedPublicKey) { return(false); } return(true); }
/// <summary> /// Creates a UProve token for non-device protected tokens. /// </summary> /// <param name="pppp">Prover presentation protocol parameters for non-device protected token.</param> /// <param name="device">Device information. Required for device protected tokens.</param> public OpenUProveToken(ProverPresentationProtocolParameters pppp) : base(null, null, null) { if (pppp == null) { throw new ArgumentNullException("UProveToken constructor expects non-null input."); } this.Group = pppp.IP.Gq; this.Bases = new GroupElement[pppp.Attributes.Length + 2]; for (int i = 0; i < this.G.Length; ++i) { this.G[i] = pppp.IP.G[i]; } this.Value = pppp.KeyAndToken.Token.H; this.Exponents = new FieldZqElement[this.RepresentationLength]; this.Alpha = pppp.KeyAndToken.PrivateKey.Invert(); FieldZqElement [] attributes = new FieldZqElement[pppp.Attributes.Length]; for (int i = 0; i < attributes.Length; ++i) { attributes[i] = ProtocolHelper.ComputeXi(pppp.IP, i, pppp.Attributes[i]); } this.SetAttributeXI(attributes); this.AttributeXT = ProtocolHelper.ComputeXt(pppp.IP, pppp.KeyAndToken.Token.TI, pppp.KeyAndToken.Token.IsDeviceProtected); }
/// <summary> /// Takes as input a series of commitments to 0 and 1, and composes them into a single Pedersen commitment: /// output.CommittedValue = product (2^i * committedBits[i].CommittedValue) /// </summary> /// <param name="committedBits">Array of commitments to Zero and One. Each commitment must use the same bases G and H.</param> /// <param name="fieldZq">Field corresponding to all PedersenCommitments</param> /// <param name="composition">Output paramter.</param> /// <returns>True on success, false on failure.</returns> private static bool ComposeCommitments(PedersenCommitment[] committedBits, FieldZq fieldZq, out PedersenCommitment composition) { try { FieldZqElement two = fieldZq.GetElement(2); FieldZqElement powerOfTwo = fieldZq.One; DLRepOfGroupElement[] bitsExpPowerOfTwo = new DLRepOfGroupElement[committedBits.Length]; for (int i = 0; i < committedBits.Length; ++i) { bitsExpPowerOfTwo[i] = committedBits[i].Exponentiate(powerOfTwo); powerOfTwo = powerOfTwo * two; } DLRepOfGroupElement actualComposition; bool success = DLRepOfGroupElement.TryStrictMultiply(bitsExpPowerOfTwo, out actualComposition); if (success) { composition = new PedersenCommitment(actualComposition); return(true); } } catch (Exception) { // do nothing } composition = null; return(false); }
public void GroupDivideTest() { Group group = ECParameterSets.ParamSet_EC_P384_V1.Group; for (int i = 0; i < 10; ++i) { GroupElement a = group.GetRandomElement(false); GroupElement b = group.GetRandomElement(true); GroupElement c = group.Divide(a, b); Assert.AreEqual <GroupElement>(a * group.Invert(b), c, "a.divide(b)."); } for (int i = 0; i < 20; ++i) { FieldZqElement a = group.FieldZq.GetRandomElement(true); FieldZqElement b = group.FieldZq.GetRandomElement(true); Assert.AreEqual(group.G.Exponentiate(a - b), group.Divide(group.G.Exponentiate(a), group.G.Exponentiate(b))); } FieldZqElement one = _smallGroup.FieldZq.One; FieldZqElement two = _smallGroup.FieldZq.GetElement(2); FieldZqElement three = _smallGroup.FieldZq.GetElement(3); FieldZqElement four = _smallGroup.FieldZq.GetElement(4); GroupElement G = _smallGroup.G; Assert.AreEqual <GroupElement>(_smallGroup.Invert(G), _smallGroup.Divide(G.Exponentiate(two), G.Exponentiate(three)), "G^2/G^3"); Assert.AreEqual <GroupElement>(G.Exponentiate(two), _smallGroup.Divide(G.Exponentiate(one), G.Exponentiate(four)), "G^1/G^4"); Assert.AreEqual <GroupElement>(G.Exponentiate(three), _smallGroup.Divide(G.Exponentiate(one), G.Exponentiate(three)), "G^1/G^3"); }
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> /// Verifies that a UProve token attribute is not equal to the given attribute value. /// </summary> /// <param name="verifier">Verifier info about token.</param> /// <param name="attributeIndexForVerifier">Target attribute, 1-based index.</param> /// <param name="attributeValue">Bad value for attribute.</param> /// <returns></returns> public bool Verify( VerifierPresentationProtocolParameters verifier, int attributeIndexForVerifier, byte [] attributeValue) { // Verify UProve Integration Proof if (this.UPIProof == null) { return(false); } VerifierPresentationProtocolParameters[] verifiers = new VerifierPresentationProtocolParameters[1] { verifier }; int[] attributeIndices = new int[1] { attributeIndexForVerifier }; if (!this.UPIProof.Verify(verifiers, attributeIndices)) { return(false); } // Verify Inequality Proof FieldZqElement committedAttribute = ProtocolHelper.ComputeXi(verifier.IP, attributeIndexForVerifier - 1, attributeValue); VerifierInequalityProofParameters ieqVerifier = new VerifierInequalityProofParameters(this.UPIProof.PedersenCommitmentValues[0], committedAttribute, new CryptoParameters(verifier.IP)); return(this.Verify(ieqVerifier)); }
/// <summary> /// If verifier knows Integer B, returns the default bit-decomposition. Returns Null if verifier does not know integer B. /// If bit[i] = 0, output[i] = verifier.G^0. /// If bit[i] = 1, output[i] = verifier.G. /// </summary> /// <param name="verifier">Verifier parameters.</param> /// <returns></returns> private static DLRepOfGroupElement[] DefaultOpenDecompositionOfIntegerB(VerifierRangeProofParameters verifier) { if (!verifier.IntegerBIsKnown) { return(null); } FieldZqElement integerB = verifier.FieldZq.GetElement((uint)verifier.RangeNormalizedIntegerB); int decompositionLength = ComputeDecompositionLength(verifier); BitArray bitsB = VerifierBitDecompositionParameters.GetBitDecomposition(integerB, decompositionLength, verifier.FieldZq); PedersenCommitment[] defaultBitDecomposition = new PedersenCommitment[bitsB.Length]; GroupElement [] bases = new GroupElement [2] { verifier.G, verifier.H }; FieldZqElement [] exponent0 = new FieldZqElement[2] { verifier.FieldZq.Zero, verifier.FieldZq.Zero, }; FieldZqElement [] exponent1 = new FieldZqElement[2] { verifier.FieldZq.One, verifier.FieldZq.Zero, }; for (int i = 0; i < defaultBitDecomposition.Length; ++i) { if (!bitsB.Get(i)) { defaultBitDecomposition[i] = new PedersenCommitment(bases, exponent0, verifier.Group); } else { defaultBitDecomposition[i] = new PedersenCommitment(bases, exponent1, verifier.Group); } } return(defaultBitDecomposition); }
public void InequalityProofSerializationTest() { for (int i = 0; i < StaticHelperClass.ParameterArray.Length; ++i) { CryptoParameters crypto = StaticHelperClass.ParameterArray[i]; FieldZqElement x = crypto.FieldZq.GetElement(1000); FieldZqElement y = crypto.FieldZq.GetElement(2000); PedersenCommitment X = new PedersenCommitment(x, crypto); PedersenCommitment Y = new PedersenCommitment(y, crypto); ProverInequalityProofParameters prover = new ProverInequalityProofParameters(X, Y, crypto); InequalityProof proof = new InequalityProof(prover); string json = CryptoSerializer.Serialize <InequalityProof>(proof); InequalityProof deserialized = CryptoSerializer.Deserialize <InequalityProof>(json); Assert.IsTrue(proof.Verify(prover), "Verify proof"); Assert.AreEqual(proof.A, deserialized.A, "A"); Assert.AreEqual(proof.B, deserialized.B, "B"); prover = new ProverInequalityProofParameters(X, y, crypto); proof = new InequalityProof(prover); json = CryptoSerializer.Serialize <InequalityProof>(proof); deserialized = CryptoSerializer.Deserialize <InequalityProof>(json); Assert.IsTrue(proof.Verify(prover), "Verify proof"); Assert.AreEqual(proof.A, deserialized.A, "A"); Assert.AreEqual(proof.B, deserialized.B, "B"); } }
public void InequalityParamsSerializationTest() { for (int i = 0; i < StaticHelperClass.ParameterArray.Length; ++i) { CryptoParameters crypto = StaticHelperClass.ParameterArray[i]; FieldZqElement x = crypto.FieldZq.GetElement(1000); FieldZqElement y = crypto.FieldZq.GetElement(2000); PedersenCommitment X = new PedersenCommitment(x, crypto); PedersenCommitment Y = new PedersenCommitment(y, crypto); VerifierInequalityProofParameters verifier = new VerifierInequalityProofParameters(X.Value, Y.Value, crypto); string json = CryptoSerializer.Serialize <VerifierInequalityProofParameters>(verifier); VerifierInequalityProofParameters deserialized = CryptoSerializer.Deserialize <VerifierInequalityProofParameters>(json); StaticHelperClass.AssertProofParametersAreEqual(verifier, deserialized, "Verifier X Y"); verifier = new VerifierInequalityProofParameters(X.Value, y, crypto); json = CryptoSerializer.Serialize <VerifierInequalityProofParameters>(verifier); deserialized = CryptoSerializer.Deserialize <VerifierInequalityProofParameters>(json); StaticHelperClass.AssertProofParametersAreEqual(verifier, deserialized, "Verifier X value"); ProverInequalityProofParameters prover = new ProverInequalityProofParameters(X, Y, crypto); json = CryptoSerializer.Serialize <ProverInequalityProofParameters>(prover); ProverInequalityProofParameters dProver = CryptoSerializer.Deserialize <ProverInequalityProofParameters>(json); StaticHelperClass.AssertProofParametersAreEqual(dProver, prover, "Prover X Y"); prover = new ProverInequalityProofParameters(X, y, crypto); json = CryptoSerializer.Serialize <ProverInequalityProofParameters>(prover); dProver = CryptoSerializer.Deserialize <ProverInequalityProofParameters>(json); StaticHelperClass.AssertProofParametersAreEqual(dProver, prover, "Prover X value"); } }
public void SimpleConstructorTest() { for (int i = 0; i < _parameters.Length; ++i) { FieldZqElement committedValue = _parameters[i].FieldZq.GetRandomElement(true); GroupElement g = _parameters[i].G; GroupElement h = _parameters[i].H; PedersenCommitment pedCom1 = new PedersenCommitment(committedValue, _parameters[i]); FieldZqElement opening = pedCom1.ExponentAtIndex(1); Assert.AreEqual(g, pedCom1.BaseAtIndex(0), "pedcom1 has wrong base_0"); Assert.AreEqual(h, pedCom1.BaseAtIndex(1), "pedcom1 has wrong base_1"); Assert.AreEqual(committedValue, pedCom1.CommittedValue, "pedcom1 used wrong committed value"); GroupElement expectedCommitmentValue = g.Exponentiate(committedValue) * h.Exponentiate(opening); Assert.AreEqual(expectedCommitmentValue, pedCom1.Value, "pedcom1 computed wrong value"); PedersenCommitment pedCom2 = new PedersenCommitment(g, h, committedValue, opening, _parameters[i].Group); Assert.AreEqual(pedCom1, pedCom2, "pedcom1 and pedcom2 different"); FieldZqElement[] exponents = new FieldZqElement[2] { committedValue, opening }; GroupElement[] bases = new GroupElement[2] { g, h }; PedersenCommitment pedCom3 = new PedersenCommitment(bases, exponents, _parameters[i].Group); Assert.AreEqual(pedCom1, pedCom3, "pedcom1 and pedcom3 different"); Assert.AreEqual(pedCom2, pedCom3, "pedcom2 and pedcom3 different"); } }
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)); }
/// <summary> /// Generates the third issuance message. /// </summary> /// <param name="message">The second issuance message.</param> /// <returnn>The third issuance message.</returnn> public ThirdIssuanceMessage GenerateThirdMessage(SecondIssuanceMessage message) { if (state != State.First) { throw new InvalidOperationException("GenerateFirstMessage must be called first"); } if (message.sigmaC.Length != numberOfTokens) { throw new ArgumentException("invalid sigmaC array length"); } FieldZqElement[] sigmaR = new FieldZqElement[message.sigmaC.Length]; Group Gq = ikap.IssuerParameters.Gq; FieldZq Zq = ikap.IssuerParameters.Zq; for (int i = 0; i < message.sigmaC.Length; i++) { sigmaR[i] = message.sigmaC[i] * ikap.PrivateKey + w[i]; w[i] = Zq.Zero; } w = null; state = State.Third; return(new ThirdIssuanceMessage(sigmaR)); }
public void CSDLRepArrayTestWithGroup() { DLRepOfGroupElement[] input = StaticHelperClass.GenerateRandomDLRepOfGroupElementArray(10, 7, this.paramIndex); FieldZqElement[][] inputExponents = new FieldZqElement[10][]; for (int dlIndex = 0; dlIndex < 10; ++dlIndex) { inputExponents[dlIndex] = new FieldZqElement[7]; for (int exponentIndex = 0; exponentIndex < 7; ++exponentIndex) { inputExponents[dlIndex][exponentIndex] = input[dlIndex].ExponentAtIndex(exponentIndex); } } string[] serializedTT = CryptoSerializer.Serialize(input, true, true); DLRepOfGroupElement[] outputTT = CryptoSerializer.Deserialize <DLRepOfGroupElement>(serializedTT, null, null); StaticHelperClass.AssertArraysAreEqual(input, outputTT, "outputTT"); string[] serializedNT = CryptoSerializer.Serialize(input, true, false); GroupElement[] newBases = StaticHelperClass.GenerateRandomBases(input[0].RepresentationLength, this.paramIndex); DLRepOfGroupElement[] outputNT = CryptoSerializer.Deserialize <DLRepOfGroupElement>(serializedNT, null, newBases); Assert.AreEqual(input.Length, outputNT.Length, "outputNT.Length"); for (int i = 0; i < outputNT.Length; ++i) { DLRepOfGroupElement expected = new DLRepOfGroupElement(newBases, inputExponents[i], this.crypto.Group); expected.Value = input[i].Value; Assert.AreEqual(expected, outputNT[i], "outputNT " + i); } FieldZqElement[] commitments = StaticHelperClass.GenerateRandomExponents(10, this.paramIndex); FieldZqElement[] openings = StaticHelperClass.GenerateRandomExponents(10, this.paramIndex); input = PedersenCommitment.GetCommitments(this.crypto, commitments, openings); }
public void BDSerializationTest() { FieldZqElement bigNum = _parameters[0].FieldZq.GetElement(2056); PedersenCommitment bigNumCommit = new PedersenCommitment(bigNum, _parameters[0]); int decompositionLength = 15; ProverBitDecompositionParameters prover = new ProverBitDecompositionParameters( bigNumCommit, decompositionLength, _parameters[0]); BitDecompositionProof proof = new BitDecompositionProof(prover); Assert.IsTrue(proof.Verify(prover), "original proof verification."); string jsonProof = CryptoSerializer.Serialize <BitDecompositionProof>(proof); // TODO: switch to using ip-based de-serialization; need to harmonize with U-Prove SDK code IssuerParameters ip = new IssuerParameters(); ip.Gq = prover.Group; BitDecompositionProof deserializedProof = ip.Deserialize <BitDecompositionProof>(jsonProof);// CryptoSerializer.Deserialize<BitDecompositionProof>(jsonProof); Assert.IsTrue(deserializedProof.Verify(prover), "deserialized proof verfication"); string jsonProver = CryptoSerializer.Serialize <ProverBitDecompositionParameters>(prover); ProverBitDecompositionParameters deserializedProver = CryptoSerializer.Deserialize <ProverBitDecompositionParameters>(jsonProver); Assert.IsTrue(deserializedProof.Verify(deserializedProver), "deserialized proof with deserialized prover."); BitDecompositionProof proof2 = new BitDecompositionProof(deserializedProver); Assert.IsTrue(proof2.Verify(deserializedProver), "proof2.verify(deserializedProver)"); Assert.IsTrue(proof2.Verify(prover), "Proof2.verify(prover)"); }
public void BDBadProofTest() { FieldZqElement bigNum = _parameters[0].FieldZq.GetElement(30); PedersenCommitment bigNumCommit = new PedersenCommitment(bigNum, _parameters[0]); int decompositionLength = 8; ProverBitDecompositionParameters proverParams = new ProverBitDecompositionParameters( bigNumCommit, decompositionLength, _parameters[0]); BitDecompositionProof proof = new BitDecompositionProof(proverParams); PrivateObject proofAccessor = new PrivateObject(proof); SetMembershipProof[] smProof = (SetMembershipProof[])proofAccessor.GetField("bitCommitmentProof"); SetMembershipProof[] badSmProof = smProof; SetMembershipProof tmp = smProof[1]; badSmProof[1] = badSmProof[0]; proofAccessor.SetFieldOrProperty("bitCommitmentProof", badSmProof); Assert.IsFalse(proof.Verify(proverParams), "bad set membeship proof."); proofAccessor.SetFieldOrProperty("bitCommitmentProof", smProof); smProof[1] = tmp; Assert.IsTrue(proof.Verify(proverParams), "good set membership proof."); EqualityProof eqProof = (EqualityProof)proofAccessor.GetField("compositionProof"); PrivateObject eqProofAccessor = new PrivateObject(eqProof); GroupElement [] b = (GroupElement[])eqProofAccessor.GetField("b"); b[1] = b[0]; eqProofAccessor.SetField("b", b); Assert.IsFalse(proof.Verify(proverParams), "bad equality proof"); }
/// <summary> /// Generates the second issuance message. /// </summary> /// <param name="message">The first issuance message.</param> /// <returns>The second issuance message.</returns> public SecondIssuanceMessage GenerateSecondMessage(FirstIssuanceMessage message) { if (state != State.Initialized) { throw new InvalidOperationException("Prover not initialized properly"); } Group Gq = ip.Gq; this.sigmaZ = message.sigmaZ; sigmaZPrime = new GroupElement[numberOfTokens]; sigmaAPrime = new GroupElement[numberOfTokens]; sigmaBPrime = new GroupElement[numberOfTokens]; sigmaCPrime = new FieldZqElement[numberOfTokens]; FieldZqElement[] sigmaC = new FieldZqElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { FieldZqElement blindingExponent = alpha[i]; sigmaZPrime[i] = message.sigmaZ.Exponentiate(blindingExponent); sigmaAPrime[i] = t1[i] * message.sigmaA[i]; sigmaBPrime[i] = sigmaZPrime[i].Exponentiate(beta1[i]) * t2[i] * message.sigmaB[i].Exponentiate(blindingExponent); HashFunction hash = ip.HashFunction; hash.Hash(h[i]); hash.Hash(PI); hash.Hash(sigmaZPrime[i]); hash.Hash(sigmaAPrime[i]); hash.Hash(sigmaBPrime[i]); sigmaCPrime[i] = ip.Zq.GetElementFromDigest(hash.Digest); sigmaC[i] = sigmaCPrime[i] + beta1[i]; } state = State.Second; return(new SecondIssuanceMessage(sigmaC)); }
/// <summary> /// Get the issuance state after the second message generation. /// </summary> /// <returns>The issuance state after the second message generation.</returns> public PostSecondMessageState ExportPostSecondMessageState() { if (state != State.Second) { throw new InvalidOperationException("GenerateSeondMessage must be called first"); } PostSecondMessageState psms = new PostSecondMessageState(); psms.TI = TI; psms.PI = PI; FieldZqElement[] alphaInverse = new FieldZqElement[numberOfTokens]; for (int i = 0; i < numberOfTokens; i++) { alphaInverse[i] = ukat[i].PrivateKey; } psms.AlphaInverse = alphaInverse; psms.Beta2 = beta2; psms.H = h; psms.SigmaZPrime = sigmaZPrime; psms.SigmaAPrime = sigmaAPrime; psms.SigmaBPrime = sigmaBPrime; psms.SigmaCPrime = sigmaCPrime; psms.IsDeviceProtected = isDeviceProtected; // we update the state so this object cannot be used by mistake to complete the issuance // (we don't want the same randomizers to be used twice on two issuer-provided messages) state = State.Tokens; return(psms); }
/// <summary> /// Constructs a non-revocation proof instance. /// </summary> /// <param name="cPrime">The <c>c'</c> value.</param> /// <param name="s">The <c>s</c> value.</param> /// <param name="X">The <c>X</c> value.</param> /// <param name="Y">The <c>Y</c> value.</param> /// <param name="Cd">The <c>Cd</c> value.</param> public NonRevocationProof(FieldZqElement cPrime, FieldZqElement[] s, GroupElement X, GroupElement Y, GroupElement Cd) { if (cPrime == null) { throw new ArgumentNullException("cPrime"); } this.cPrime = cPrime; if (s == null || s.Length != 6) { throw new ArgumentException("s"); } this.s = s; if (X == null) { throw new ArgumentNullException("X"); } this.X = X; if (Y == null) { throw new ArgumentNullException("Y"); } this.Y = Y; if (Cd == null) { throw new ArgumentNullException("Cd"); } this.Cd = Cd; }
/// <summary> /// Helper method for constructing proof. Computes a[index], c[index], r[index] values for when /// the committedValue is not equal to prover.MemberSet[index]. /// </summary> /// <param name="index">Index into prover.MemberSet</param> /// <param name="prover">Prover parameters</param> /// <param name="randomChallengeValue">Value to set c[index]</param> /// <param name="randomResponseValue">Value to set r[index]</param> private void generateFakeProof(int index, ProverSetMembershipParameters prover, FieldZqElement randomChallengeValue, FieldZqElement randomResponseValue) { if (index < this.c.Length) { this.c[index] = randomChallengeValue; } this.r[index] = randomResponseValue; // compute this.a[index] as a multi-exponentiation // a[index] = h^r[index] * g^{memberset[index] + c[index]} * X^{-c[index] GroupElement[] bases = new GroupElement[3] { prover.H, // h prover.G, // g prover.ClosedCommitment // X }; FieldZqElement[] exponents = new FieldZqElement[3] { randomResponseValue, // r[index] prover.MemberSet[index] * randomChallengeValue, // memberset[index] * c randomChallengeValue.Negate() // -c }; this.a[index] = prover.Group.MultiExponentiate(bases, exponents); }
/// <summary> /// Constructs a new <code>IDEscrowProofGenerationRandomData</code> instance. /// </summary> /// <param name="r">The <code>r</code> value.</param> /// <param name="xbPrime">The <code>xbPrime</code> values.</param> /// <param name="rPrime">The <code>rPrime</code> value.</param> /// <param name="obPrime">The <code>obPrime</code> value.</param> public IDEscrowProofGenerationRandomData(FieldZqElement r, FieldZqElement xbPrime, FieldZqElement rPrime, FieldZqElement obPrime) { this.r = r; this.xbPrime = xbPrime; this.rPrime = rPrime; this.obPrime = obPrime; }
public void InequalityParamUnknownValueTest() { CryptoParameters crypto = StaticHelperClass.ParameterArray[1]; FieldZqElement x = crypto.FieldZq.GetRandomElement(false); FieldZqElement y = x + crypto.FieldZq.One; // inequality does not hold PedersenCommitment X = new PedersenCommitment(x, crypto); PedersenCommitment Y = new PedersenCommitment(y, crypto); PedersenCommitment badY = new PedersenCommitment(x, crypto); ProverInequalityProofParameters badProver = new ProverInequalityProofParameters(X, badY, crypto); Assert.IsFalse(badProver.Verify(), "x=y"); // X uses wrong bases PedersenCommitment badX = new PedersenCommitment(crypto.H, crypto.G, x, x, crypto.Group); badProver = new ProverInequalityProofParameters(badX, Y, crypto); Assert.IsFalse(badProver.Verify(), "bad bases in X"); // Y uses wrong bases badProver = new ProverInequalityProofParameters(Y, badX, crypto); Assert.IsFalse(badProver.Verify(), "bad bases in Y"); //good parameters ok ProverInequalityProofParameters prover = new ProverInequalityProofParameters(X, Y, crypto); Assert.IsTrue(prover.Verify(), "prover verify"); VerifierInequalityProofParameters verifier = new VerifierInequalityProofParameters(X.Value, Y.Value, crypto); Assert.IsTrue(verifier.Verify(), "verifier ok."); }
/// <summary> /// Verifies a U-Prove token signature. /// </summary> /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param> /// <param name="upt">The U-Prove token to verify.</param> /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception> public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt) { Group Gq = ip.Gq; FieldZq Zq = ip.Zq; if (upt.H == Gq.Identity) { throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)"); } GroupElement[] bases = new GroupElement[2]; FieldZqElement[] exponents = new FieldZqElement[2]; HashFunction hash = ip.HashFunction; hash.Hash(upt.H); hash.Hash(upt.PI); hash.Hash(upt.SigmaZPrime); bases[0] = Gq.G; exponents[0] = upt.SigmaRPrime; bases[1] = ip.G[0]; exponents[1] = upt.SigmaCPrime.Negate(); hash.Hash(Gq.MultiExponentiate(bases, exponents)); bases[0] = upt.H; exponents[0] = upt.SigmaRPrime; bases[1] = upt.SigmaZPrime; exponents[1] = upt.SigmaCPrime.Negate(); hash.Hash(Gq.MultiExponentiate(bases, exponents)); if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid U-Prove token signature"); } }
/// <summary> /// Verifies that the given (commitment, challenge, response) values are a /// valid proof for this object. See IOpenEquation for how commitment and response are generated. /// </summary> /// <param name="challenge">The challenge for this proof (second step in Sigma protocol).</param> /// <param name="responseValues">The response (third step in Sigma protocol).</param> /// <param name="commitment">The commitment (first step in Sigma protocol).</param> /// <returns></returns> public override bool Verify(GroupElement commitment, FieldZqElement challenge, FieldZqElement[] response) { if ((response == null) || (response.Length != this.RepresentationLength)) { return(false); } GroupElement[] bases = new GroupElement[this.RepresentationLength + 1]; FieldZqElement[] exponents = new FieldZqElement[this.RepresentationLength + 1]; for (int i = 0; i < response.Length; ++i) { bases[i] = this.BaseAtIndex(i); exponents[i] = response[i]; } exponents[0] = challenge.Negate(); bases[this.RepresentationLength] = this.PublicKey; exponents[this.RepresentationLength] = response[0]; GroupElement verifier = this.Group.MultiExponentiate(bases, exponents); if (commitment != verifier) { return(false); } return(true); }
/// <summary> /// Add the value to this value and return the result. /// </summary> /// <param name="e">The value to add to this value.</param> /// <returns>This value plus e.</returns> public override FieldZqElement Add(FieldZqElement e) { return new FieldZqElementBCImpl(i.Add((e as FieldZqElementBCImpl).i) % field.modulus, field); }
/// <summary> /// Returns true if the given element is an element from this field. /// </summary> /// <param name="element">The element to check.</param> /// <returns>True if the given element is an element from this field.</returns> public override bool IsElement(FieldZqElement element) { FieldZqElementBCImpl xdImpl = element as FieldZqElementBCImpl; if (xdImpl == null) { throw new ArgumentNullException(); } if (((xdImpl.field) as FieldZqBCImpl).modulus != modulus) { return false; } if (xdImpl.i < BCBigInt.Zero || xdImpl.i >= this.modulus) { return false; } return true; }
/// <summary> /// Returns <code>this^exponent</code>. /// </summary> /// <param name="exponent">The exponent.</param> /// <returns>A group element.</returns> public override GroupElement Exponentiate(FieldZqElement exponent) { return new ECGroupElementBCImpl( Point.Multiply( (exponent as FieldZqElementBCImpl).i) as FpPoint ); }
/// <summary> /// Multiply this element by the element e. /// </summary> /// <param name="e">The value to multiply this value by.</param> /// <returns>The value of this * e.</returns> public override FieldZqElement Multiply(FieldZqElement e) { return new FieldZqElementBCImpl(i.Multiply((e as FieldZqElementBCImpl).i) % field.modulus, field); }
/// <summary> /// Bouncy castle implementation of multi-exponentiation. /// </summary> /// <param name="g">bases</param> /// <param name="f">exponents</param> /// <returns></returns> public override GroupElement MultiExponentiate(GroupElement[] g, FieldZqElement[] f) { if (g == null || f == null || g.Length != f.Length) { throw new ArgumentException("g and f must be non-null and of the same length"); } GroupElement value = Identity; for (int i = 0; i < g.Length; i++) { value *= g[i].Exponentiate(f[i]); } return value; }
/// <summary> /// Exponentiate this value to the exponent power. /// </summary> /// <param name="exponent">The exponent to raise this value to.</param> /// <returns>This value to the exponent power.</returns> public override FieldZqElement ModPow(FieldZqElement exponent) { return new FieldZqElementBCImpl(i.ModPow((exponent as FieldZqElementBCImpl).i, field.modulus), field); }
public override GroupElement Exponentiate(FieldZqElement exponent) { return new SubgroupGroupElementBCImpl(i.ModPow(((FieldZqElementBCImpl)exponent).i, p), p); }