/// <summary> /// Compare two presentation proofs. /// </summary> /// <param name="o">An object to compare against this presentation proof.</param> /// <returns>True if equal, false otherwise</returns> public override bool Equals(Object o) { if (o == null) { return(false); } CommitmentValues cv = o as CommitmentValues; if ((System.Object)cv == null) { return(false); } return(TildeC.Equals(cv.TildeC) && TildeA.SequenceEqual(cv.TildeA) && TildeR.Equals(cv.TildeR)); }
/// <summary> /// Constructs a new <code>PresentationProof</code> instance. /// </summary> /// <param name="disclosedAttributes">The disclosed attributes.</param> /// <param name="a">The <code>a</code> value.</param> /// <param name="ap">The <code>ap</code> value.</param> /// <param name="ps">The <code>Ps</code> value.</param> /// <param name="r">The <code>r</code> values.</param> /// <param name="commitments">The commitments values.</param> public PresentationProof(byte[][] disclosedAttributes, byte[] a, byte[] ap, GroupElement ps, FieldZqElement[] r, CommitmentValues[] commitments) { this.disclosedAttributes = disclosedAttributes; this.a = a; this.ap = ap; this.ps = ps; this.r = r; this.commitments = commitments; }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); int dArraySize = disclosed.Length + 2; GroupElement[] dBases = new GroupElement[dArraySize]; FieldZqElement[] dExponents = new FieldZqElement[dArraySize]; dBases[0] = ip.G[0]; dExponents[0] = ip.Zq.One; // g0^1 dBases[1] = ip.G[n + 1]; dExponents[1] = ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected); // gt^xt FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; int aPreImageArraySize = 2 + (n - disclosed.Length) + (upt.IsDeviceProtected ? 1 : 0); GroupElement[] aPreImageBases = new GroupElement[aPreImageArraySize]; FieldZqElement[] aPreImageExponents = new FieldZqElement[aPreImageArraySize]; // aPreImage arrays' index 0 values depend on the dArray values; they will be filled out later aPreImageBases[1] = upt.H; aPreImageExponents[1] = this.r[0]; // h^r0 int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dBases[dIndex + 2] = ip.G[i]; dExponents[dIndex + 2] = disclosedX[dIndex]; dIndex++; } else { aPreImageBases[uIndex + 1] = ip.G[i]; aPreImageExponents[uIndex + 1] = this.r[uIndex]; // gi^ri if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); aPreImageBases[0] = Gq.MultiExponentiate(dBases, dExponents); aPreImageExponents[0] = c.Negate(); // g0.gt^xt.Product[gi^xi]_(for disclosed i) if (upt.IsDeviceProtected) { aPreImageBases[aPreImageArraySize - 1] = ip.Gd; aPreImageExponents[aPreImageArraySize - 1] = this.r[this.r.Length - 1]; // gd^rd } HashFunction hash = ip.HashFunction; hash.Hash(Gq.MultiExponentiate(aPreImageBases, aPreImageExponents)); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(Gq.MultiExponentiate(new GroupElement[] { ps, gs }, new FieldZqElement[] { c, r[pseudonymResponseIndex] })); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { GroupElement[] cBases = new GroupElement[3]; FieldZqElement[] cExponents = new FieldZqElement[3]; cBases[1] = Gq.G; cBases[2] = ip.G[1]; cExponents[0] = c; for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; cBases[0] = commitment.TildeC; cExponents[1] = this.r[commitmentResponseIndices[i]]; cExponents[2] = commitment.TildeR; hash.Hash(Gq.MultiExponentiate(cBases, cExponents)); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } }
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt) { try { // make sure disclosed list is sorted if (disclosed == null) { // can't be null later, so make it an empty array disclosed = new int[] { }; } Array.Sort(disclosed); Group Gq = ip.Gq; int n = ip.E.Length; bool presentPseudonym = false; if (gs != null && pseudonymAttribIndex != 0) { if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex)) { throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)"); } if (disclosed.Contains(pseudonymAttribIndex)) { throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array"); } presentPseudonym = true; } else // no nym { pseudonymAttribIndex = 0; } bool verifyCommitments = (committed != null && committed.Length > 0); if (verifyCommitments) { Array.Sort(committed); } ProtocolHelper.VerifyTokenSignature(ip, upt); FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length]; GroupElement dAccumulator = ip.G[0] * ip.G[n + 1].Exponentiate(ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected)); // g0 * gt^xt GroupElement uAccumulator = upt.H.Exponentiate(this.r[0]); int dIndex = 0; int uIndex = 1; int cIndex = 0; int pseudonymResponseIndex = 0; int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null; for (int i = 1; i <= n; i++) { if (disclosed.Contains(i)) { disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]); dAccumulator = dAccumulator * ip.G[i].Exponentiate(disclosedX[dIndex]); dIndex++; } else { uAccumulator = uAccumulator * ip.G[i].Exponentiate(this.r[uIndex]); if (presentPseudonym) { if (pseudonymAttribIndex == i) { pseudonymResponseIndex = uIndex; } } if (verifyCommitments) { if (committed.Contains(i)) { // remember which response correspond to which commitment commitmentResponseIndices[cIndex] = uIndex; cIndex++; } } uIndex++; } } if (pseudonymAttribIndex == DeviceAttributeIndex) { pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array } byte[] unused; // verifier doesn't use the returned message for device FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused); HashFunction hash = ip.HashFunction; hash.Hash((dAccumulator.Exponentiate(c.Negate()) * uAccumulator * (upt.IsDeviceProtected ? ip.Gd.Exponentiate(this.r[this.r.Length - 1]) : Gq.Identity))); if (!this.a.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } if (presentPseudonym) { hash.Hash(this.ps.Exponentiate(c).Multiply(gs.Exponentiate(this.r[pseudonymResponseIndex]))); if (!this.ap.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid pseudonym"); } } if (verifyCommitments) { for (int i = 0; i < commitmentResponseIndices.Length; i++) { CommitmentValues commitment = this.Commitments[i]; hash.Hash(commitment.TildeC.Exponentiate(c).Multiply(ip.Gq.G.Exponentiate(this.r[commitmentResponseIndices[i]])).Multiply(ip.G[1].Exponentiate(commitment.TildeR))); if (!commitment.TildeA.SequenceEqual(hash.Digest)) { throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]); } } } } catch (ArgumentException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } catch (IndexOutOfRangeException) { throw new InvalidUProveArtifactException("Invalid presentation proof"); } }
internal static FieldZqElement GenerateChallenge(IssuerParameters ip, UProveToken upt, byte[] a, int pseudonymIndex, byte[] ap, GroupElement Ps, byte[] m, byte[] md, int[] disclosed, FieldZqElement[] disclosedX, int[] committed, CommitmentValues[] commitments, out byte[] mdPrime) { bool hasCommitments = (committed != null && committed.Length > 0); if (hasCommitments) { if (committed.Length != commitments.Length) { throw new ArgumentException("Inconsistent committed indices and commitment values"); } } HashFunction hash = ip.HashFunction; hash.Hash(ComputeTokenID(ip, upt)); hash.Hash(a); hash.Hash(disclosed); hash.Hash(disclosedX); if (!hasCommitments) { hash.HashNull(); // C hash.HashNull(); // < {tildeC} > hash.HashNull(); // < {tildeA} > } else { hash.Hash(committed); hash.Hash(commitments.Length); // length of < {tildeC} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeC); } hash.Hash(commitments.Length); // length of < {tildeA} > for (int i = 0; i < commitments.Length; i++) { hash.Hash(commitments[i].TildeA); } } hash.Hash(pseudonymIndex == PresentationProof.DeviceAttributeIndex ? 0 : pseudonymIndex); hash.Hash(ap); hash.Hash(Ps); hash.Hash(m); mdPrime = hash.Digest; if (upt.IsDeviceProtected) { hash = ip.HashFunction; hash.Hash(md); hash.Hash(mdPrime); return ip.Zq.GetElementFromDigest(hash.Digest); } else { return ip.Zq.GetElementFromDigest(mdPrime); } }