/// <summary>
 /// Represents a U-Prove token.
 /// </summary>
 /// <param name="uidp">The Issuer parameters UID.</param>
 /// <param name="h">The public key value h.</param>
 /// <param name="TI">The token information field value.</param>
 /// <param name="PI">The Prover information field value.</param>
 /// <param name="sigmaZPrime">The sigmaZPrime value.</param>
 /// <param name="sigmaCPrime">The sigmaCPrime value.</param>
 /// <param name="sigmaRPrime">The sigmaRPrime value.</param>
 /// <param name="isDeviceProtected">True if the token is Device-protected, false otherwise.</param>
 public UProveToken(byte[] uidp, GroupElement h, byte[] TI, byte[] PI, GroupElement sigmaZPrime, FieldZqElement sigmaCPrime, FieldZqElement sigmaRPrime, bool isDeviceProtected)
 {
     this.uidp = uidp;
     this.h = h;
     this.ti = TI;
     this.pi = PI;
     this.sigmaZPrime = sigmaZPrime;
     this.sigmaCPrime = sigmaCPrime;
     this.sigmaRPrime = sigmaRPrime;
     this.isDeviceProtected = isDeviceProtected;
 }
Example #2
0
 /// <summary>
 /// Private constructor - takes and sets all fields.
 /// </summary>
 /// <param name="Gq">The group</param>
 /// <param name="gd">The device generator</param>
 /// <param name="Zq">The Field associated to the group <c>Gq</c></param>
 /// <param name="xd">The xd.</param>
 /// <param name="preGenWdPrime">The pre gen wd prime.</param>
 VirtualDevice(Group Gq, GroupElement gd, FieldZq Zq, FieldZqElement xd, FieldZqElement preGenWdPrime)
 {
     if (xd != null && !Zq.IsElement(xd))
     {
         throw new ArgumentException("xd is not a valid Zq element");
     }
     this.Gd      = gd;
     this.Gq      = Gq;
     this.Zq      = Zq;
     this.xd      = xd ?? this.Zq.GetRandomElement(true); // assign xd a random value if null
     this.wdPrime = preGenWdPrime;
     this.hd      = this.Gd.Exponentiate(this.xd);
 }
        /// <summary>
        /// Generates the Issuer parameters cryptographic data, <code>ip</code> will be updated with the cryptographic data.
        /// </summary>
        /// <param name="ip">An instanciated Issuer parameters; the Gq and E properties must be set.</param>
        /// <param name="gValues">The issuer generators to use, or null.</param>
        /// <param name="supportDevice">Indicates if the device generator must be generated.</param>
        /// <returns>The Issuer parameters private key.</returns>
        internal static FieldZqElement GenerateIssuerParametersCryptoData(IssuerParameters ip, GroupElement[] gValues, bool supportDevice)
        {
            if (ip == null)
            {
                throw new ArgumentNullException("ip");
            }
            if (ip.Gq == null)
            {
                throw new ArgumentException("Group description is not set");
            }
            int n = ip.E == null ? 0 : ip.E.Length;
            Group Gq = ip.Gq;
            ip.G = new GroupElement[n + 2];

            FieldZqElement privateKey;
            if (gValues == null)
            {
                FieldZqElement[] y = ip.Zq.GetRandomElements(n + 2, false);
                privateKey = y[0];

                for (int i = 0; i < (n + 2); i++)
                {
                    ip.G[i] = Gq.G.Exponentiate(y[i]);
                }
            }
            else
            {
                // g_0
                privateKey = ip.Zq.GetRandomElement(false);
                ip.G[0] = Gq.G.Exponentiate(privateKey);

                // g_1,..,g_n
                for (int i = 1; i < (n + 1); i++)
                {
                    ip.G[i] = gValues[i - 1];
                }

                // g_t
                int t = n + 1;
                ip.G[t] = gValues[gValues.Length - 1];
            }

            if (supportDevice)
            {
                if (ip.Gd == null)
                {
                    ip.Gd = Gq.G.Exponentiate(ip.Zq.GetRandomElement(false));
                }
            }
            return privateKey;
        }
Example #4
0
        /// <summary>
        /// Generates an array of random group elements.  Calls GetRandomElement n times.
        /// </summary>
        /// <param name="n">The number of elements to return.</param>
        /// <param name="nonIdentity">True to return non-identity elements.</param>
        /// <param name="maxBitLength">Maximum length of the exponent used to get random element. For example, to choose a random
        /// group elements from the set {G^0, G^1, G^2, G^3}, set maxBitLength to 2. Set maxBitLength to -1 to choose random group elements
        /// from the entire group.</param>
        /// <returns>Random group elements.</returns>
        public GroupElement[] GetRandomElements(int n, bool nonIdentity, int maxBitLength = -1)
        {
            if (maxBitLength != -1)
            {
                throw new NotImplementedException("GetRandomElement cannot handle argument maxBitLength != -1.");
            }

            GroupElement[] r = new GroupElement[n];
            for (int i = 0; i < n; i++)
            {
                r[i] = GetRandomElement(nonIdentity, maxBitLength);
            }
            return(r);
        }
