/// <summary> /// Creates a range proof that compares a UProve attribute to a target date. /// Target attribute MUST NOT be hashed. /// Value MUST be generated via RangeProofParameterFactory.EncodeYearAndDayAsUProveAttribute. /// </summary> /// <param name="prover">Token information.</param> /// <param name="attributeIndexForProver">1-based index of target attribute.</param> /// <param name="proofType">Range proof type</param> /// <param name="targetDate">Compare token attribute to this date. (Time component is ignored).</param> /// <param name="minYear">Minimum year for attribute and target date.</param> /// <param name="maxYear">Maximum year for attribute and target date.</param> public RangeProof( ProverPresentationProtocolParameters prover1, int attributeIndexForProver1, VerifierRangeProofParameters.ProofType proofType, ProverPresentationProtocolParameters prover2, int attributeIndexForProver2, int minValue, int maxValue) { // make sure target attribute is not hashed if ((prover1.IP.E[attributeIndexForProver1 - 1] == 0x01) || ((prover2.IP.E[attributeIndexForProver2 - 1]) == 0x01)) { throw new ArgumentException("UProve attributes used in Range Proof must not be hashed."); } // generate Pedersen Commitments to token attributes ProverPresentationProtocolParameters[] provers = new ProverPresentationProtocolParameters[] { prover1, prover2 }; int[] attributeIndices = new int[] { attributeIndexForProver1, attributeIndexForProver2 }; PedersenCommitment[] attributeCommitments = PedersenCommitment.PedersenCommmitmentsToAttributes(provers, attributeIndices); // create range proof ProverRangeProofParameters rangeProver = new ProverRangeProofParameters( new CryptoParameters(prover1.IP), attributeCommitments[0], proofType, attributeCommitments[1], minValue, maxValue); ConstructorHelper(rangeProver); // Add UProve Integration proof this.UPIProof = new UProveIntegrationProof(provers, attributeIndices, attributeCommitments); this.UPIProof.IsGroupSerializable = false; }
/// <summary> /// Returns array of DLRepOfGroupElement objects, where output[i] = openA[i] / openB[i]. /// Input arrays should be not null and of equal lengths. /// </summary> /// <param name="prover">Used to get bases G and H.</param> /// <param name="openA">Each openA[i] should have RepresentationLength=2, with bases equal to prover.G and prover.H</param> /// <param name="openB">Each openB[i] should have RepresentationLength=2, with bases equal to prover.G and prover.H</param> /// <returns></returns> public static DLRepOfGroupElement[] ComputeOpenAdivB(ProverRangeProofParameters prover, DLRepOfGroupElement [] openA, DLRepOfGroupElement [] openB) { DLRepOfGroupElement[] AdivB = new DLRepOfGroupElement[openA.Length]; for (int i = 0; i < AdivB.Length; ++i) { AdivB[i] = new PedersenCommitment( prover.G, prover.H, openA[i].ExponentAtIndex(0) - openB[i].ExponentAtIndex(0), openA[i].ExponentAtIndex(1) - openB[i].ExponentAtIndex(1), prover.Group); } return(AdivB); }
/// <summary> /// Computes commitment to (a-b)^2. /// Let openAdivB[i] be a commitment to (a[i]-b[i]). This method chooses /// random u[i] and returns: /// output[i] = (openAdivB[i].Value)^(a[i]-b[i]) * prover.H^u[i] /// </summary> /// <param name="prover">Range proof parameters</param> /// <param name="openAdivB">Commitment to A/B</param> /// <returns>Array of same length as openAdivB, first element is null.</returns> public static DLRepOfGroupElement[] ComputeOpenX(ProverRangeProofParameters prover, DLRepOfGroupElement[] openAdivB) { FieldZqElement[] u = prover.FieldZq.GetRandomElements(openAdivB.Length, true); DLRepOfGroupElement[] openX = new DLRepOfGroupElement[openAdivB.Length]; openX[0] = null; for (int i = 1; i < openX.Length; ++i) { openX[i] = new PedersenCommitment( openAdivB[i].Value, prover.H, openAdivB[i].ExponentAtIndex(0), u[i], prover.Group); } return(openX); }
/// <summary> /// Computes an array of commitments to d=Compute_d(prover,AdivB). /// </summary> /// <param name="prover">Used for bases G, H.</param> /// <param name="AdivB">Used to compute committed values d.</param> /// <returns>Array of same length as AdivB.</returns> public static DLRepOfGroupElement[] ComputeOpenD(ProverRangeProofParameters prover, DLRepOfGroupElement [] AdivB) { FieldZqElement[] d = Compute_d(prover, AdivB); DLRepOfGroupElement[] D = new DLRepOfGroupElement[d.Length]; FieldZqElement[] t = prover.FieldZq.GetRandomElements(d.Length, true); D[0] = AdivB[0]; for (int i = 1; i < D.Length; ++i) { D[i] = new PedersenCommitment( prover.G, prover.H, d[i], t[i], prover.Group); } return(D); }
/// <summary> /// Let a[i] be the committed bits in openAdivB, /// /// Computes the arrray d as follows: /// d[0] = a[0] /// d[i] = d[i-1] - d[i-1]*a[i]^2 + a[i] /// </summary> /// <param name="prover">Prover parameters</param> /// <returns>The array d</returns> private static FieldZqElement[] Compute_d(ProverRangeProofParameters prover, DLRepOfGroupElement [] openAdivB) { FieldZqElement[] d = new FieldZqElement[openAdivB.Length]; for (int i = 0; i < d.Length; ++i) { FieldZqElement difference = openAdivB[i].ExponentAtIndex(0); if (i == 0) { d[0] = difference; } else { d[i] = d[i - 1] + (d[i - 1].Negate() * difference * difference) + difference; } } return(d); }
/// <summary> /// Creates a DL representation equation E[i]. /// Let d[i] be the committed value in D[i]. /// Let E[i].Value = D[i]/D[i-1] * AdivB[i]^{-1}. /// Computes nu[i] so that the following relation holds /// E[i].Value= (X[i]^{-1})^{d[i-1]} * prover.H^{nu[i]}. /// </summary> /// <param name="prover"></param> /// <param name="D">Commitments to d</param> /// <param name="X">Commitment to (a-b)^2</param> /// <param name="AdivB">A/B</param> /// <returns>Array of same length as D, first element is null.</returns> public static DLRepOfGroupElement[] ComputeOpenE(ProverRangeProofParameters prover, DLRepOfGroupElement[] D, DLRepOfGroupElement [] X, DLRepOfGroupElement [] AdivB) { DLRepOfGroupElement[] E = new DLRepOfGroupElement[D.Length]; E[0] = null; for (int i = 1; i < E.Length; ++i) { FieldZqElement nu = D[i].ExponentAtIndex(1) // t[i] - D[i - 1].ExponentAtIndex(1) // - t[i-1] - AdivB[i].ExponentAtIndex(1) // - r[i] + (D[i - 1].ExponentAtIndex(0) // + (d[i-1] * r[i] * adivb[i]) * AdivB[i].ExponentAtIndex(1) * AdivB[i].ExponentAtIndex(0)) + (D[i - 1].ExponentAtIndex(0) // (d[i-1] * u[i]) * X[i].ExponentAtIndex(1)); E[i] = new PedersenCommitment( prover.Group.Invert(X[i].Value), prover.H, D[i - 1].ExponentAtIndex(0), nu, prover.Group); } return(E); }
/// <summary> /// Creates a bit decomposition of prover.OpenIntegerA and prover.OpenIntegerB, /// and proofs that they are valid. Sets member fields /// A, B, ProofBitDecompositionOfA and ProofBitDecompositionOfB. /// </summary> /// <param name="prover">Prover range proof parameters</param> /// <param name="bitProverA">outputs parameters for bit decomposition proof for A</param> /// <param name="bitProverB">outputs parameters for bit decomposition proof for B</param> /// <returns>Array AdivB with the bit decomposition of A divided by the bit decomposition of B.</returns> private DLRepOfGroupElement [] CreateBitDecompositionProofs(ProverRangeProofParameters prover) { int decompositionLength = RangeProof.ComputeDecompositionLength(prover); // create proof for A ProverBitDecompositionParameters bitProverA = new ProverBitDecompositionParameters(prover.RangeNormalizedOpenIntegerA, decompositionLength, prover); this.ProofBitDecompositionOfA = new BitDecompositionProof(bitProverA); this.A = bitProverA.ClosedBitDecomposition(); // create proof for B if it is unknown. ProverBitDecompositionParameters bitProverB = new ProverBitDecompositionParameters(prover.RangeNormalizedOpenIntegerB, decompositionLength, prover); if (prover.IntegerBIsKnown) { this.ProofBitDecompositionOfB = null; this.B = null; DLRepOfGroupElement[] defaultB = DefaultOpenDecompositionOfIntegerB(prover); return(ComputeOpenAdivB(prover, bitProverA.OpenBitDecomposition(), defaultB)); } this.ProofBitDecompositionOfB = new BitDecompositionProof(bitProverB); this.B = bitProverB.ClosedBitDecomposition(); return(ComputeOpenAdivB(prover, bitProverA.OpenBitDecomposition(), bitProverB.OpenBitDecomposition())); }
public void ConstructorHelper(ProverRangeProofParameters prover) { try { // verify prover parameters if (!prover.Verify()) { throw new ArgumentException("RangeProof: could not create RangeProof because prover parameters are invalid."); } // set group this.Group = prover.Group; this.IsGroupSerializable = true; // set up the bit decomposition proof and compute helper values DLRepOfGroupElement[] openAdivB = CreateBitDecompositionProofs(prover); if (this.ProofBitDecompositionOfA != null) { this.ProofBitDecompositionOfA.IsGroupSerializable = false; } if (this.ProofBitDecompositionOfB != null) { this.ProofBitDecompositionOfB.IsGroupSerializable = false; } DLRepOfGroupElement[] openD = ComputeOpenD(prover, openAdivB); DLRepOfGroupElement[] openX = ComputeOpenX(prover, openAdivB); DLRepOfGroupElement[] openE = ComputeOpenE(prover, openD, openX, openAdivB); // compute RangeProof DLRepOfGroupElement[] allOpenDL = CombineAllOpenDLReps(openD, openAdivB, openX, openE); EqualityMap map = ComputeEqualityMap(prover, A.Length); ProverEqualityParameters peParams = new ProverEqualityParameters( allOpenDL, map, prover); this.FullRangeProof = new EqualityProof(peParams); this.FullRangeProof.IsGroupSerializable = false; // set X and D this.SetX(openX); this.SetD(openD); // create additional proofs based on proof type PedersenCommitment LastD = (PedersenCommitment)openD[openD.Length - 1]; switch (prover.RangeProofType) { case VerifierRangeProofParameters.ProofType.GREATER_THAN: // Prove that D is a commitment to 1 case VerifierRangeProofParameters.ProofType.LESS_THAN: // Prove that D is a commitment to -1 DLRepOfGroupElement equation = new DLRepOfGroupElement( new GroupElement[1] { prover.H }, new FieldZqElement[1] { LastD.ExponentAtIndex(1) }, prover.Group); ProverEqualityParameters strictProver = new ProverEqualityParameters( equation, prover); this.StrictlyThanProof = new EqualityProof(strictProver); this.StrictlyThanProof.IsGroupSerializable = false; break; case VerifierRangeProofParameters.ProofType.GREATER_THAN_OR_EQUAL_TO: // Prove that D is a commitment to either 0 or 1 ProverSetMembershipParameters greaterEqualProver = new ProverSetMembershipParameters( LastD, new FieldZqElement[] { prover.FieldZq.Zero, prover.FieldZq.One }, prover); this.OrEqualToProof = new SetMembershipProof(greaterEqualProver); this.OrEqualToProof.IsGroupSerializable = false; break; case VerifierRangeProofParameters.ProofType.LESS_THAN_OR_EQUAL_TO: // Prove that D is a commitment to either 0 or -1 ProverSetMembershipParameters lessEqualProver = new ProverSetMembershipParameters( LastD, new FieldZqElement[] { prover.FieldZq.Zero, prover.FieldZq.One.Negate() }, prover); this.OrEqualToProof = new SetMembershipProof(lessEqualProver); this.OrEqualToProof.IsGroupSerializable = false; break; } } catch (Exception e) { throw new Exception("RangeProof: Could not create range proof.", e); } }
/// <summary> /// Creates a RangeProof given the parameters. Throws an ArgumentException on error. /// </summary> /// <param name="prover"></param> public RangeProof(ProverRangeProofParameters prover) { ConstructorHelper(prover); }