Exemplo n.º 1
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));
        }
Exemplo n.º 2
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.Exponentiate(beta0Inverse);        // remove the blind that was included in gamma (if no blind beta0Inverse = 1)

            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 sigmaBExponent = alpha[i].Multiply(beta0Inverse);  // will remove the collab-issuance blind, if present

                sigmaZPrime[i] = this.sigmaZ.Exponentiate(alpha[i]);
                sigmaAPrime[i] = t1[i] * message.sigmaA[i];
                sigmaBPrime[i] = Gq.MultiExponentiate(new GroupElement[] { sigmaZPrime[i], h[i], message.sigmaB[i] }, new FieldZqElement[] { beta1[i], beta2[i], sigmaBExponent });
                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));
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
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");
            }
        }
Exemplo n.º 5
0
        internal static FieldZqElement ComputeXt(IssuerParameters ip, byte[] TI, bool supportDevice)
        {
            HashFunction hash = ip.HashFunction;

            hash.Hash((byte)1);
            hash.Hash(ip.Digest(supportDevice));
            hash.Hash(TI);
            return(ip.Zq.GetElementFromDigest(hash.Digest));
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Computes the value x_i.
        /// A field element is computed from an attribute value
        /// </summary>
        /// <param name="ip"> The issuer paramters</param>
        /// <param name="i"> The index of the attribute</param>
        /// <param name="A"> An array contianing the attributes</param>
        /// <returns></returns>
        public static FieldZqElement ComputeXi(IssuerParameters ip, int i, byte[] A)
        {
            FieldZqElement xi;

            if (ip.E[i] == 0x01)            // hash
            {
                if (A == null)
                {
                    xi = ip.Zq.Zero;
                }
                else
                {
                    HashFunction hash = ip.HashFunction;
                    hash.Hash(A);
                    xi = ip.Zq.GetElementFromDigest(hash.Digest);
                }
            }
            else if (ip.E[i] == 0x00)       // do not hash
            {
                if (A == null)
                {
                    throw new ArgumentNullException("A", "A can't be null when ip.E[i] == 0x00");
                }
                else
                {
                    xi = ip.Zq.GetElement(A);
                }
            }
            else
            {
                throw new ArgumentException("invalid E[" + i + "] value");
            }

            return(xi);
        }
Exemplo n.º 8
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");
            }
        }
        public void HashFormattingTest()
        {
            HashFunction hash;

            // byte
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            byte b = 0x01;
            hash.Hash(b);
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_byte).SequenceEqual(hash.Digest), "hash_byte");

            // octet string
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            byte[] octetString = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };
            hash.Hash(octetString);
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_octetstring).SequenceEqual(hash.Digest), "hash_octetstring");

            // null
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            hash.HashNull();
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_null).SequenceEqual(hash.Digest), "hash_null");

            // list
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            hash.Hash(3); // list length
            hash.Hash(b);
            hash.Hash(octetString);
            hash.HashNull();
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_list).SequenceEqual(hash.Digest), "hash_list");

            // subgroup 1.3.6.1.4.1.311.75.1.1.1
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            hash.Hash(SubgroupParameterSets.ParamSetL2048N256V1.Group);
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_subgroup).SequenceEqual(hash.Digest), "hash_subgroup");

            // ec group 1.3.6.1.4.1.311.75.1.2.1
            hash = new HashFunction(TestVectorData.HashVectors.UIDh);
            hash.Hash(ECParameterSets.ParamSet_EC_P256_V1.Group);
            Assert.IsTrue(HexToBytes(TestVectorData.HashVectors.hash_ecgroup).SequenceEqual(hash.Digest), "hash_ecgroup");
        }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
 internal static FieldZqElement GenerateChallengeForDevice(FieldZq zq, HashFunction hash, byte[] md, byte[] mdPrime)
 {
     hash.Hash(md);
     hash.Hash(mdPrime);
     return(zq.GetElementFromDigest(hash.Digest));
 }
Exemplo n.º 12
0
 internal static FieldZqElement GenerateChallengeForDevice(FieldZq zq, HashFunction hash, byte[] md, byte[] mdPrime)
 {
     hash.Hash(md);
     hash.Hash(mdPrime);
     return zq.GetElementFromDigest(hash.Digest);
 }
Exemplo n.º 13
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));
            }
        }
Exemplo n.º 14
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");
            }
        }
Exemplo n.º 15
0
        /// <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);
        }
Exemplo n.º 16
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);

                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");
            }
        }
Exemplo n.º 17
0
 internal static FieldZqElement GenerateChallengeForDevice(FieldZq zq, HashFunction hash, byte[] md, byte[] cp)
 {
     hash.Hash(new byte[][] { cp, md });
     return(zq.GetElementFromDigest(hash.Digest));
 }