Example #5
0
        /// <summary>
        /// Generates the U-Prove key and tokens.
        /// </summary>
        /// <param name="message">The third issuance message.</param>
        /// <param name="skipTokenValidation">Set to <code>true</code> to skip token validation;
        /// <code>false</code> otherwise. Token validation SHOULD be performed before use, either
        /// by setting <code>skipTokenValidation</code> to <code>false</code>, or by later using the
        /// <code>ProtocolHelper.VerifyTokenSignature</code> method.
        /// </param>
        /// <exception cref="InvalidUProveArtifactException">If the token signature is invalid.</exception>
        /// <returns>An array of U-Prove keys and tokens</returns>
        public UProveKeyAndToken[] GenerateTokens(ThirdIssuanceMessage message, bool skipTokenValidation = false)
        {
            if (state != State.Second)
            {
                throw new InvalidOperationException("GenerateSecondMessage must be called first");
            }

            bool doBatchValidation  = !skipTokenValidation && batchValidationSecurityLevel > 0;
            bool doNormalValidation = !skipTokenValidation && batchValidationSecurityLevel <= 0;

            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            FieldZqElement[] sigmaRPrime = new FieldZqElement[numberOfTokens];

            FieldZqElement phoAR = Zq.Zero, phoR = Zq.Zero, phoAC = Zq.Zero, phoC = Zq.Zero;
            GroupElement   batchAcc = Gq.Identity;

            for (int i = 0; i < numberOfTokens; i++)
            {
                sigmaRPrime[i] = message.sigmaR[i] + beta2[i];
                if (doBatchValidation)
                {
                    FieldZqElement s = Zq.GetRandomElement(true, batchValidationSecurityLevel);
                    phoAR    += (s * alpha[i] * sigmaRPrime[i]);
                    phoR     += (s * sigmaRPrime[i]);
                    phoAC    += (s * alpha[i] * sigmaCPrime[i]);
                    phoC     += (s * sigmaCPrime[i]);
                    batchAcc *= (sigmaAPrime[i] * sigmaBPrime[i]).Exponentiate(s);
                }
                else if (doNormalValidation)
                {
                    if (!(sigmaAPrime[i] * sigmaBPrime[i]).Equals(
                            ((Gq.G * h[i]).Exponentiate(sigmaRPrime[i]) * (ip.G[0] * sigmaZPrime[i]).Exponentiate(sigmaCPrime[i].Negate()))))
                    {
                        throw new InvalidUProveArtifactException("Invalid token signature: " + i);
                    }
                }
                ukat[i].Token = new UProveToken(ip.UidP, h[i], TI, PI, sigmaZPrime[i], sigmaCPrime[i], sigmaRPrime[i], isDeviceProtected);
            }
            if (doBatchValidation &&
                (batchAcc != Gq.G.Exponentiate(phoR) * gamma.Exponentiate(phoAR) * ip.G[0].Exponentiate(phoC.Negate()) * sigmaZ.Exponentiate(phoAC.Negate())))
            {
                throw new InvalidUProveArtifactException("Invalid token signature");
            }

            state = State.Tokens;
            return(ukat);
        }
        /// <summary>
        /// Constructs an Issuer parameters instance from a serialized string
        /// </summary>
        public IssuerParameters(string serializedIssuerParameters)
        {
            IssuerParameters.serializer = new Serializer();

            IssuerParameters issuerParameters = this.Deserialize <IssuerParameters>(serializedIssuerParameters);

            this.uidp  = issuerParameters.uidp;
            this.group = issuerParameters.group;
            this.uidh  = issuerParameters.uidh;
            this.g     = issuerParameters.g;
            this.gd    = issuerParameters.gd;
            this.e     = issuerParameters.e;
            this.s     = issuerParameters.s;
            this.usesRecommendedParameters = issuerParameters.usesRecommendedParameters;
        }
        /// <summary>
        /// Constructs an Issuer parameters instance.
        /// </summary>
        /// <param name="uidp">The Issuer parameters UID.</param>
        /// <param name="group">The group description.</param>
        /// <param name="uidh">The hash algorithm identifier.</param>
        /// <param name="g">The generator values.</param>
        /// <param name="gd">The Device generator, or null.</param>
        /// <param name="e">The encoding bytes.</param>
        /// <param name="s">The specification bytes.</param>
        /// <param name="usesRecommendedParameters">Indicates if the group and g array uses the recommended parameters.</param>
        /// <param name="maxNumberOfAttributes">maximum number of attributes, the issuer will be able to include into an issued token - extension by Fablei</param>
        public IssuerParameters(byte[] uidp, Group group, string uidh, GroupElement[] g, GroupElement gd, byte[] e, byte[] s, bool usesRecommendedParameters,
                                int maxNumberOfAttributes)
        {
            this.uidp  = uidp;
            this.group = group;
            this.uidh  = uidh;
            this.g     = g;
            this.gd    = gd;
            this.e     = e;
            this.s     = s;
            this.usesRecommendedParameters = usesRecommendedParameters;
            // extension by Fablei
            MaxNumberOfAttributes = maxNumberOfAttributes;

            IssuerParameters.serializer = new Serializer();
        }
    public static FirstIssuanceMessage convertFirstIssuanceMessageComposite(FirstIssuanceMessageComposite fic, IssuerParameters ip)
    {
      GroupElement[] geArray1 = new GroupElement[fic.SigmaA.Length];
      for (int i = 0; i < fic.SigmaA.Length; i++)
      {
        geArray1[i] = ip.Gq.CreateGroupElement(fic.SigmaA[i]);
      }

      GroupElement[] geArray2 = new GroupElement[fic.SigmaB.Length];
      for (int i = 0; i < fic.SigmaB.Length; i++)
      {
        geArray2[i] = ip.Gq.CreateGroupElement(fic.SigmaB[i]);
      }

      FirstIssuanceMessage fi = new FirstIssuanceMessage(ip.Gq.CreateGroupElement(fic.SigmaZ), geArray1, geArray2);
      return fi;
    }
 /// <summary>
 /// Convert a base64 string to a GroupElement[] using a specific Group object.
 /// </summary>
 /// <param name="encodedElements">The encoded string to convert.</param>
 /// <param name="group">The group object to use.</param>
 /// <returns>The converted object.</returns>
 public static GroupElement[] ToGroupElementArray(this String[] encodedElements, Group group)
 {
     if (encodedElements == null)
     {
         return(null);
     }
     if (group == null)
     {
         throw new ArgumentNullException("group");
     }
     GroupElement[] groupElements = new GroupElement[encodedElements.Length];
     for (int i = 0; i < encodedElements.Length; i++)
     {
         groupElements[i] = encodedElements[i].ToGroupElement(group);
     }
     return(groupElements);
 }
        /// <summary>
        /// Constructs an Issuer parameters instance from a serialized string
        /// </summary>
        public IssuerParameters(string serializedIssuerParameters)
        {
            IssuerParameters.serializer = new Serializer();

            IssuerParameters issuerParameters = this.Deserialize <IssuerParameters>(serializedIssuerParameters);

            this.uidp  = issuerParameters.uidp;
            this.group = issuerParameters.group;
            this.uidh  = issuerParameters.uidh;
            this.g     = issuerParameters.g;
            this.gd    = issuerParameters.gd;
            this.e     = issuerParameters.e;
            this.s     = issuerParameters.s;
            this.usesRecommendedParameters = issuerParameters.usesRecommendedParameters;

            // extension by Fablei
            MaxNumberOfAttributes = issuerParameters.MaxNumberOfAttributes;
        }
Example #11
0
        /// <summary>
        /// Computes the value <c>gamma</c>, an input to the issuance protocol.
        /// </summary>
        /// <param name="ip">The issuer parameters</param>
        /// <param name="A"> The attribute values, or null if the token contains no attributes </param>
        /// <param name="TI">The token information field</param>
        /// <param name="hd">The device public key, or <c>null</c> if device binding is not supported by the issuer paramters.</param>
        /// <returns>The group element gamma </returns>
        public static GroupElement ComputeIssuanceInput(IssuerParameters ip, byte[][] A, byte[] TI, GroupElement hd)
        {
            if (ip == null)
            {
                throw new ArgumentNullException("Issuer parameters are null");
            }
            int  n             = 0;
            bool supportDevice = (hd != null);

            if (supportDevice && !ip.IsDeviceSupported)
            {
                throw new InvalidOperationException("Issuer parameters does not support devices");
            }
            if (A != null)
            {
                n = A.Length;
            }
            Group Gq = ip.Gq;

            GroupElement[]   bases     = new GroupElement[n + 1];
            FieldZqElement[] exponents = new FieldZqElement[n + 1];
            for (int i = 0; i < n; i++)
            {
                FieldZqElement xi = ComputeXi(ip, i, A[i]);
                bases[i]     = ip.G[i + 1];
                exponents[i] = xi;
            }

            FieldZqElement xt = ComputeXt(ip, TI, supportDevice);

            bases[n]     = ip.G[n + 1];
            exponents[n] = xt;

            GroupElement gamma = ip.G[0] * Gq.MultiExponentiate(bases, exponents);

            // Multiply-in the device public key for device-protected tokens
            if (supportDevice)
            {
                gamma = gamma * hd;
            }
            return(gamma);
        }
