/// <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> /// 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); }