Beispiel #1
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;
        }
Beispiel #2
0
        private void Precompute(GroupElement gamma, ProverRandomData pregeneratedRandomData)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (pregeneratedRandomData == null)
            {
                alpha = Zq.GetRandomElements(numberOfTokens, true);
                beta1 = Zq.GetRandomElements(numberOfTokens, false);
                beta2 = Zq.GetRandomElements(numberOfTokens, false);
            }
            else
            {
                alpha = pregeneratedRandomData.Alpha;
                beta1 = pregeneratedRandomData.Beta1;
                beta2 = pregeneratedRandomData.Beta2;
            }
            h    = new GroupElement[numberOfTokens];
            t1   = new GroupElement[numberOfTokens];
            t2   = new GroupElement[numberOfTokens];
            ukat = new UProveKeyAndToken[numberOfTokens];
            for (int i = 0; i < numberOfTokens; i++)
            {
                ukat[i]            = new UProveKeyAndToken();
                h[i]               = gamma.Exponentiate(alpha[i]);
                t1[i]              = ip.G[0].Exponentiate(beta1[i]) * Gq.G.Exponentiate(beta2[i]);
                t2[i]              = h[i].Exponentiate(beta2[i]);
                ukat[i].PrivateKey = alpha[i].Invert();
            }
            state = State.Initialized;
        }
Beispiel #3
0
        private void Precompute(GroupElement gamma, ProverRandomData pregeneratedRandomData)
        {
            Group   Gq = ip.Gq;
            FieldZq Zq = ip.Zq;

            if (pregeneratedRandomData == null)
            {
                alpha = Zq.GetRandomElements(numberOfTokens, true);
                beta1 = Zq.GetRandomElements(numberOfTokens, false);
                beta2 = Zq.GetRandomElements(numberOfTokens, false);
            }
            else
            {
                alpha = pregeneratedRandomData.Alpha;
                beta1 = pregeneratedRandomData.Beta1;
                beta2 = pregeneratedRandomData.Beta2;
            }

            h  = new GroupElement[numberOfTokens];
            t1 = new GroupElement[numberOfTokens];
            // we don't compute t2 in the precomputation since we prefer to
            // compute h^beta2 as part of the sigmaBPrime multi-exponentiation
            ukat = new UProveKeyAndToken[numberOfTokens];
            for (int i = 0; i < numberOfTokens; i++)
            {
                ukat[i]            = new UProveKeyAndToken();
                h[i]               = gamma.Exponentiate(alpha[i].Multiply(beta0Inverse)); // remove collab issuance blind, if present
                t1[i]              = Gq.MultiExponentiate(new GroupElement[] { ip.G[0], Gq.G }, new FieldZqElement[] { beta1[i], beta2[i] });
                ukat[i].PrivateKey = alpha[i].Invert();
            }
            state = State.Initialized;
        }
Beispiel #4
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));
            }
Beispiel #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);
        }
        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>
        /// 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;
        }
            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>
        /// 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);
        }