Example #12
0
            GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps)
            {
                if (this.device == null)
                {
                    throw new DeviceException("Invalid context.");
                }
                if (this.wdPrime != null)
                {
                    throw new DeviceException("Initial witness already calculated.");
                }

                this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false);

                // compute pseudonym
                apPrime = gs.Exponentiate(this.wdPrime);
                Ps      = gs.Exponentiate(this.device.xd);

                // compute initial witness
                return(this.device.Gd.Exponentiate(this.wdPrime));
            }
    /// <summary>
    /// Constructs a new SampleDevice instance.
    /// </summary>
    /// <param name="gq">The group construction.</param>
    /// <param name="gd">The device generator.</param>
    public SmartCardDevice(GroupDescription gq, GroupElement gd, SmartCardParams smartCardParam)
    {
      pin = smartCardParam.pin;
      credID = smartCardParam.credID;
      groupID = smartCardParam.groupID;
      proverID = smartCardParam.proverID;
     
      // As SnartCardDevice do not provide a way to lookup card readr names
      // we provide a small potion of logic to lookup a card and cardreader
      List<CardInfo> cardInfoList = SmartCardUtils.GetReaderNames();
      // loop until we find a card with the status of "working mode". if none found
      // throw
      String readerName = null;
      foreach (CardInfo i in cardInfoList)
      {
        if (i.CardMode == (int)CardMode.WORKING)
        {
          readerName = i.ReaderName;
          break;
        }
      }
      if (readerName == null)
      {
        // TODO create a better exception
        throw new Exception("No card founds in working mode");
      }
      bool doTimeProfile = ParseConfigManager.doTimeProfile();
      this.device = new SmartCard(readerName, pin, doTimeProfile);
      // As the group and generator is set from the java init service we will only verify
      // TODO fix to see that group 0 is set on the hw smartcard.
      //if (!this.device.IsGeneratorSet(groupID))
      //{
        // TODO Find better exception
       // throw new Exception("No generator is set on the card to use this group");
      //}

      this.Gq = gq;
      this.Gd = gd;
    }
        private byte[] ComputeDigest(bool deviceProtected)
        {
            HashFunction H = this.HashFunction;

            H.Hash(UidP);
            H.Hash(group);
            if (deviceProtected)
            {
                // Gd must be part of the Gi array
                GroupElement[] GWithGd = new GroupElement[G.Length + 1];
                Array.Copy(G, GWithGd, G.Length);
                GWithGd[G.Length] = gd;
                H.Hash(GWithGd);
            }
            else
            {
                H.Hash(G);
            }
            H.Hash(E);
            H.Hash(S);
            return(H.Digest);
        }
Example #15
0
 void IParametrizedDeserialization.FinishDeserialization(IssuerParameters ip)
 {
     try
     {
         if (!this.deserializationStarted)
         {
             throw new SerializationException("deserialization not started");
         }
         this.h           = _h.ToGroupElement(ip);
         this.sigmaZPrime = _sigmaZPrime.ToGroupElement(ip);
         this.sigmaCPrime = _sigmaCPrime.ToFieldZqElement(ip.Zq);
         this.sigmaRPrime = _sigmaRPrime.ToFieldZqElement(ip.Zq);
     }
     catch
     {
         throw;
     }
     finally
     {
         this.deserializationStarted = false;
     }
 }
Example #16
0
        internal void OnDeserialized(StreamingContext context)
        {
            if (_uidp == null)
            {
                throw new UProveSerializationException("uidp");
            }
            if (_h == null)
            {
                throw new UProveSerializationException("h");
            }
            if (_sigmaZPrime == null)
            {
                throw new UProveSerializationException("szp");
            }
            if (_sigmaCPrime == null)
            {
                throw new UProveSerializationException("scp");
            }
            if (_sigmaRPrime == null)
            {
                throw new UProveSerializationException("srp");
            }

            // default to false if not provided
            if (_isDeviceProtected == null)
            {
                _isDeviceProtected = false;
            }

            this.uidp              = _uidp.ToByteArray();
            this.h                 = _h.ToGroupElement(Serializer.ip);
            this.ti                = _ti.ToByteArray();
            this.pi                = _pi.ToByteArray();
            this.sigmaZPrime       = _sigmaZPrime.ToGroupElement(Serializer.ip);
            this.sigmaCPrime       = _sigmaCPrime.ToFieldZqElement(Serializer.ip.Zq);
            this.sigmaRPrime       = _sigmaRPrime.ToFieldZqElement(Serializer.ip.Zq);
            this.isDeviceProtected = _isDeviceProtected.Value;
        }
Example #17
0
        /// <summary>
        /// Returns the product of all the numerators divided by the product of all the denominators.
        /// </summary>
        /// <param name="numerators">Array of group elements to multiply together to form the numerator.</param>
        /// <param name="denominators">Array of group elements to multiply together to form the denominator.</param>
        /// <returns>Quotient.</returns>
        public GroupElement Divide(GroupElement[] numerators, GroupElement[] denominators)
        {
            if ((numerators == null) || (denominators == null))
            {
                throw new ArgumentNullException("Divide expects all arguments to be not null.");
            }

            GroupElement numerator = this.Identity;

            for (int i = 0; i < numerators.Length; ++i)
            {
                numerator *= numerators[i];
            }

            GroupElement denominator = this.Identity;

            for (int i = 0; i < denominators.Length; ++i)
            {
                denominator *= denominators[i];
            }

            return(this.Divide(numerator, denominator));
        }
