/// <summary> /// Combines the input arrays into a master array of DL representation equations to use /// for FullRangeProof. Arrays should all be not null and of equal length. /// </summary> /// <param name="openD">openD[length-1] is excluded.</param> /// <param name="AdivB">AdivB[0] is excluded.</param> /// <param name="openX">openX[0] is excluded.</param> /// <param name="openE">openE[0] is excluded. </param> /// <returns>Concatentation of all arrays, minus excluded values.</returns> public static DLRepOfGroupElement[] CombineAllOpenDLReps(DLRepOfGroupElement [] openD, DLRepOfGroupElement[] AdivB, DLRepOfGroupElement[] openX, DLRepOfGroupElement[] openE) { DLRepOfGroupElement[] openDL = new DLRepOfGroupElement[openD.Length - 1 + AdivB.Length - 1 + openX.Length - 1 + openE.Length - 1]; int openDLIndex = 0; for (int i = 0; i < openD.Length - 1; ++i) { openDL[openDLIndex] = openD[i]; ++openDLIndex; } for (int i = 1; i < AdivB.Length; ++i) { openDL[openDLIndex] = AdivB[i]; ++openDLIndex; } for (int i = 1; i < openX.Length; ++i) { openDL[openDLIndex] = openX[i]; ++openDLIndex; } for (int i = 1; i < openE.Length; ++i) { openDL[openDLIndex] = openE[i]; ++openDLIndex; } return(openDL); }
/// <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 PedersenCommitment(DLRepOfGroupElement dl) { if ((dl == null) || (dl.RepresentationLength != 2)) { throw new ArgumentException("Cannot convert input into Pedersen Commitment"); } GroupElement [] bases = new GroupElement[2] { dl.BaseAtIndex(0), dl.BaseAtIndex(1) }; FieldZqElement[] exponents = new FieldZqElement[] { dl.ExponentAtIndex(0), dl.ExponentAtIndex(1) }; this.Group = dl.Group; this.ComputeValue(bases, exponents); }
/// <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> /// Genererates proof for when prover.CompareToKnownValue=true. /// </summary> /// <param name="prover"></param> private void CreateProofForKnownValue(ProverInequalityProofParameters prover) { // Pedersen Commitment to a random value a // A = g^a h^r FieldZqElement a = prover.FieldZq.GetRandomElement(true); FieldZqElement r = prover.FieldZq.GetRandomElement(true); PedersenCommitment openA = new PedersenCommitment(prover.G, prover.H, a, r, prover.Group); // B = g^(x-value)a DLRepOfGroupElement openB = new DLRepOfGroupElement( new GroupElement[1] { prover.G }, new FieldZqElement[1] { (prover.CommitmentX.CommittedValue - prover.Value) * a }, prover.Group ); // C = (Xg^{-value})^a h^{-ya} = B PedersenCommitment openC = new PedersenCommitment( prover.CommitmentX.Value * prover.G.Exponentiate(prover.Value.Negate()), prover.H, a, a.Negate() * prover.CommitmentX.Opening, prover.Group ); // Create DL equations DLRepOfGroupElement[] equations = new DLRepOfGroupElement[] { prover.CommitmentX, openA, openB, openC }; // generate proof EqualityMap map = this.GetEqualityMap(); ProverEqualityParameters eqProver = new ProverEqualityParameters(equations, map, prover); this.Proof = new EqualityProof(eqProver); this.A = openA.Value; this.B = openB.Value; }
/// <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> /// 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> /// Multiplies all objects in dlarray. Adds all the exponents and multiplies the values. /// Fails if objects in dlarray don't have the same bases in the same order. /// </summary> /// <param name="dlarray"></param> /// <param name="product"></param> /// <returns></returns> public static bool TryStrictMultiply(DLRepOfGroupElement [] dlarray, out DLRepOfGroupElement product) { product = null; // make sure there is at least one element in the array if ((dlarray == null) || (dlarray.Length < 1)) { return(false); } // compare bases for (int i = 1; i < dlarray.Length; ++i) { if (!dlarray[0].AreBasesEqual(dlarray[i])) { return(false); } } GroupElement [] newBases = new GroupElement[dlarray[0].RepresentationLength]; FieldZqElement [] newExponents = new FieldZqElement[dlarray[0].RepresentationLength]; for (int baseIndex = 0; baseIndex < dlarray[0].RepresentationLength; ++baseIndex) { newBases[baseIndex] = dlarray[0].BaseAtIndex(baseIndex); newExponents[baseIndex] = dlarray[0].ExponentAtIndex(baseIndex); for (int dlIndex = 1; dlIndex < dlarray.Length; ++dlIndex) { newExponents[baseIndex] += dlarray[dlIndex].ExponentAtIndex(baseIndex); } } product = new DLRepOfGroupElement(newBases, newExponents, dlarray[0].Group); return(true); }
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); } }