Beispiel #10
0
        /// <summary>
        /// Create a new pre-issuance proof.
        /// </summary>
        /// <param name="pipp">The prover parameters.</param>
        /// <param name="beta0">The random blinding value used to create the proof, output so that the prover can use it during the issuance protocol</param>
        /// <param name="message">An optional message to sign while creating the proof.</param>
        /// <returns></returns>
        public static PreIssuanceProof CreateProof(ProverPreIssuanceParameters pipp, out FieldZqElement beta0, byte[] message)
        {
            // validate paramters first
            pipp.Validate();

            bool supportDevice = (pipp.DevicePublicKey == null) ? false : true;

            IssuerParameters ip = pipp.IP;
            FieldZq          Zq = ip.Zq;
            Group            Gq = ip.Gq;
            Dictionary <string, FieldZqElement> responses = new Dictionary <string, FieldZqElement>();

            // these will be used if there is a carry-over attribute
            CommitmentPrivateValues cpv       = null;
            PresentationProof       presProof = null;

            GroupElement[]   C      = null;
            GroupElement[]   tildeC = null;
            FieldZqElement[] tildeR = null;

            // extension by Fablei -> needs to calculate the ip.G.Length -> pipp.Attributes.Length + 2
            int ipGLength = pipp.Attributes.Length + 2;

            // Generate random values
            beta0 = Zq.GetRandomElement(true);
            FieldZqElement tildeBeta0 = Zq.GetRandomElement(true);
            FieldZqElement rho        = Zq.GetRandomElement(true);
            FieldZqElement tildeRho   = Zq.GetRandomElement(true);
            FieldZqElement tilde_d    = Zq.GetRandomElement(true);

            FieldZqElement[] tildeX = new FieldZqElement[ipGLength - 1];
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i))
                {
                    tildeX[i] = Zq.GetRandomElement(true);
                }
            }

            // Compute the U-Prove presentation proof, if there are carry-over attributes
            if (pipp.HasCarryOverAttributes)
            {
                // generate the presentation proof
                int[] disclosed = new int[] { };
                ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(pipp.SourceIP, disclosed, message, pipp.KeyAndToken, pipp.SourceAttributes);
                pppp.Committed = pipp.Corig;

                // TODO: What if the source token is device protected?  need to handle this as well. (a pointer to the device should be included in pipp
                //if (device != null)
                //{
                //    pppp.SetDeviceData(deviceMessage, device.GetPresentationContext());
                //}-
                // For now just fail:
                if (pipp.KeyAndToken.Token.IsDeviceProtected)
                {
                    throw new NotImplementedException("Device protected tokens may not be used for carry-over attributes");
                }

                presProof = PresentationProof.Generate(pppp, out cpv);

                //set C
                C = new GroupElement[pipp.C.Length];
                // Generate random values for the commitment randomizers
                tildeR = Zq.GetRandomElements(pipp.C.Length, true);
                tildeC = new GroupElement[C.Length];
                for (int i = 0; i < C.Length; i++)
                {
                    C[i]      = presProof.Commitments[i].TildeC;
                    tildeC[i] = Gq.MultiExponentiate(Gq.G, ip.G[1], tildeX[pipp.C[i]], tildeR[i]);
                }
            }   // end if cary-over attributes

            // Compute gamma
            GroupElement gamma = ProtocolHelper.ComputeIssuanceInput(ip, pipp.Attributes, pipp.TI, pipp.DevicePublicKey);

            // Compute h0, Cgamma, Ch0, tildeD, tildeT:
            GroupElement h0     = gamma.Exponentiate(beta0);
            GroupElement Cgamma = gamma.Multiply(Gq.G.Exponentiate(rho));        // Cgamma = gamma*(g^rho)
            GroupElement Ch0    = Cgamma.Exponentiate(beta0);
            GroupElement tildeD = Gq.G.Exponentiate(tilde_d);

            GroupElement tildeT = Cgamma.Exponentiate(tildeBeta0);

            // Compute tildeCgamma:
            List <GroupElement>   bases     = new List <GroupElement>();
            List <FieldZqElement> exponents = new List <FieldZqElement>();

            bases.Add(Gq.G);
            exponents.Add(tildeRho);
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i))     // i \not\in K
                {
                    bases.Add(ip.G[i]);
                    exponents.Add(tildeX[i]);
                }
            }
            GroupElement tildeCgamma = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // TODO: if device protected, then multiply tildeCgamma by the public key
            // Note: We leave TI out, (i.e., (g_t)^(x_t) because t \in K implicitly.

            // Compute the challenge
            byte[]         c    = ComputeChallenge(ip, h0, Cgamma, Ch0, C, tildeD, tildeCgamma, tildeT, tildeC, message);
            FieldZqElement negc = Zq.GetElementFromDigest(c).Negate();

            // Compute the responses
            responses.Add("sBeta0", tildeBeta0.Add(beta0.Multiply(negc)));          // sBeta0 = tildeBeta0 - beta0*c
            responses.Add("sD", tilde_d.Add(beta0.Multiply(rho).Multiply(negc)));   // sD = tilde_d - beta0*rho*c
            responses.Add("sRho", tildeRho.Add(rho.Multiply(negc)));                // sRho = tildeRho - rho*c

            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!pipp.K.Contains(i)) // in \not\in K
                {
                    FieldZqElement xi = ProtocolHelper.ComputeXi(ip, i - 1, pipp.Attributes[i - 1]);
                    responses.Add("sx" + i, tildeX[i].Add(xi.Multiply(negc)));          // sxi = tildeX[i] - xi*c
                }
            }

            if (pipp.HasCarryOverAttributes)
            {
                for (int i = 0; i < C.Length; i++)
                {
                    responses.Add("sR" + i, tildeR[i].Add(cpv.TildeO[i].Multiply(negc)));      // sRi = tildeR[i] - tildeO[i]*c
                }
            }

            return(new PreIssuanceProof(h0, Cgamma, Ch0, c, responses,
                                        pipp.HasCarryOverAttributes ? presProof : null, pipp.Attributes.Length));
        }
        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");
            }
        }
Beispiel #12
0
 /// <summary>
 /// Returns g^{-1}.
 /// </summary>
 /// <param name="g">Group element to invert.</param>
 /// <returns></returns>
 public GroupElement Invert(GroupElement g)
 {
     return(g.Exponentiate(this.FieldZq.NegativeOne));
 }
Beispiel #13
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;
        }
Beispiel #14
0
 private void Precompute(GroupElement gamma, ProverRandomData pregeneratedRandomData)
 {
     Group Gq = ip.Gq;
     FieldZq Zq = ip.Zq;
     if (pregeneratedRandomData == null)
     {
         alpha = Zq.GetRandomElements(numberOfTokens, true);
         beta1 = Zq.GetRandomElements(numberOfTokens, false);
         beta2 = Zq.GetRandomElements(numberOfTokens, false);
     }
     else
     {
         alpha = pregeneratedRandomData.Alpha;
         beta1 = pregeneratedRandomData.Beta1;
         beta2 = pregeneratedRandomData.Beta2;
     }
     h = new GroupElement[numberOfTokens];
     t1 = new GroupElement[numberOfTokens];
     t2 = new GroupElement[numberOfTokens];
     ukat = new UProveKeyAndToken[numberOfTokens];
     for (int i = 0; i < numberOfTokens; i++)
     {
         ukat[i] = new UProveKeyAndToken();
         h[i] = gamma.Exponentiate(alpha[i]);
         t1[i] = ip.G[0].Exponentiate(beta1[i]) * Gq.G.Exponentiate(beta2[i]);
         t2[i] = h[i].Exponentiate(beta2[i]);
         ukat[i].PrivateKey = alpha[i].Invert();
     }
     state = State.Initialized;
 }