Example #18
0
        /// <summary>
        /// Constructs a new <code>Prover</code> instance.
        /// </summary>
        /// <param name="ip">The Issuer parameters.</param>
        /// <param name="numberOfTokens">Number of tokens to issue.</param>
        /// <param name="gamma">The gamma value encoding the token attributes. If <c>beta0</c> is non-null, then this value is blinded with <c>beta0</c>.</param>
        /// <param name="TI">The token information field value.</param>
        /// <param name="PI">The Prover information field value.</param>
        /// <param name="preGeneratedRandomData">Optional pregenerated ProverRandomData instance.</param>
        /// <param name="isDeviceProtected">True if the token is to be device-protected, false otherwise.</param>
        /// <param name="batchValidationSecurityLevel">The security level of the batch token signature validation. Given a security level <code>l</code>,
        /// the probability for the Prover to accept an invalid token is <code>2^-l</code>. If set to 0, than
        /// regular validation is used. A value of 20 is recommended.</param>
        /// <param name="beta0">Non-null if the input <c>gamma</c> value is blinded (collaborative issuance, i.e., the input <c>gamma</c> is blinded with beta0).
        ///                            This parameter defaults to null if ommitted. </param>
        internal Prover(IssuerParameters ip, int numberOfTokens, GroupElement gamma, byte[] TI, byte[] PI, ProverRandomData preGeneratedRandomData,
                        bool isDeviceProtected, ushort batchValidationSecurityLevel, FieldZqElement beta0 = null)
        {
            if (ip == null)
            {
                throw new ArgumentNullException("ip");
            }
            this.ip = ip;
            if (numberOfTokens <= 0)
            {
                throw new ArgumentException("numberOfTokens must be greater than 0");
            }
            this.numberOfTokens = numberOfTokens;
            this.TI             = TI;
            this.PI             = PI;
            if (preGeneratedRandomData != null &&
                (preGeneratedRandomData.Alpha.Length != numberOfTokens ||
                 preGeneratedRandomData.Beta1.Length != numberOfTokens ||
                 preGeneratedRandomData.Beta2.Length != numberOfTokens))
            {
                throw new ArgumentException("invalid preGeneratedRandomData");
            }
            this.isDeviceProtected            = isDeviceProtected;
            this.batchValidationSecurityLevel = batchValidationSecurityLevel;

            this.gamma = gamma;
            if (beta0 != null)                          // inputs are blinded; collab issuance
            {
                this.beta0Inverse = beta0.Invert();
            }
            else                                        // no collab issuance
            {
                this.beta0Inverse = ip.Zq.One;
            }

            Precompute(gamma, preGeneratedRandomData);
        }
        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");
            }
        }
 /// <summary>
 /// Constructs a new instance.
 /// </summary>
 /// <param name="tildeC">The <code>tildeC</code> value.</param>
 /// <param name="tildeA">The <code>tildeA</code> value.</param>
 /// <param name="tildeR">The <code>tildeR</code> value.</param>
 public CommitmentValues(GroupElement tildeC, byte[] tildeA, FieldZqElement tildeR)
 {
     TildeC = tildeC;
     TildeA = tildeA;
     TildeR = tildeR;
 }
        /// <summary>
        /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values.
        /// </summary>
        /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param>
        /// <param name="disclosed">An ordered array of disclosed attribute indices.</param>
        /// <param name="committed">An ordered array of committed attribute indices.</param>
        /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param>
        /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param>
        /// <param name="message">The presentation message.</param>
        /// <param name="messageD">The message for the Device, or null.</param>
        /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param>
        /// <param name="upkt">The U-Proke key and token.</param>
        /// <param name="attributes">The token attributes.</param>
        /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param>
        /// <param name="cpv">Returned commitment private values if commitments are computed.</param>
        /// <returns>A presentation proof.</returns>
        internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv)
        {
            if (upkt.Token.IsDeviceProtected && deviceContext == null)
            {
                throw new ArgumentNullException("Device context is not initialized");
            }
            bool generateCommitments = (committed != null && committed.Length > 0);
            FieldZqElement[] tildeO = null;

            // make sure disclosed and committed lists are sorted
            if (disclosed == null)
            {
                // can't be null later, so make it an empty array
                disclosed = new int[] { };
            }
            Array.Sort(disclosed);
            if (generateCommitments)
            {
                Array.Sort(committed);
            }

            int n = 0;
            if (ip.E != null)
                n = ip.E.Length;

            bool presentPseudonym = false;

            if (gs != null)
            {
                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 if (pseudonymAttribIndex > 0)
            {
                throw new ArgumentNullException("gs is null");
            }
            else
            {
                pseudonymAttribIndex = 0;
            }

            Group Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            FieldZqElement xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected);
            ProofGenerationRandomData random;
            if (preGenW == null)
            {
                random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected);
            }
            else
            {
                random = preGenW;
            }

            FieldZqElement[] x = new FieldZqElement[n];
            GroupElement temp = upkt.Token.H.Exponentiate(random.W0);
            int uIndex = 0;
            int dIndex = 0;
            int cIndex = 0;
            PresentationProof proof = new PresentationProof();
            proof.DisclosedAttributes = new byte[disclosed.Length][];
            int pseudonymRandomizerIndex = 0;
            if (generateCommitments)
            {
                proof.Commitments = new CommitmentValues[committed.Length];
                tildeO = new FieldZqElement[committed.Length];
            }
            HashFunction hash = ip.HashFunction;
            for (int i = 0; i < n; i++)
            {
                x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]);
                if (!disclosed.Contains(i + 1))
                {
                    temp = temp * ip.G[i + 1].Exponentiate(random.W[uIndex]);
                    if (presentPseudonym)
                    {
                        if (pseudonymAttribIndex == (i + 1))
                        {
                            pseudonymRandomizerIndex = uIndex;
                        }
                    }

                    if (generateCommitments && committed.Contains(i + 1))
                    {
                        GroupElement tildeC = ip.Gq.G.Exponentiate(x[i]) * ip.G[1].Exponentiate(random.TildeO[cIndex]);
                        tildeO[cIndex] = random.TildeO[cIndex];
                        GroupElement temp2 = ip.Gq.G.Exponentiate(random.W[uIndex]) * ip.G[1].Exponentiate(random.TildeW[cIndex]);
                        hash.Hash(temp2);
                        byte[] tildeA = hash.Digest;
                        proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null);

                        cIndex++;
                    }

                    uIndex++;
                }
                else if (generateCommitments && committed.Contains(i + 1))
                {
                    throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed");
                }
                else
                {
                    proof.DisclosedAttributes[dIndex] = attributes[i];
                    dIndex++;
                }
            }
            if (upkt.Token.IsDeviceProtected)
            {
                GroupElement ad;
                // pseudonym computed by device
                if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex)
                {
                    GroupElement apPrime;
                    GroupElement Ps;
                    ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps);
                    hash.Hash(apPrime * gs.Exponentiate(random.Wd));
                    proof.Ap = hash.Digest;
                    proof.Ps = Ps;
                }
                else
                {
                    ad = deviceContext.GetInitialWitness();
                }
                temp = temp * ip.Gd.Exponentiate(random.Wd) * ad;
            }
            hash.Hash(temp);
            proof.a = hash.Digest;

            // pseudonym derived from one token attribute
            if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex)
            {
                hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex]));
                proof.Ap = hash.Digest;
                proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]);
            }

            byte[] mdPrime;
            FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime);
            proof.r = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d
            proof.r[0] = c * upkt.PrivateKey + random.W0;
            uIndex = 1;
            for (int i = 1; i <= n; i++)
            {
                if (!disclosed.Contains(i))
                {
                    proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1];
                    uIndex++;
                }
            }
            if (upkt.Token.IsDeviceProtected)
            {
                proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd;
            }
            if (generateCommitments)
            {
                for (int i = 0; i < committed.Length; i++)
                {
                    proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i];
                }
            }

            random.Clear();
            cpv = new CommitmentPrivateValues(tildeO);
            return proof;
        }
Example #22
0
 /// <summary>
 /// Create a first issuance message. Notation defined in the U-Prove spec.
 /// </summary>
 public FirstIssuanceMessage(GroupElement sigmaZ, GroupElement[] sigmaA, GroupElement[] sigmaB)
 {
     this.sigmaA = sigmaA;
     this.sigmaB = sigmaB;
     this.sigmaZ = sigmaZ;
 }
            GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(GroupElement gs, out GroupElement apPrime, out GroupElement Ps)
            {
                if (this.device == null)
                {
                    throw new DeviceException("Invalid context.");
                }
                if (this.wdPrime != null)
                {
                    throw new DeviceException("Initial witness already calculated.");
                }

                this.wdPrime = this.device.wdPrime ?? this.device.Zq.GetRandomElement(false);
                
                // compute pseudonym
                apPrime = gs.Exponentiate(this.wdPrime);
                Ps = gs.Exponentiate(this.device.xd);

                // compute initial witness
                return this.device.Gd.Exponentiate(this.wdPrime);               
            }
