/// <summary> /// Create verifier parameters. /// </summary> /// <param name="statements">Statements.</param> /// <param name="map">Equality map for statements.</param> /// <param name="crypto">Crypto parameters</param> public VerifierEqualityParameters( IStatement[] statements, EqualityMap map, CryptoParameters crypto) : base(crypto) { this.Map = map; this.setVerifierParameters(statements); }
/// <summary> /// Constructor. /// </summary> /// <param name="witnesses"></param> /// <param name="map"></param> /// <param name="crypto"></param> public ProverEqualityParameters( IWitness[] witnesses, EqualityMap map, CryptoParameters crypto) : base(crypto) { this.setProverParameters(witnesses); this.Map = map; }
/// <summary> /// Verifies this proof for when verifier.CompareToKnownValue=true. /// </summary> /// <param name="verifier">Verifier parameters</param> /// <returns></returns> private bool VerifyProofForKnownValue(VerifierInequalityProofParameters verifier) { // B must not be 1. if (this.B == verifier.Group.Identity) { return(false); } // Reconstruct DL equations from proof and verifier parameters ClosedPedersenCommitment closedX = new ClosedPedersenCommitment( new GroupElement[2] { verifier.G, verifier.H }, verifier.ClosedCommitmentX, verifier.Group); ClosedPedersenCommitment closedA = new ClosedPedersenCommitment( new GroupElement[2] { verifier.G, verifier.H }, this.A, verifier.Group); ClosedDLRepOfGroupElement closedB = new ClosedDLRepOfGroupElement( new GroupElement[1] { verifier.G }, this.B, verifier.Group); ClosedPedersenCommitment closedC = new ClosedPedersenCommitment( new GroupElement[2] { closedX.Value *verifier.G.Exponentiate(verifier.Value.Negate()), verifier.H }, this.B, verifier.Group); ClosedDLRepOfGroupElement[] equations = new ClosedDLRepOfGroupElement[] { closedX, closedA, closedB, closedC }; // verify the proof EqualityMap map = this.GetEqualityMap(); VerifierEqualityParameters eqVerifier = new VerifierEqualityParameters(equations, map, verifier); if (!this.Proof.Verify(eqVerifier)) { return(false); } return(true); }
/// <summary> /// Creates an EqualityMap used for Proof. This is actually a constant that can /// be independently generated by the prover and verifier. /// </summary> /// <returns></returns> private EqualityMap GetEqualityMap() { // create equality map // A = g^{\delta} h^ {gamma} // C = (X*g^{-v})^{\delta} h^{kappa} EqualityMap map = new EqualityMap(); map.Add(new PrettyName("delta", 0), new DoubleIndex(1, 0)); map.Add(new PrettyName("delta", 0), new DoubleIndex(3, 0)); return(map); }
/// <summary> /// Generates a list of Pedersen Commitments /// </summary> /// <param name="prover">Array of tokens</param> /// <param name="attributeIndices">target attribute for each token</param> /// <param name="commitmentsToAttribute">Pedersen commitment to target attribute in token. Generated via method /// Proof.PedersenCommmitmentsToAttributes</param> public UProveIntegrationProof(ProverPresentationProtocolParameters [] prover, int [] attributeIndices, PedersenCommitment [] commitmentsToAttribute) { if ((prover == null) || (prover.Length == 0)) { throw new ArgumentException("First argument should be an array of at least one element."); } if (!UProveIntegrationProof.AreTokensCompatible(prover)) { throw new ArgumentException("All tokens must use same group."); } if ((attributeIndices == null) || (attributeIndices.Length != prover.Length)) { throw new ArgumentNullException("Second argument must be an array of the same length as first argument."); } if ((commitmentsToAttribute == null) || (commitmentsToAttribute.Length != prover.Length)) { throw new ArgumentNullException("Third argument must be an array of the same length as first argument."); } // copy Pedersen Commitment values this.PedersenCommitmentValues = new GroupElement[prover.Length]; for (int i = 0; i < PedersenCommitmentValues.Length; ++i) { this.PedersenCommitmentValues[i] = commitmentsToAttribute[i].Value; } // Create Equality Proof between Pedersen Commitments and tokens. EqualityMap map = new EqualityMap(); IWitness [] witnesses = new IWitness[prover.Length * 2]; OpenUProveToken[] tokens = new OpenUProveToken[prover.Length]; for (int i = 0; i < tokens.Length; ++i) { // create uprove token and add target attribute to map witnesses[2 * i] = new OpenUProveToken(prover[i]); map.Add(new PrettyName("token", 2 * i), new DoubleIndex(i, attributeIndices[i])); // add pedersen commitment to witness list, and add to map witnesses[2 * i + 1] = commitmentsToAttribute[i]; map.Add(new PrettyName("token", 2 * i + 1), new DoubleIndex(i, 0)); } ProverEqualityParameters eqProver = new ProverEqualityParameters(witnesses, map, new CryptoParameters(prover[0].IP)); this.TokenCommitmentEqualityProof = new EqualityProof(eqProver); this.TokenCommitmentEqualityProof.IsGroupSerializable = false; }
/// <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> /// Verifies this proof that the committed values are valid Pedersen Commitments to token attributes. /// </summary> /// <param name="verifier">Array of verifier token parameters.</param> /// <param name="attributeIndices">Target attribute in each token.</param> /// <param name="committedValues">Array of Pedersen Commitment values.</param> /// <returns></returns> public bool Verify(VerifierPresentationProtocolParameters [] verifier, int [] attributeIndices) { if ((verifier == null) || (verifier.Length == 0)) { throw new ArgumentException("First argument should be an array of at least one element."); } if (!UProveIntegrationProof.AreTokensCompatible(verifier)) { throw new ArgumentException("All tokens must use same group."); } if ((attributeIndices == null) || (attributeIndices.Length != verifier.Length)) { throw new ArgumentNullException("Second argument must be an array of the same length as first argument."); } if ((this.PedersenCommitmentValues == null) || (this.PedersenCommitmentValues.Length != verifier.Length)) { throw new ArgumentNullException("Third argument must be an array of the same length as first argument."); } EqualityMap map = new EqualityMap(); IStatement[] statements = new IStatement[verifier.Length * 2]; ClosedUProveToken[] tokens = new ClosedUProveToken[verifier.Length]; for (int i = 0; i < tokens.Length; ++i) { // create uprove token and add target attribute to map statements[2 * i] = new ClosedUProveToken(verifier[i]); map.Add(new PrettyName("token", 2 * i), new DoubleIndex(i, attributeIndices[i])); // add pedersen commitment to witness list, and add to map statements[2 * i + 1] = new ClosedPedersenCommitment(verifier[i].IP, this.PedersenCommitmentValues[i]); map.Add(new PrettyName("token", 2 * i + 1), new DoubleIndex(i, 0)); } VerifierEqualityParameters eqVerifier = new VerifierEqualityParameters(statements, map, new CryptoParameters(verifier[0].IP)); return(this.TokenCommitmentEqualityProof.Verify(eqVerifier)); }
/// <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> /// 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); }
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); } }