/// <summary>
 /// Constructs a <code>VerifierPresentationProtocolParameters</code> instance.
 /// </summary>
 /// <param name="ip">The issuer parameters.</param>
 /// <param name="disclosed">Disclosed attribute indices.</param>
 /// <param name="message">Presentation message.</param>
 /// <param name="token">Presented token.</param>
 public VerifierPresentationProtocolParameters(IssuerParameters ip, int[] disclosed, byte[] message, UProveToken token)
 {
     IP        = ip;
     Disclosed = disclosed;
     Message   = message;
     Token     = token;
 }
Example #2
0
        /// <summary>
        /// Verifies a U-Prove token signature.
        /// </summary>
        /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param>
        /// <param name="upt">The U-Prove token to verify.</param>
        /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception>
        public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (upt.H == Gq.Identity)
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)");
            }
            GroupElement[]   bases     = new GroupElement[2];
            FieldZqElement[] exponents = new FieldZqElement[2];

            HashFunction hash = ip.HashFunction;

            hash.Hash(upt.H);
            hash.Hash(upt.PI);
            hash.Hash(upt.SigmaZPrime);
            bases[0] = Gq.G; exponents[0] = upt.SigmaRPrime;
            bases[1] = ip.G[0]; exponents[1] = upt.SigmaCPrime.Negate();
            hash.Hash(Gq.MultiExponentiate(bases, exponents));
            bases[0] = upt.H; exponents[0] = upt.SigmaRPrime;
            bases[1] = upt.SigmaZPrime; exponents[1] = upt.SigmaCPrime.Negate();
            hash.Hash(Gq.MultiExponentiate(bases, exponents));
            if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest))
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token signature");
            }
        }
Example #3
0
        /// <summary>
        /// Computes the U-Prove token identifier.
        /// </summary>
        /// <param name="ip">The issuer parameters associated with <code>upt</code>.</param>
        /// <param name="upt">The U-Prove token from which to compute the identifier.</param>
        /// <returns></returns>
        public static byte[] ComputeTokenID(IssuerParameters ip, UProveToken upt)
        {
            HashFunction hash = ip.HashFunction;

            hash.Hash(upt.H);
            hash.Hash(upt.SigmaZPrime);
            hash.Hash(upt.SigmaCPrime);
            hash.Hash(upt.SigmaRPrime);
            return(hash.Digest);
        }
Example #4
0
        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));
            }
        }
Example #5
0
 /// <summary>
 /// Indicates that attributes are carried over from the source token into the new one.
 /// </summary>
 /// <param name="sourceIndex">The indices of the attributes in the existing token.</param>
 /// <param name="destinationIndex">The indices of the attributes in the new token.</param>
 /// /// <param name="sourceIP">The Issuer Parameters used to issue the source token. This can be the same as <c>Ip</c> if the
 /// same Issuer issues the source and new tokens.</param>
 /// <param name="sourceToken">The source token.</param>
 public void CarryOverAttribute(int[] sourceIndex, int[] destinationIndex, IssuerParameters sourceIP, UProveToken sourceToken)
 {
     if (sourceIndex == null || destinationIndex == null || sourceIP == null || sourceToken == null)
     {
         throw new ArgumentNullException("arguments can't be null");
     }
     if (sourceIndex.Length != destinationIndex.Length)
     {
         throw new ArgumentException("sourceIndex and destinationIndex must have the same lenght");
     }
     if (!sourceToken.Uidp.SequenceEqual <byte>(sourceIP.UidP))
     {
         throw new ArgumentException("sourceToken and sourceIP do not match");
     }
     C        = destinationIndex;
     Corig    = sourceIndex;
     SourceIP = sourceIP;
     Tokens   = sourceToken;
     HasCarryOverAttributes = true;
 }