Example #24
0
        /// <summary>
        /// Constructs a new <code>Issuer</code> instance.
        /// </summary>
        /// <param name="ikap">The Issuer key and parameters.</param>
        /// <param name="numberOfTokens">Number of tokens to issue.</param>
        /// <param name="gamma">The gamma value encoding the token attributes.</param>
        /// <param name="preGeneratedW">Optional pregenerated <code>numberOfTokens</code> random Zq elements.</param>
        internal Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, GroupElement gamma, FieldZqElement[] preGeneratedW)
        {
            if (ikap == null || ikap.PrivateKey == null || ikap.IssuerParameters == null)
            {
                throw new ArgumentNullException("ikap is malformed or null");
            }
            this.ikap = ikap;

            if (numberOfTokens <= 0)
            {
                throw new ArgumentException("numberOfTokens must be greater than 0");
            }
            this.numberOfTokens = numberOfTokens;

            if (gamma == null)
            {
                throw new ArgumentNullException("gamma is null");
            }

            if (preGeneratedW != null && preGeneratedW.Length != numberOfTokens)
            {
                throw new ArgumentException("invalid preGeneratedW array length");
            }

            Precompute(gamma, preGeneratedW);
        }
        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");
            }
        }
Example #26
0
 public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd, FieldZqElement[] preGeneratedW)
     : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), preGeneratedW)
 { }
Example #27
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 #28
0
        // Private helper function
        private static byte[] ComputeChallenge(IssuerParameters ip, GroupElement h0, GroupElement CGamma,
                                               GroupElement Ch0, GroupElement[] C, GroupElement tildeD, GroupElement tildeCgamma, GroupElement tildeT,
                                               GroupElement[] tildeC, byte[] message)
        {
            HashFunction H = ip.HashFunction;

            H.Hash(ip.Digest(false));
            H.Hash(h0);
            H.Hash(CGamma);
            H.Hash(Ch0);
            H.Hash(C);
            H.Hash(tildeD);
            H.Hash(tildeCgamma);
            H.Hash(tildeT);
            H.Hash(tildeC);
            H.Hash(message);

            byte[] digest = H.Digest;

#if DEBUG
            Debug.WriteLine("h0 = " + BitConverter.ToString(h0.GetEncoded()));
            Debug.WriteLine("CGamma = " + BitConverter.ToString(CGamma.GetEncoded()));
            Debug.WriteLine("Ch0 = " + BitConverter.ToString(Ch0.GetEncoded()));
            if (tildeC != null)
            {
                Debug.WriteLine("tildeC[0] = " + BitConverter.ToString(tildeC[0].GetEncoded()));
            }
            Debug.WriteLine("tildeD = " + BitConverter.ToString(tildeD.GetEncoded()));
            Debug.WriteLine("tildeT = " + BitConverter.ToString(tildeT.GetEncoded()));
            Debug.WriteLine("tildeCgamma = " + BitConverter.ToString(tildeCgamma.GetEncoded()));
            Debug.WriteLine("digest = " + BitConverter.ToString(digest));
#endif

            return(digest);
        }
        internal void OnDeserialized(StreamingContext context)
        {
            if (_uidp == null)
                throw new UProveSerializationException("uidp");
            if (_h == null)
                throw new UProveSerializationException("h");
            if (_sigmaZPrime == null)
                throw new UProveSerializationException("szp");
            if (_sigmaCPrime == null)
                throw new UProveSerializationException("scp");
            if (_sigmaRPrime == null)
                throw new UProveSerializationException("srp");
            
            // default to false if not provided
            if (_isDeviceProtected == null)
                _isDeviceProtected = false;

            this.uidp = _uidp.ToByteArray();
            this.h = _h.ToGroupElement(Serializer.ip);
            this.ti = _ti.ToByteArray();
            this.pi = _pi.ToByteArray();
            this.sigmaZPrime = _sigmaZPrime.ToGroupElement(Serializer.ip);
            this.sigmaCPrime = _sigmaCPrime.ToFieldZqElement(Serializer.ip.Zq);
            this.sigmaRPrime = _sigmaRPrime.ToFieldZqElement(Serializer.ip.Zq);
            this.isDeviceProtected = _isDeviceProtected.Value;
        }
      GroupElement IDevicePresentationContext.GetInitialWitnessesAndPseudonym(byte[] scope, out GroupElement apPrime, out GroupElement Ps)
      {
        // return a_d, ap', and p_s from page 19 u-prove spec.
        // the scope-exclusive pseudonym derivation function seems to be different from what is used
        // in U-Prove, so if a smartcard-based pseudonym is requested, better to call it directly without using this interface.
        //this.device.ProofSession = this.device.device.BeginCommitment(this.device.proverID);
        if (this.device.credID != -1)
        {
          try
          {
            // call GetPresCommitment, to ensure correct counter value on hw card.

            int credStatus = this.device.device.GetCreadentialStatus((byte)this.device.credID);
            cOut.write("cred status : GetInitialWitnessesAndPseudonym " + credStatus);
            if (credStatus == 0)
            {
              this.device.device.GetIssuanceCommitment((byte)this.device.credID);
            }
            else if (credStatus == 2)
            {
              this.device.device.GetPresCommitment(this.device.proverID, this.device.credID);
            }
          }
          catch (ErrorCode ex)
          {
            cOut.write("Counter do not have the correct value " + ex.Message);
            DebugUtils.DebugPrintErrorCodes(ex);
            this.device.device.EndCommitment();
            throw;
          }
        }
      
        byte[] a_dBig = this.device.device.GetDeviceCommitment(true);
#if DEBUG
        this.comForDebug = a_dBig;
#endif
        byte[] apPrimeBig = this.device.device.GetScopeExclusiveCommitment(scope, true);
        byte[] psBig = this.device.device.GetScopeExclusivePseudonym(scope, true);
        
        this.device.device.EndCommitment();

        apPrime = this.device.Gq.CreateGroupElement(apPrimeBig);
        Ps = this.device.Gq.CreateGroupElement(psBig);
        
        return this.device.Gq.CreateGroupElement(a_dBig);
      }
Example #31
0
 /// <summary>
 /// Returns <code>this*a</code>.
 /// </summary>
 /// <param name="a">The operand.</param>
 /// <returns>A group element.</returns>
 public abstract GroupElement Multiply(GroupElement a);
 /// <summary>
 /// Constructs an Issuer parameters instance.
 /// </summary>
 /// <param name="uidp">The Issuer parameters UID.</param>
 /// <param name="group">The group description.</param>
 /// <param name="uidh">The hash algorithm identifier.</param>
 /// <param name="g">The generator values.</param>
 /// <param name="gd">The Device generator, or null.</param>
 /// <param name="e">The encoding bytes.</param>
 /// <param name="s">The specification bytes.</param>
 /// <param name="usesRecommendedParameters">Indicates if the group and g array uses the recommended parameters.</param>
 public IssuerParameters(byte[] uidp, Group group, string uidh, GroupElement[] g, GroupElement gd, byte[] e, byte[] s, bool usesRecommendedParameters)
 {
     this.uidp  = uidp;
     this.group = group;
     this.uidh  = uidh;
     this.g     = g;
     this.gd    = gd;
     this.e     = e;
     this.s     = s;
     this.usesRecommendedParameters = usesRecommendedParameters;
     IssuerParameters.serializer    = new Serializer();
 }
