/// <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 the number of bits needed to represent the committed value in ClosedIntegerA /// and ClosedIntegerB. This is computed ceiling(log_2 MaxValue-MinValue) /// </summary> /// <param name="verifier"></param> /// <returns></returns> private static int ComputeDecompositionLength(VerifierRangeProofParameters verifier) { int range = verifier.MaxValue - verifier.MinValue; double exactBits = System.Math.Log(range, 2.0); return((int)System.Math.Ceiling(exactBits)); }
/// <summary> /// Returns array of ClosedDLRepOfGroupElement objects, where output[i] = A[i] / B[i]. /// If verifier.IntegerBIsKnown is true, replaces input B with default B. /// </summary> /// <param name="verifier">Used to get bases G and H. If verifier knows B, generates new array B.</param> /// <param name="A">Array of group elements.</param> /// <param name="B">Array of group elements of same length as A. May be null if verifier.IntegerBIsKnown is true.</param> /// <returns></returns> public static GroupElement[] ComputeClosedAdivB(VerifierRangeProofParameters verifier, GroupElement[] A, GroupElement[] B) { if (verifier.IntegerBIsKnown) { B = DefaultClosedDecompositionOfIntegerB(verifier); } GroupElement [] closedAdivB = new GroupElement[A.Length]; for (int i = 0; i < closedAdivB.Length; ++i) { closedAdivB[i] = verifier.Group.Divide(A[i], B[i]); } return(closedAdivB); }
/// <summary> /// Computes closed DL representation of E[i] = D[i]/D[i-1] * closedAdivB[i]^{-1}. /// Bases are X^{-1} and verifier.H. /// </summary> /// <param name="verifier">Verifier range proof parameters.</param> /// <param name="X">Array of commitments to (a-b)^2</param> /// <param name="D">Array of commitments to d.</param> /// <param name="closedAdivB">A/B</param> /// <returns>Array of same length as X, first element is null.</returns> public static ClosedDLRepOfGroupElement[] ComputeClosedE(VerifierRangeProofParameters verifier, GroupElement[] X, GroupElement[] D, GroupElement[] closedAdivB) { ClosedDLRepOfGroupElement[] closedE = new ClosedDLRepOfGroupElement[X.Length]; closedE[0] = null; for (int i = 1; i < closedE.Length; ++i) { closedE[i] = new ClosedDLRepOfGroupElement( new GroupElement[2] { verifier.Group.Invert(X[i]), verifier.H }, verifier.Group.Divide(new GroupElement[] { D[i] }, new GroupElement[] { D[i - 1], closedAdivB[i] }), verifier.Group); } return(closedE); }
/// <summary> /// Computes closed DL representation equations for X using /// bases closedAdivB[i] and verifier.H. /// </summary> /// <param name="verifier">Used to get base verifier.H</param> /// <param name="X">Array of group elements</param> /// <param name="closedAdivB">Used for base at index 0.</param> /// <returns>Array of same length as X, first element is null.</returns> public static ClosedDLRepOfGroupElement[] ComputeClosedX(VerifierRangeProofParameters verifier, GroupElement[] X, GroupElement [] closedAdivB) { ClosedDLRepOfGroupElement[] closedX = new ClosedDLRepOfGroupElement[X.Length]; closedX[0] = null; for (int i = 1; i < X.Length; ++i) { closedX[i] = new ClosedDLRepOfGroupElement( new GroupElement[2] { closedAdivB[i], verifier.H }, X[i], verifier.Group); } return(closedX); }
public bool Verify( VerifierPresentationProtocolParameters verifier1, int attributeIndexForVerifier1, VerifierRangeProofParameters.ProofType proofType, VerifierPresentationProtocolParameters verifier2, int attributeIndexForVerifier2, int minYear, int maxYear) { // Verify target attribute is not hashed if ((verifier1.IP.E[attributeIndexForVerifier1 - 1] == 0x01) || (verifier2.IP.E[attributeIndexForVerifier1 - 1] == 0x01)) { return(false); } // Verify UProve Integration Proof if (this.UPIProof == null) { return(false); } VerifierPresentationProtocolParameters[] verifiers = new VerifierPresentationProtocolParameters[2] { verifier1, verifier2 }; int[] attributeIndices = new int[2] { attributeIndexForVerifier1, attributeIndexForVerifier2 }; if (!this.UPIProof.Verify(verifiers, attributeIndices)) { return(false); } // Verify Range Proof VerifierRangeProofParameters rangeVerifier = new VerifierRangeProofParameters( new CryptoParameters(verifier1.IP), this.UPIProof.PedersenCommitmentValues[0], proofType, this.UPIProof.PedersenCommitmentValues[1], minYear, maxYear); return(this.Verify(rangeVerifier)); }
/// <summary> /// Computes the EqualityMap used by both the prover and verifier. /// </summary> /// <param name="verifier">Public parameters</param> /// <param name="decompositionLength">Number of bits used to represent integer A and integer B (e.g. A.Length)</param> /// <returns>EqualityMap</returns> public static EqualityMap ComputeEqualityMap(VerifierRangeProofParameters verifier, int decompositionLength) { EqualityMap map = new EqualityMap(); int dlIndex = 0; // process forall i in [0,m-2] D[i] = g^{delta,i} h^{tau,i} for (int i = 0; i < decompositionLength - 1; ++i) { map.Add(new PrettyName("delta", i), new DoubleIndex(dlIndex, 0)); ++dlIndex; } // skip D[m -1] -- this will be a separate proof based on RangeProofType // process forall i in [1,m-1]: A[i]/B[i] = g^{chi,i} h^{zeta,i} // Note: A[0]/B[0] appears in the proof indirectly as D[0] for (int i = 1; i < decompositionLength; ++i) { map.Add(new PrettyName("chi", i), new DoubleIndex(dlIndex, 0)); ++dlIndex; } // process forall i in [1,m-1]: X[i] = (A[i]/B[i])^{chi,i} h^{mu,i} // Note: X[0]=null. for (int i = 1; i < decompositionLength; ++i) { map.Add(new PrettyName("chi", i), new DoubleIndex(dlIndex, 0)); ++dlIndex; } // process forall i in [1,m-1]: E[i] = (X[i]^-1)^{delta, i-1} h^{nu,i} // Note: E[0] = null. for (int i = 1; i < decompositionLength; ++i) { map.Add(new PrettyName("delta", i - 1), new DoubleIndex(dlIndex, 0)); ++dlIndex; } return(map); }
/// <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> /// Verifies the RangeProof. Returns true if it is valid, false otherwise. /// </summary> /// <param name="verifier">Verifier parameters.</param> /// <returns></returns> public bool Verify(VerifierRangeProofParameters verifier) { try { // Verify parameters if (!verifier.Verify()) { return(false); } // verify bit decomposition proofs if (!VerifyBitDecompositionProofs(verifier, this.A, this.B, ProofBitDecompositionOfA, ProofBitDecompositionOfB)) { return(false); } // verify FullRangeProof GroupElement[] closedAdivB = ComputeClosedAdivB(verifier, this.A, this.B); this.D[0] = closedAdivB[0]; ClosedDLRepOfGroupElement[] closedX = ComputeClosedX(verifier, this.X, closedAdivB); ClosedDLRepOfGroupElement[] closedE = ComputeClosedE(verifier, this.X, this.D, closedAdivB); ClosedDLRepOfGroupElement[] allClosedDL = CombineAllClosedDLReps(this.D, closedAdivB, closedX, closedE, verifier); EqualityMap map = ComputeEqualityMap(verifier, A.Length); VerifierEqualityParameters veParameters = new VerifierEqualityParameters( allClosedDL, map, verifier); bool success = this.FullRangeProof.Verify(veParameters); if (!success) { return(false); } // verify additional proof based on proof type GroupElement LastD = this.D[this.D.Length - 1]; switch (verifier.RangeProofType) { case VerifierRangeProofParameters.ProofType.GREATER_THAN: ClosedDLRepOfGroupElement gtEquation = new ClosedDLRepOfGroupElement( new GroupElement[1] { verifier.H }, LastD * verifier.G.Exponentiate(verifier.FieldZq.One.Negate()), verifier.Group); VerifierEqualityParameters greaterThanVerifier = new VerifierEqualityParameters( gtEquation, verifier); return(StrictlyThanProof.Verify(greaterThanVerifier)); case VerifierRangeProofParameters.ProofType.LESS_THAN: ClosedDLRepOfGroupElement ltEquation = new ClosedDLRepOfGroupElement( new GroupElement[1] { verifier.H }, LastD * verifier.G, verifier.Group); VerifierEqualityParameters lessThanVerifier = new VerifierEqualityParameters( ltEquation, verifier); return(StrictlyThanProof.Verify(lessThanVerifier)); case VerifierRangeProofParameters.ProofType.GREATER_THAN_OR_EQUAL_TO: VerifierSetMembershipParameters greaterEqualVerifier = new VerifierSetMembershipParameters( LastD, new FieldZqElement[] { verifier.FieldZq.Zero, verifier.FieldZq.One }, verifier); return(this.OrEqualToProof.Verify(greaterEqualVerifier)); case VerifierRangeProofParameters.ProofType.LESS_THAN_OR_EQUAL_TO: VerifierSetMembershipParameters lessEqualProver = new VerifierSetMembershipParameters( LastD, new FieldZqElement[] { verifier.FieldZq.Zero, verifier.FieldZq.One.Negate() }, verifier); return(this.OrEqualToProof.Verify(lessEqualProver)); } } catch (Exception) { } return(false); }