Example #6
0
        /// <summary>
        /// Verifies a U-Prove token signature.
        /// </summary>
        /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param>
        /// <param name="upt">The U-Prove token to verify.</param>
        /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception>
        public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (upt.H == Gq.Identity)
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)");
            }

            HashFunction hash = ip.HashFunction;

            hash.Hash(upt.H);
            hash.Hash(upt.PI);
            hash.Hash(upt.SigmaZPrime);
            hash.Hash(Gq.G.Exponentiate(upt.SigmaRPrime) * ip.G[0].Exponentiate(upt.SigmaCPrime.Negate()));
            hash.Hash(upt.H.Exponentiate(upt.SigmaRPrime) * upt.SigmaZPrime.Exponentiate(upt.SigmaCPrime.Negate()));
            if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest))
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token signature");
            }
        }
 /// <summary>
 /// Computes the U-Prove token identifier.
 /// </summary>
 /// <param name="ip">The issuer parameters associated with <code>upt</code>.</param>
 /// <param name="upt">The U-Prove token from which to compute the identifier.</param>
 /// <returns></returns>
 public static byte[] ComputeTokenID(IssuerParameters ip, UProveToken upt)
 {
     HashFunction hash = ip.HashFunction;
     hash.Hash(upt.H);
     hash.Hash(upt.SigmaZPrime);
     hash.Hash(upt.SigmaCPrime);
     hash.Hash(upt.SigmaRPrime);
     return hash.Digest;
 }
    public static UProveToken convertUProveTokenComposite(IssuerParameters ip, UProveTokenComposite utc)
    {
      UProveToken up = new UProveToken();

      up.H = ip.Gq.CreateGroupElement(utc.H);
      up.IsDeviceProtected = utc.IsDeviceProtected;
      up.PI = utc.PI;
      up.SigmaCPrime = new BigInteger(1, utc.SigmaCPrime);
      up.SigmaRPrime = new BigInteger(1, utc.SigmaRPrime);
      up.SigmaZPrime = ip.Gq.CreateGroupElement(utc.SigmaZPrime);
      up.TI = utc.TI;
      up.Uidp = utc.Uidp;

      return up;
    }
        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");
            }
        }
 public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, byte[] pseudonymScope, byte[] message, byte[] messageD, UProveToken upt)
 {
     GroupElement gs = ProtocolHelper.GenerateScopeElement(ip.Gq, pseudonymScope);
     Verify(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, upt);
 }
        public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, byte[] pseudonymScope, byte[] message, byte[] messageD, UProveToken upt)
        {
            GroupElement gs = ProtocolHelper.GenerateScopeElement(ip.Gq, pseudonymScope);

            Verify(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, upt);
        }
 public void Verify(IssuerParameters ip, int[] disclosed, byte[] message, byte[] messageD, UProveToken upt)
 {
     GroupElement gs = null;
     Verify(ip, disclosed, null, 0, gs, message, messageD, upt);
 }
        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");
            }
        }
        /// <summary>
        /// Verifies a U-Prove token signature.
        /// </summary>
        /// <param name="ip">The Issuer parameters corresponding to the U-Prove token.</param>
        /// <param name="upt">The U-Prove token to verify.</param>
        /// <exception cref="InvalidUProveArtifactException">If the U-Prove token is invalid.</exception>
        public static void VerifyTokenSignature(IssuerParameters ip, UProveToken upt)
        {
            Group Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (upt.H == Gq.Identity)
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token (public key H = 1)");
            }

            HashFunction hash = ip.HashFunction;
            hash.Hash(upt.H);
            hash.Hash(upt.PI);
            hash.Hash(upt.SigmaZPrime);
            hash.Hash(Gq.G.Exponentiate(upt.SigmaRPrime) * ip.G[0].Exponentiate(upt.SigmaCPrime.Negate()));
            hash.Hash(upt.H.Exponentiate(upt.SigmaRPrime) * upt.SigmaZPrime.Exponentiate(upt.SigmaCPrime.Negate()));
            if (upt.SigmaCPrime != Zq.GetElementFromDigest(hash.Digest)) 
            {
                throw new InvalidUProveArtifactException("Invalid U-Prove token signature");
            }
        }
 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);
     }
 }
    public static UProveTokenComposite convertUProveToken(UProveToken up)
    {
      UProveTokenComposite utc = new UProveTokenComposite();

      utc.H = up.H.GetEncoded();
      utc.IsDeviceProtected = up.IsDeviceProtected;
      utc.PI = up.PI;
      utc.SigmaCPrime = up.SigmaCPrime.ToByteArray();
      utc.SigmaRPrime = up.SigmaRPrime.ToByteArray();
      utc.SigmaZPrime = up.SigmaZPrime.GetEncoded();
      utc.TI = up.TI;
      utc.Uidp = up.Uidp;

      return utc;
    }
Example #17
0
        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");
            }
        }
        public void Verify(IssuerParameters ip, int[] disclosed, byte[] message, byte[] messageD, UProveToken upt)
        {
            GroupElement gs = null;

            Verify(ip, disclosed, null, 0, gs, message, messageD, upt);
        }
 /// <summary>
 /// Constructs a <code>VerifierPresentationProtocolParameters</code> instance.
 /// </summary>
 /// <param name="ip">The issuer parameters.</param>
 /// <param name="disclosed">Disclosed attribute indices.</param>
 /// <param name="message">Presentation message.</param>
 /// <param name="token">Presented token.</param>
 public VerifierPresentationProtocolParameters(IssuerParameters ip, int[] disclosed, byte[] message, UProveToken token)
 {
     IP = ip;
     Disclosed = disclosed;
     Message = message;
     Token = token;
 }