Example #33
0
 public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd, FieldZqElement[] preGeneratedW)
     : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), preGeneratedW)
 {
 }
 /// <summary>
 /// Returns <code>this*a</code>.
 /// </summary>
 /// <param name="a">The operand.</param>
 /// <returns>A group element.</returns>
 public abstract GroupElement Multiply(GroupElement a);
Example #35
0
 /// <summary>
 /// Verifies that e is a group element.
 /// </summary>
 /// <param name="e">The element to test.</param>
 /// <exception cref="InvalidUProveArtifactException">
 /// Thrown if e is not in the group.</exception>
 public abstract void ValidateGroupElement(GroupElement e);
 /// <summary>
 /// Hash a GroupElement.
 /// </summary>
 /// <param name="value">A GroupElement to be hashed.</param>
 public void Hash(GroupElement value)
 {
     if (value == null)
     {
         HashNull();
         return;
     }
     value.UpdateHash(this);
 }
 /// <summary>
 /// Create a first issuance message. Notation defined in the U-Prove spec.
 /// </summary>
 public FirstIssuanceMessage(GroupElement sigmaZ, GroupElement[] sigmaA, GroupElement[] sigmaB)
 {
     this.sigmaA = sigmaA;
     this.sigmaB = sigmaB;
     this.sigmaZ = sigmaZ;
 }
 /// <summary>
 /// Convert a base64 string to a GroupElement[] using a specific Group object.
 /// </summary>
 /// <param name="encodedElements">The encoded string to convert.</param>
 /// <param name="group">The group object to use.</param>
 /// <returns>The converted object.</returns>
 public static GroupElement[] ToGroupElementArray(this String[] encodedElements, Group group)
 {
     if (encodedElements == null) return null;
     if (group == null) throw new ArgumentNullException("group");
     GroupElement[] groupElements = new GroupElement[encodedElements.Length];
     for (int i = 0; i < encodedElements.Length; i++)
     {
         groupElements[i] = encodedElements[i].ToGroupElement(group);
     }
     return groupElements;
 }
        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 Pseudonym(GroupElement A, GroupElement P, BigInteger R) { this.A = A; this.P = P; this.R = R; }
        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 static IssuerParameters convertIssuerParametersComposite(IssuerParametersComposite ipc, SessionData sessionData)
    {

      IssuerParameters ip = new IssuerParameters();

      ip.E = ipc.E;

      if (sessionData.group == null)
      {
        GroupDescription sGroup = convertSubgroupDescription(ipc.Gq);
        ip.Gq = sGroup;
      }
      else
      {
        ip.Gq = sessionData.group;
      }

      GroupElement[] geArray = new GroupElement[ipc.G.Length];
      for (int i = 0; i < ipc.G.Length; i++)
      {
        geArray[i] = ip.Gq.CreateGroupElement(ipc.G[i]);
      }

      ip.G = geArray;
      if (ipc.UsesRecommendedParameters && ipc.Gd == null)
      {
        ip.Gd = sessionData.parameterSet.Gd;
      }
      else if (ipc.Gd != null)
      {
        ip.Gd = ip.Gq.CreateGroupElement(ipc.Gd);
      }
      else
      {
        ip.Gd = ip.Gq.CreateGroupElement(ipc.Gq.Gd); //sessionData.groupElement;// parametersSet.Gd;
      }
      

      

      ip.S = ipc.S;
      ip.UidH = ipc.UidH;
      ip.UidP = ipc.UidP;
      ip.UsesRecommendedParameters = ipc.UsesRecommendedParameters;
      sessionData.group = ip.Gq;
      sessionData.groupElement = ip.Gd;
      return ip;
    }
 /// <summary>
 /// Private constructor - takes and sets all fields.
 /// </summary>
 /// <param name="Gq">The group</param>
 /// <param name="gd">The device generator</param>
 /// <param name="Zq">The Field associated to the group <c>Gq</c></param>
 /// <param name="xd">The xd.</param>
 /// <param name="preGenWdPrime">The pre gen wd prime.</param>
 VirtualDevice(Group Gq, GroupElement gd, FieldZq Zq, FieldZqElement xd, FieldZqElement preGenWdPrime)
 {
     if (xd != null && !Zq.IsElement(xd))
     {
         throw new ArgumentException("xd is not a valid Zq element");
     }
     this.Gd = gd;
     this.Gq = Gq;
     this.Zq = Zq;
     this.xd = xd ?? this.Zq.GetRandomElement(true);     // assign xd a random value if null
     this.wdPrime = preGenWdPrime;
     this.hd = this.Gd.Exponentiate(this.xd);
 }
Example #44
0
        private void Precompute(GroupElement gamma, FieldZqElement[] preGenW)
        {
            IssuerParameters ip = ikap.IssuerParameters;
            Group Gq = ip.Gq;
            FieldZq Zq = ip.Zq;
            sigmaZ = gamma.Exponentiate(ikap.PrivateKey);
            if (preGenW == null)
            {
                w = Zq.GetRandomElements(numberOfTokens, false);
            }
            else
            {
                w = preGenW;
            }

            sigmaA = new GroupElement[numberOfTokens];
            sigmaB = new GroupElement[numberOfTokens];
            for (int i = 0; i < numberOfTokens; i++)
            {
                sigmaA[i] = Gq.G.Exponentiate(w[i]);
                sigmaB[i] = gamma.Exponentiate(w[i]);
            }
            state = State.Initialized;
        }
    private void InitDevice(ParameterSet set)
    {

      if (device == null)
      {
        if (UseVirtualDevice)
        {
          device = new VirtualDevice(set, new BigInteger(1, deviceSecret));
        }
        else
        {
          // use a smartcard
          device = new SmartCardDevice(set.Group, set.Gd, smartCardParam);
        }
        Gq = set.Group;
        HashFunctionOID = SecurityLevelUtils.getHashfunction(set);
        hash = new HashFunction(HashFunctionOID);
        Gd = set.Gd;
      }
    }
Example #46
0
 public Prover(IssuerParameters ip, int numberOfTokens, byte[][] A, byte[] TI, byte[] PI, GroupElement hd)
     : this(ip, numberOfTokens, A, TI, PI, hd, null)
 {
 }
 /// <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;
 }
Example #48
0
 public Prover(IssuerParameters ip, int numberOfTokens, byte[][] A, byte[] TI, byte[] PI, GroupElement hd, ProverRandomData preGeneratedRandomData)
     : this(ip, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ip, A, TI, hd), TI, PI, preGeneratedRandomData, hd != null, DefaultBatchValidationSecurityLevel)
 {
 }
 public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO)
 {
     CommitmentPrivateValues cpv;
     PresentationProof proof = Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out cpv);
     tildeO = cpv.TildeO;
     return proof;
 }
