/// <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); }
/// <summary> /// Returns an array of Zero and One FieldZqElements, in Small Endian notation. /// So sum result[i] * 2^i = integer. If decompositionLength is too short, /// returns the minimum length array with the correct decomposition. /// </summary> /// <param name="integer">Integer to decompose</param> /// <param name="decompositionLength">Minimum number of bits.</param> /// <param name="fieldZq">Field</param> /// <returns></returns> public static BitArray GetBitDecomposition(FieldZqElement integer, int decompositionLength, FieldZq fieldZq) { // get bit array BitArray bits = new BitArray(VerifierBitDecompositionParameters.Reverse(integer.ToByteArray())); // compute minimum decompositionLength if ((decompositionLength < IndexOfMostSignificantNonZeroBit(bits) + 1)) { decompositionLength = IndexOfMostSignificantNonZeroBit(bits) + 1; } // translate bits into array of FieldZqElements BitArray bitDecomposition = new BitArray(decompositionLength); for (int bitIndex = 0; bitIndex < bitDecomposition.Length; ++bitIndex) { if ((bitIndex < bits.Length) && bits.Get(bitIndex)) { bitDecomposition.Set(bitIndex, true); } else { bitDecomposition.Set(bitIndex, false); } } return(bitDecomposition); }
/// <summary> /// Gets verifier parameters corresponding to this object. /// </summary> /// <returns></returns> public VerifierBitDecompositionParameters GetVerifierParameters() { VerifierBitDecompositionParameters verifierParams = new VerifierBitDecompositionParameters( this.ClosedCommitment, this.ClosedBitDecomposition(), this); return(verifierParams); }
/// <summary> /// Checks that this bit decomposition proof is valid with respect to /// the given verifier parameters. /// </summary> /// <param name="verifier">Verifier parameters.</param> /// <returns>True if this proof is valid, false otherwise.</returns> public bool Verify(VerifierBitDecompositionParameters verifier) { try { // check verifier parameters if (!verifier.Verify()) { return(false); } // check each set membership proof VerifierSetMembershipParameters smParameters = new VerifierSetMembershipParameters(verifier); FieldZqElement[] memberSet = SetOfZeroAndOne(verifier); for (int committedBitIndex = 0; committedBitIndex < this.bitCommitmentProof.Length; ++committedBitIndex) { GroupElement committedBit = verifier.ClosedBitDecomposition(committedBitIndex); smParameters.setVerifierParameters(committedBit, memberSet); if (!this.bitCommitmentProof[committedBitIndex].Verify(smParameters)) { return(false); } } // check the composition proof GroupElement actualComposedValue = ComposeClosedCommittedBits(verifier.ClosedBitDecomposition(), verifier); GroupElement[] bases = new GroupElement[2] { verifier.G, verifier.H }; VerifierEqualityParameters veParameters = new VerifierEqualityParameters( new ClosedDLRepOfGroupElement(bases, actualComposedValue, verifier.Group), 0, new ClosedDLRepOfGroupElement(bases, verifier.ClosedCommitment, verifier.Group), 0, verifier); if (!this.compositionProof.Verify(veParameters)) { return(false); } return(true); } catch (Exception) { return(false); } }
/// <summary> /// Constructs a bit decomposition of openCommitment.CommittedValue and /// generates the appropriate ProverBitDecompositionParameters. /// If decompositionLength is too short, automatically chooses /// minimum required length. /// </summary> /// <param name="openCommitment">Pedersen Commitment to some value</param> /// <param name="decompositionLength">Number of bits in bit-decomposition.</param> /// <param name="parameterSet">Parameter set</param> /// <returns></returns> public ProverBitDecompositionParameters( PedersenCommitment openCommitment, int decompositionLength, CryptoParameters crypto) : base(crypto) { BitArray bits = VerifierBitDecompositionParameters.GetBitDecomposition(openCommitment.CommittedValue, decompositionLength, this.FieldZq); PedersenCommitment [] openBitDecomposition = new PedersenCommitment[bits.Length]; for (int bitIndex = 0; bitIndex < bits.Length; ++bitIndex) { if (bits.Get(bitIndex)) { openBitDecomposition[bitIndex] = new PedersenCommitment(crypto.FieldZq.One, crypto); } else { openBitDecomposition[bitIndex] = new PedersenCommitment(crypto.FieldZq.Zero, crypto); } } this.setProverParameters(openBitDecomposition, openCommitment); }
/// <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 GroupElement[] DefaultClosedDecompositionOfIntegerB(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); GroupElement[] defaultBitDecomposition = new GroupElement[bitsB.Length]; for (int i = 0; i < defaultBitDecomposition.Length; ++i) { if (bitsB.Get(i)) { defaultBitDecomposition[i] = verifier.G; } else { defaultBitDecomposition[i] = verifier.Group.Identity; } } return(defaultBitDecomposition); }
/// <summary> /// Verifies that A is a valid bit decomposition of verifier.ClosedIntegerA and /// B is a valid bit decomposition of verifier.ClosedIntegerB. /// </summary> /// <param name="verifier"></param> /// <param name="A">Bit decomposition of A.</param> /// <param name="B">Bit decomposition of B.</param> /// <param name="proofA">Proof that A is a valid bit decomposition of verifier.ClosedIntegerA.</param> /// <param name="proofB">Proof that B is a valid bit decomposition of verifier.ClosedIntegerB.</param> /// <returns></returns> private static bool VerifyBitDecompositionProofs(VerifierRangeProofParameters verifier, GroupElement [] A, GroupElement [] B, BitDecompositionProof proofA, BitDecompositionProof proofB) { // verify A VerifierBitDecompositionParameters bitVerifierA = new VerifierBitDecompositionParameters(verifier.RangeNormalizedClosedIntegerA, A, verifier); if (!proofA.Verify(bitVerifierA)) { return(false); } // verify B if ((verifier.IntegerBIsKnown) && (B == null) && (proofB == null)) { return(true); } VerifierBitDecompositionParameters bitVerifierB = new VerifierBitDecompositionParameters(verifier.RangeNormalizedClosedIntegerB, B, verifier); if (!proofB.Verify(bitVerifierB)) { return(false); } return(true); }
/// <summary> /// Constructor. Takes as input an integer, creates a Pedersen Commitment to it, and generates /// a sequence of Pedersen Commitments to its bit decomposition. /// </summary> /// <param name="integer">Creates a Pedersen Commitment to this value.</param> /// <param name="decompositionLength">Minimum number of integers in the decomposition.</param> /// <param name="crypto">Cryptographic parameters.</param> /// <param name="hideCommittedValue">Decomposed integer is secret.</param> public ProverBitDecompositionParameters(FieldZqElement integer, int decompositionLength, CryptoParameters crypto, bool hideCommittedValue = true) : base(crypto) { BitArray bits = VerifierBitDecompositionParameters.GetBitDecomposition(integer, decompositionLength, this.FieldZq); PedersenCommitment[] openCommittedBits = new PedersenCommitment[bits.Length]; PedersenCommitment openCommitment; if (hideCommittedValue) { for (int i = 0; i < bits.Length; ++i) { FieldZqElement curBit = this.FieldZq.Zero; if (bits.Get(i)) { curBit = this.FieldZq.One; } openCommittedBits[i] = new PedersenCommitment(curBit, this); } openCommitment = new PedersenCommitment(integer, this); } else { for (int i = 0; i < bits.Length; ++i) { FieldZqElement curBit = this.FieldZq.Zero; if (bits.Get(i)) { curBit = this.FieldZq.One; } openCommittedBits[i] = new PedersenCommitment(this.G, this.H, curBit, this.FieldZq.Zero, this.Group); } openCommitment = new PedersenCommitment(this.G, this.H, integer, this.FieldZq.Zero, this.Group); } this.setProverParameters(openCommittedBits, openCommitment); }
/// <summary> /// Sets verifier parameters for situations when the committed value is known /// to the verifier. Computes the bit decomposition for committedValue /// ClosedCommittment = G^committedValue /// ClosedCommittedBit[i] = G^bit[i] /// </summary> /// <param name="committedValue">Committed value.</param> /// <param name="decompositionLength">Minimum bit decomposition length.</param> public void setVerifierParameters(FieldZqElement committedValue, int decompositionLength) { if (committedValue == null) { base.setVerifierParameters(null); return; } BitArray commitedBits = VerifierBitDecompositionParameters.GetBitDecomposition(committedValue, decompositionLength, this.FieldZq); GroupElement[] publicValues = new GroupElement[commitedBits.Length + 1]; for (int i = 0; i < commitedBits.Length; ++i) { if (!commitedBits.Get(i)) { publicValues[i] = this.Group.Identity; } else { publicValues[i] = this.G; } } publicValues[publicValues.Length - 1] = this.G.Exponentiate(committedValue); this.setVerifierParameters(publicValues); }
/// <summary> /// Verifies that the ProverRangeProofParameters are valid. /// </summary> /// <returns>True if parameters are valid.</returns> new public bool Verify() { if (!base.Verify()) { return(false); } // check that they're in range BitArray maxValueBits = VerifierBitDecompositionParameters.GetBitDecomposition(this.GetRangeNormalizedFieldZqElement(this.MaxValue), 0, this.FieldZq); int decompositionLength = maxValueBits.Length; BitArray minValueBits = VerifierBitDecompositionParameters.GetBitDecomposition(this.GetRangeNormalizedFieldZqElement(this.MinValue), decompositionLength, this.FieldZq); // check integer A and integer B exist if (this.OpenIntegerA == null) { return(false); } BitArray bitA = VerifierBitDecompositionParameters.GetBitDecomposition(this.RangeNormalizedOpenIntegerA.ExponentAtIndex(0), decompositionLength, this.FieldZq); BitArray bitB; if (this.IntegerBIsKnown) { bitB = VerifierBitDecompositionParameters.GetBitDecomposition(this.GetRangeNormalizedFieldZqElement(this.IntegerB), decompositionLength, this.FieldZq); } else { if (this.OpenIntegerB == null) { return(false); } bitB = VerifierBitDecompositionParameters.GetBitDecomposition(this.RangeNormalizedOpenIntegerB.ExponentAtIndex(0), decompositionLength, this.FieldZq); } // make sure integerA and integerB are in range. if ((Compare(bitA, minValueBits) < 0) || (Compare(bitA, maxValueBits) > 0) || (Compare(bitB, minValueBits) < 0) || (Compare(bitB, maxValueBits) > 0)) { return(false); } // now compare integerA and integerB based on range proof type. switch (this.RangeProofType) { case VerifierRangeProofParameters.ProofType.GREATER_THAN: if (Compare(bitA, bitB) <= 0) { return(false); } break; case VerifierRangeProofParameters.ProofType.GREATER_THAN_OR_EQUAL_TO: if (Compare(bitA, bitB) < 0) { return(false); } break; case VerifierRangeProofParameters.ProofType.LESS_THAN: if (Compare(bitA, bitB) >= 0) { return(false); } break; case VerifierRangeProofParameters.ProofType.LESS_THAN_OR_EQUAL_TO: if (Compare(bitA, bitB) > 0) { return(false); } break; } return(true); }