Example #50
0
 public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd)
     : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), null)
 { }
Example #51
0
 public Issuer(IssuerKeyAndParameters ikap, int numberOfTokens, byte[][] A, byte[] TI, GroupElement hd)
     : this(ikap, numberOfTokens, ProtocolHelper.ComputeIssuanceInput(ikap.IssuerParameters, A, TI, hd), null)
 {
 }
        /// <summary>
        /// Computes the value <c>gamma</c>, an input to the issuance protocol. 
        /// </summary>
        /// <param name="ip">The issuer parameters</param>
        /// <param name="A"> The attribute values, or null if the token contains no attributes </param>
        /// <param name="TI">The token information field</param>
        /// <param name="hd">The device public key, or <c>null</c> if device binding is not supported by the issuer paramters.</param>
        /// <returns>The group element gamma </returns>
        public static GroupElement ComputeIssuanceInput(IssuerParameters ip, byte[][] A, byte[] TI, GroupElement hd)
        {
            if (ip == null)
            {
                throw new ArgumentNullException("Issuer parameters are null");
            }
            int n = 0;
            bool supportDevice = (hd != null);
            if (supportDevice && !ip.IsDeviceSupported)
            {
                throw new InvalidOperationException("Issuer parameters does not support devices");
            }
            if (A != null)
            {
                n = A.Length;
            }
            Group Gq = ip.Gq;
            GroupElement gamma = ip.G[0];
            for (int i = 0; i < n; i++)
            {
                FieldZqElement xi = ComputeXi(ip, i, A[i]);
                gamma = gamma * ip.G[i+1].Exponentiate(xi);
            }
            FieldZqElement xt = ComputeXt(ip, TI, supportDevice);
            gamma = gamma * ip.G[n+1].Exponentiate(xt);

            // Multiply-in the device public key for device-protected tokens
            if (supportDevice)
            {
                gamma = gamma * hd;
            }
            return gamma;
        }
Example #53
0
 /// <summary>
 /// Compute a product of powers.
 /// Return the product of the <code>bases[i].Exponentiate(exponents[i])</code> for <c>i</c> from <c>0</c> to <c>bases.Length -1</c>.
 /// The inputs <c>bases</c> and <c>exponents</c> must have the same length
 /// </summary>
 /// <param name="bases">Group elements array.</param>
 /// <param name="exponents">Field elements array.</param>
 /// <returns>Multi-exponentiation of the group elements to the field elements.</returns>
 public abstract GroupElement MultiExponentiate(GroupElement[] bases, FieldZqElement[] exponents);
 /// <summary>
 /// Constructs a new instance.
 /// </summary>
 /// <param name="tildeC">The <code>tildeC</code> value.</param>
 /// <param name="tildeA">The <code>tildeA</code> value.</param>
 /// <param name="tildeR">The <code>tildeR</code> value.</param>
 public CommitmentValues(GroupElement tildeC, byte[] tildeA, FieldZqElement tildeR)
 {
     TildeC = tildeC;
     TildeA = tildeA;
     TildeR = tildeR;
 }
        /// <summary>
        /// Generates a presentation proof including optionally presenting a pseudonym, creating attribute commitments, and passing pre-generated random values.
        /// </summary>
        /// <param name="ip">The issuer parameters corresponding to <code>upkt</code>.</param>
        /// <param name="disclosed">An ordered array of disclosed attribute indices.</param>
        /// <param name="committed">An ordered array of committed attribute indices.</param>
        /// <param name="pseudonymAttribIndex">Index of the attribute used to create a scope-exclusive pseudonym, or 0 if no pseudonym is to be presented. The index must not be part of the disclosed attributes.</param>
        /// <param name="gs">The pseudonym scope element, or null if no pseudonym is to be presented.</param>
        /// <param name="message">The presentation message.</param>
        /// <param name="messageD">The message for the Device, or null.</param>
        /// <param name="deviceContext">The active device context, if token is device-protected, or null.</param>
        /// <param name="upkt">The U-Proke key and token.</param>
        /// <param name="attributes">The token attributes.</param>
        /// <param name="preGenW">Optional pregenerated random data for the proof generation.</param>
        /// <param name="cpv">Returned commitment private values if commitments are computed.</param>
        /// <returns>A presentation proof.</returns>
        internal static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out CommitmentPrivateValues cpv)
        {
            if (upkt.Token.IsDeviceProtected && deviceContext == null)
            {
                throw new ArgumentNullException("Device context is not initialized");
            }
            bool generateCommitments = (committed != null && committed.Length > 0);

            FieldZqElement[] tildeO = null;

            // make sure disclosed and committed lists are sorted
            if (disclosed == null)
            {
                // can't be null later, so make it an empty array
                disclosed = new int[] { };
            }
            Array.Sort(disclosed);
            if (generateCommitments)
            {
                Array.Sort(committed);
            }

            int n = 0;

            if (ip.E != null)
            {
                n = ip.E.Length;
                if (n != attributes.Length)
                {
                    throw new ArgumentException("number of attributes is inconsistent with issuer parameters");
                }
            }

            bool presentPseudonym = false;

            if (gs != null)
            {
                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 if (pseudonymAttribIndex > 0)
            {
                throw new ArgumentNullException("gs is null");
            }
            else
            {
                pseudonymAttribIndex = 0;
            }

            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            FieldZqElement            xt = ProtocolHelper.ComputeXt(ip, upkt.Token.TI, upkt.Token.IsDeviceProtected);
            ProofGenerationRandomData random;

            if (preGenW == null)
            {
                random = ProofGenerationRandomData.Generate(n - disclosed.Length, generateCommitments ? committed.Length : 0, Zq, upkt.Token.IsDeviceProtected);
            }
            else
            {
                random = preGenW;
            }

            // set up the multi-exponentiation arrays, with h^w0 as the first term
            int multiExpArraySize = 1 + (n - disclosed.Length) + (upkt.Token.IsDeviceProtected ? 1 : 0);

            GroupElement[]   bases     = new GroupElement[multiExpArraySize];
            FieldZqElement[] exponents = new FieldZqElement[multiExpArraySize];
            int multiExpIndex          = 0;

            bases[multiExpIndex]       = upkt.Token.H;
            exponents[multiExpIndex++] = random.W0;

            FieldZqElement[] x      = new FieldZqElement[n];
            int uIndex              = 0;
            int dIndex              = 0;
            int cIndex              = 0;
            PresentationProof proof = new PresentationProof();

            proof.DisclosedAttributes = new byte[disclosed.Length][];
            int pseudonymRandomizerIndex = 0;

            if (generateCommitments)
            {
                proof.Commitments = new CommitmentValues[committed.Length];
                tildeO            = new FieldZqElement[committed.Length];
            }
            HashFunction hash = ip.HashFunction;

            GroupElement[] cBases = new GroupElement[2] {
                Gq.G, ip.G[1]
            };
            for (int i = 0; i < n; i++)
            {
                x[i] = ProtocolHelper.ComputeXi(ip, i, attributes[i]);
                if (!disclosed.Contains(i + 1))
                {
                    bases[multiExpIndex]       = ip.G[i + 1];
                    exponents[multiExpIndex++] = random.W[uIndex];
                    if (presentPseudonym)
                    {
                        if (pseudonymAttribIndex == (i + 1))
                        {
                            pseudonymRandomizerIndex = uIndex;
                        }
                    }

                    if (generateCommitments && committed.Contains(i + 1))
                    {
                        GroupElement tildeC = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] {
                            x[i], random.TildeO[cIndex]
                        });
                        tildeO[cIndex] = random.TildeO[cIndex];
                        GroupElement temp2 = ip.Gq.MultiExponentiate(cBases, new FieldZqElement[2] {
                            random.W[uIndex], random.TildeW[cIndex]
                        });
                        hash.Hash(temp2);
                        byte[] tildeA = hash.Digest;
                        proof.Commitments[cIndex] = new CommitmentValues(tildeC, tildeA, null);
                        cIndex++;
                    }

                    uIndex++;
                }
                else if (generateCommitments && committed.Contains(i + 1))
                {
                    throw new ArgumentException("attribute " + (i + 1) + " cannot be both disclosed and committed");
                }
                else
                {
                    proof.DisclosedAttributes[dIndex] = attributes[i];
                    dIndex++;
                }
            }
            GroupElement aPreImage;

            if (upkt.Token.IsDeviceProtected)
            {
                GroupElement ad;
                // pseudonym computed by device
                if (presentPseudonym && pseudonymAttribIndex == DeviceAttributeIndex)
                {
                    GroupElement apPrime;
                    GroupElement Ps;
                    ad = deviceContext.GetInitialWitnessesAndPseudonym(gs, out apPrime, out Ps);
                    hash.Hash(apPrime * gs.Exponentiate(random.Wd));
                    proof.Ap = hash.Digest;
                    proof.Ps = Ps;
                }
                else
                {
                    ad = deviceContext.GetInitialWitness();
                }
                bases[multiExpIndex]       = ip.Gd;
                exponents[multiExpIndex++] = random.Wd;
                aPreImage = Gq.MultiExponentiate(bases, exponents) * ad;
            }
            else
            {
                aPreImage = Gq.MultiExponentiate(bases, exponents);
            }
            hash.Hash(aPreImage);
            proof.a = hash.Digest;

            // pseudonym derived from one token attribute
            if (presentPseudonym && pseudonymAttribIndex != DeviceAttributeIndex)
            {
                hash.Hash(gs.Exponentiate(random.W[pseudonymRandomizerIndex]));
                proof.Ap = hash.Digest;
                proof.Ps = gs.Exponentiate(x[pseudonymAttribIndex - 1]);
            }

            byte[]         mdPrime;
            FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upkt.Token, proof.a, pseudonymAttribIndex, proof.ap, proof.Ps, message, messageD, disclosed, GetDisclosedX(disclosed, x), committed, proof.Commitments, out mdPrime);

            proof.r    = new FieldZqElement[1 + n - disclosed.Length + (upkt.Token.IsDeviceProtected ? 1 : 0)]; // r_0, {r_i} for undisclosed i, r_d
            proof.r[0] = c * upkt.PrivateKey + random.W0;
            uIndex     = 1;
            for (int i = 1; i <= n; i++)
            {
                if (!disclosed.Contains(i))
                {
                    proof.r[uIndex] = c.Negate() * x[i - 1] + random.W[uIndex - 1];
                    uIndex++;
                }
            }
            if (upkt.Token.IsDeviceProtected)
            {
                proof.r[proof.r.Length - 1] = deviceContext.GetDeviceResponse(messageD, mdPrime, ip.HashFunctionOID) + random.Wd;
            }
            if (generateCommitments)
            {
                for (int i = 0; i < committed.Length; i++)
                {
                    proof.Commitments[i].TildeR = c.Negate() * random.TildeO[i] + random.TildeW[i];
                }
            }

            random.Clear();
            cpv = new CommitmentPrivateValues(tildeO);
            return(proof);
        }
        public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO)
        {
            CommitmentPrivateValues cpv;
            PresentationProof       proof = Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out cpv);

            tildeO = cpv.TildeO;
            return(proof);
        }
Example #57
0
        /// <summary>
        /// Generates the second issuance message.
        /// </summary>
        /// <param name="message">The first issuance message.</param>
        /// <returns>The second issuance message.</returns>
        public SecondIssuanceMessage GenerateSecondMessage(FirstIssuanceMessage message)
        {
            if (state != State.Initialized)
            {
                throw new InvalidOperationException("Prover not initialized properly");
            }

            Group Gq = ip.Gq;
            this.sigmaZ = message.sigmaZ;

            sigmaZPrime = new GroupElement[numberOfTokens];
            sigmaAPrime = new GroupElement[numberOfTokens];
            sigmaBPrime = new GroupElement[numberOfTokens];
            sigmaCPrime = new FieldZqElement[numberOfTokens];
            FieldZqElement[] sigmaC = new FieldZqElement[numberOfTokens];
            for (int i = 0; i < numberOfTokens; i++)
            {
                FieldZqElement blindingExponent = alpha[i];
                sigmaZPrime[i] = message.sigmaZ.Exponentiate(blindingExponent);
                sigmaAPrime[i] = t1[i] * message.sigmaA[i];
                sigmaBPrime[i] = sigmaZPrime[i].Exponentiate(beta1[i]) * t2[i] * message.sigmaB[i].Exponentiate(blindingExponent);

                HashFunction hash = ip.HashFunction;
                hash.Hash(h[i]);
                hash.Hash(PI);
                hash.Hash(sigmaZPrime[i]);
                hash.Hash(sigmaAPrime[i]);
                hash.Hash(sigmaBPrime[i]);
                sigmaCPrime[i] = ip.Zq.GetElementFromDigest(hash.Digest);
                sigmaC[i] = sigmaCPrime[i] + beta1[i];
            }
            state = State.Second;
            return new SecondIssuanceMessage(sigmaC);
        }
        public static PresentationProof Generate(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, byte[] pseudonymScope, byte[] message, byte[] messageD, IDevicePresentationContext deviceContext, UProveKeyAndToken upkt, byte[][] attributes, ProofGenerationRandomData preGenW, out FieldZqElement[] tildeO)
        {
            GroupElement gs = ProtocolHelper.GenerateScopeElement(ip.Gq, pseudonymScope);

            return(Generate(ip, disclosed, committed, pseudonymAttribIndex, gs, message, messageD, deviceContext, upkt, attributes, preGenW, out tildeO));
        }
 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);
     }
 }
 /// <summary>
 /// Hash a GroupElement array.
 /// </summary>
 /// <param name="values">An array of GroupElements to be hashed.</param>
 public void Hash(GroupElement[] values)
 {
     if (values == null)
     {
         HashNull();
     }
     else
     {
         Hash(values.Length);
         foreach (GroupElement i in values)
         {
             i.UpdateHash(this);
         }
     }
 }