private static CommitmentPrivateValues PresentUProveToken(IssuerParameters ip, UProveKeyAndToken upkt, byte[][] attributes, int[] disclosed, int[] committed, byte[] message, byte[] scope, IDevice device, byte[] deviceMessage)
        {
            WriteLine("Presenting one token");
            // the returned commitment randomizer (to be used by an external proof module)
            CommitmentPrivateValues cpv;

            // generate the presentation proof
            string token = ip.Serialize<UProveToken>(upkt.Token);
            ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(ip, disclosed, message, upkt, attributes);
            pppp.Committed = committed;
            // if a scope is defined, we use the first attribute to derive a scope exclusive pseudonym            
            pppp.PseudonymAttributeIndex = (scope == null ? 0 : 1);
            pppp.PseudonymScope = scope;
            if (device != null)
            {
                pppp.SetDeviceData(deviceMessage, device.GetPresentationContext());
            }
            pppp.KeyAndToken = upkt;
            pppp.Attributes = attributes;
            string proof = ip.Serialize<PresentationProof>(PresentationProof.Generate(pppp, out cpv));

            // verify the presentation proof
            VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ip, disclosed, message, ip.Deserialize<UProveToken>(token));
            vppp.Committed = committed;
            // if a scope is defined, we use the first attribute to derive a scope exclusive pseudonym            
            vppp.PseudonymAttributeIndex = (scope == null ? 0 : 1);
            vppp.PseudonymScope = scope;
            vppp.DeviceMessage = deviceMessage;
            ip.Deserialize<PresentationProof>(proof).Verify(vppp);

            return cpv;
        }
        /// <summary>
        /// Verifies a presentation proof.
        /// </summary>
        /// <param name="vppp">The verifier presentation protocol parameters.</param>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public void Verify(VerifierPresentationProtocolParameters vppp)
        {
#pragma warning disable 0618        // this call is deprecated in the public API
            Verify(vppp.IP, vppp.Disclosed, vppp.Committed, vppp.PseudonymAttributeIndex, vppp.PseudonymScopeElement, vppp.Message, vppp.DeviceMessage, vppp.Token);
#pragma warning restore 0618
        }
Exemple #3
0
        // Verifies the pre-issuance proof, and returns the element gamma needed for the token issuance.
        /// <summary>
        /// Verifies a pre-issuance proof and returns the element gamma needed for collaborative issuance.
        /// </summary>
        /// <param name="ipip">The pre-issuance proof parameters for the Issuer</param>
        /// <param name="proof">The proof to be verified</param>
        /// <param name="message">An optional message to be verified (must match the one signed by the prover)</param>
        /// <returns>The group element <c>gamma^beta0</c>, a blinded version of the element gamma used during token issuance.</returns>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public static GroupElement VerifyProof(IssuerPreIssuanceParameters ipip, PreIssuanceProof proof, byte[] message)
        {
            // Validate paramters first
            ipip.Validate();

            // extension by Fablei -> need to know the number of attributes involved in this proof -> ip.G.length
            int ipGLength = proof.na + 2;

            IssuerParameters ip = ipip.IP;
            FieldZq          Zq = ip.Zq;
            Group            Gq = ip.Gq;

            List <GroupElement>   bases     = new List <GroupElement>();
            List <FieldZqElement> exponents = new List <FieldZqElement>();

            GroupElement[] C      = null;
            GroupElement[] CPrime = null;

            FieldZqElement c = Zq.GetElementFromDigest(proof.c);

            if (ipip.HasCarryOverAttributes)
            {
                // validate presentation proof
                int[] disclosed = new int[] {};
                VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ipip.SourceIP, disclosed, message, ipip.Tokens);
                vppp.Committed = ipip.Corig;

                try
                {
                    proof.presentation.Verify(vppp);
                }
                catch (InvalidUProveArtifactException e)
                {
                    throw new InvalidUProveArtifactException("Failed to verify pre-Issuance proof, presentation proof " + 0 + " failed to verify (" + e.ToString() + ")");
                }

                // extract the commitments
                C      = new GroupElement[ipip.C.Length];
                CPrime = new GroupElement[ipip.C.Length];
                for (int i = 0; i < C.Length; i++)
                {
                    C[i] = proof.presentation.Commitments[i].TildeC;

                    // Compute the CPrime[i] values.
                    bases     = new List <GroupElement>();
                    exponents = new List <FieldZqElement>();
                    bases.Add(C[i]);
                    exponents.Add(c);
                    bases.Add(Gq.G);
                    exponents.Add(proof.GetResponse("sx" + ipip.C[i]));
                    bases.Add(ip.G[1]);
                    exponents.Add(proof.GetResponse("sR" + i));
                    CPrime[i] = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());
                    //Debug.WriteLine("CPrime[i] = " + BitConverter.ToString(CPrime[i].GetEncoded()));
                }
            }

            // Compute D'
            FieldZqElement sd     = proof.GetResponse("sD");
            GroupElement   DPrime = Gq.MultiExponentiate(proof.Ch0, proof.h0, c, c.Negate()); // TODO: add Inverse() to group element to simplify this

            DPrime = DPrime.Multiply(Gq.G.Exponentiate(sd));
            //Debug.WriteLine("DPrime = " + BitConverter.ToString(DPrime.GetEncoded()));

            // Compute T'
            FieldZqElement sBeta0 = proof.GetResponse("sBeta0");
            GroupElement   TPrime = Gq.MultiExponentiate(proof.Ch0, proof.CGamma, c, sBeta0);

            //Debug.WriteLine("TPrime = " + BitConverter.ToString(TPrime.GetEncoded()));

            // Compute gammaK (product of known attributes)
            bases     = new List <GroupElement>();
            exponents = new List <FieldZqElement>();
            //int t = ip.G.Length-1;
            // extension by Fablei
            int            t  = ipGLength - 1;
            FieldZqElement xt = ProtocolHelper.ComputeXt(ip, ipip.TI, ipip.DeviceProtected);

            bases.Add(ip.G[0]);
            exponents.Add(ip.Zq.One);
            bases.Add(ip.G[t]);
            exponents.Add(xt);  // gammaK = g0*(gt^xt)
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (ipip.K.Contains(i))
                {
                    FieldZqElement xi = ProtocolHelper.ComputeXi(ip, i - 1, ipip.Attributes[i - 1]);
                    bases.Add(ip.G[i]);
                    exponents.Add(xi);
                }
            }
            GroupElement gammaK = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // Compute Cgamma'
            bases     = new List <GroupElement>();
            exponents = new List <FieldZqElement>();
            bases.Add(proof.CGamma);
            exponents.Add(c);
            bases.Add(gammaK);
            exponents.Add(c.Negate());  // TODO: do with one exp; i.e., (CGamma/gammaK)^c
            for (int i = 1; i < ipGLength - 1; i++)
            {
                if (!ipip.K.Contains(i))
                {
                    FieldZqElement sxi = proof.GetResponse("sx" + i);
                    bases.Add(ip.G[i]);
                    exponents.Add(sxi);
                }
            }
            bases.Add(Gq.G);
            exponents.Add(proof.GetResponse("sRho"));
            GroupElement CgammaPrime = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());

            // TODO: if deviceprotected multiply device base/response.
            //Debug.WriteLine("CgammaPrime = " + BitConverter.ToString(CgammaPrime.GetEncoded()));

            // Recompute challenge
            byte[] cPrime = ComputeChallenge(ip, proof.h0, proof.CGamma, proof.Ch0, C, DPrime, CgammaPrime, TPrime, CPrime, message);
            //Debug.WriteLine("c' = " + BitConverter.ToString(cPrime));

            if (!cPrime.SequenceEqual <byte>(proof.c))
            {
                throw new InvalidUProveArtifactException("invalid proof");
            }

            return(proof.h0);
        }
        /// <summary>
        /// Verifies a presentation proof.
        /// </summary>
        /// <param name="vppp">The verifier presentation protocol parameters.</param>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public void Verify(VerifierPresentationProtocolParameters vppp)
        {
#pragma warning disable 0618        // this call is deprecated in the public API
            Verify(vppp.IP, vppp.Disclosed, vppp.Committed, vppp.PseudonymAttributeIndex, vppp.PseudonymScopeElement, vppp.Message, vppp.DeviceMessage, vppp.Token);
#pragma warning restore 0618
        }
        public void ProtocolTest()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            bool[] bools = new bool[] { true, false };
            foreach (bool isSubgroupConstruction in bools)
            {
                foreach (bool supportDevice in bools)
                {
                    var vectors =
                        supportDevice ?
                        (isSubgroupConstruction ?
                            GetTestVectors("testvectorssubgroup_Device_doc.txt")
                            :
                            GetTestVectors("testvectorsEC_Device_doc.txt"))
                        :
                        (isSubgroupConstruction ?
                            GetTestVectors("testvectorssubgroup_doc.txt")
                            :
                            GetTestVectors("testvectorsEC_doc.txt"));

                    IssuerKeyAndParameters ikap = LoadIssuerKeyAndParameters(isSubgroupConstruction, vectors["GroupName"], supportDevice, vectors);
                    FieldZq Zq = ikap.IssuerParameters.Zq;
                    // replace random y0/g0 with test vector values
                    ikap.PrivateKey = Zq.GetElement(HexToBytes(vectors["y0"]));
                    ikap.IssuerParameters.G[0] = CreateGroupElement(ikap.IssuerParameters.Gq, vectors["g0"]);
                    Assert.AreEqual(ikap.IssuerParameters.G[0], ikap.IssuerParameters.Gq.G.Exponentiate(ikap.PrivateKey), "g0 computation");
                    IssuerParameters ip = ikap.IssuerParameters;
                    ip.Verify();

                    /*
                     * issuance
                     */

                    byte[][] A = new byte[][] {
                        HexToBytes(vectors["A1"]), 
                        HexToBytes(vectors["A2"]),
                        HexToBytes(vectors["A3"]),
                        HexToBytes(vectors["A4"]),
                        HexToBytes(vectors["A5"])
                        };

                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x1"])), ProtocolHelper.ComputeXi(ip, 0, A[0]), "x1");
                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x2"])), ProtocolHelper.ComputeXi(ip, 1, A[1]), "x2");
                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x3"])), ProtocolHelper.ComputeXi(ip, 2, A[2]), "x3");
                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x4"])), ProtocolHelper.ComputeXi(ip, 3, A[3]), "x4");
                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["x5"])), ProtocolHelper.ComputeXi(ip, 4, A[4]), "x5");

                    byte[] TI = HexToBytes(vectors["TI"]);
                    Assert.IsTrue(HexToBytes(vectors["P"]).SequenceEqual(ip.Digest(supportDevice)), "P");
                    Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["xt"])), ProtocolHelper.ComputeXt(ip, TI, supportDevice), "xt");

                    IDevice device = null;
                    GroupElement hd = null;
                    if (supportDevice)
                    {
                        device = new VirtualDevice(ip, Zq.GetElement(HexToBytes(vectors["xd"])), Zq.GetElement(HexToBytes(vectors["wdPrime"])));
                        IDevicePresentationContext context = device.GetPresentationContext();
                        // Test device responses
                        Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["hd"]), device.GetDevicePublicKey(), "hd");
                        Assert.AreEqual(CreateGroupElement(ip.Gq, vectors["ad"]), context.GetInitialWitness(), "ad");
                        Assert.AreEqual(Zq.GetElement(HexToBytes(vectors["rdPrime"])), context.GetDeviceResponse(HexToBytes(vectors["md"]), HexToBytes(vectors["mdPrime"]), ip.HashFunctionOID), "rdPrime");
                        hd = CreateGroupElement(ip.Gq, vectors["hd"]);
                    }

                    IssuerProtocolParameters ipp = new IssuerProtocolParameters(ikap);
                    ipp.Attributes = A;
                    ipp.NumberOfTokens = 1;
                    ipp.TokenInformation = TI;
                    ipp.DevicePublicKey = hd;
                    ipp.PreGeneratedW = new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["w"])) };
                    Issuer issuer = ipp.CreateIssuer();
                    byte[] PI = HexToBytes(vectors["PI"]);

                    ProverProtocolParameters ppp = new ProverProtocolParameters(ip);
                    ppp.Attributes = A;
                    ppp.NumberOfTokens = 1;
                    ppp.TokenInformation = TI;
                    ppp.ProverInformation = PI;
                    ppp.DevicePublicKey = hd;
                    ppp.ProverRandomData = new ProverRandomData(
                        new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["alpha"])) },
                        new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta1"])) },
                        new FieldZqElement[] { Zq.GetElement(HexToBytes(vectors["beta2"])) });
                    Prover prover = ppp.CreateProver();

                    FirstIssuanceMessage msg1 = issuer.GenerateFirstMessage();
                    Assert.AreEqual(msg1.sigmaZ, CreateGroupElement(ip.Gq, vectors["sigmaZ"]), "sigmaZ");
                    Assert.AreEqual(msg1.sigmaA[0], CreateGroupElement(ip.Gq, vectors["sigmaA"]), "sigmaA");
                    Assert.AreEqual(msg1.sigmaB[0], CreateGroupElement(ip.Gq, vectors["sigmaB"]), "sigmaB");

                    SecondIssuanceMessage msg2 = prover.GenerateSecondMessage(msg1);
                    Assert.AreEqual(msg2.sigmaC[0], Zq.GetElement(HexToBytes(vectors["sigmaC"])), "sigmaC");

                    ThirdIssuanceMessage msg3 = issuer.GenerateThirdMessage(msg2);
                    Assert.AreEqual(msg3.sigmaR[0], Zq.GetElement(HexToBytes(vectors["sigmaR"])), "sigmaR");

                    UProveKeyAndToken[] upkt = prover.GenerateTokens(msg3);
                    Assert.AreEqual(upkt[0].PrivateKey, Zq.GetElement(HexToBytes(vectors["alphaInverse"])), "alphaInverse");
                    UProveToken token = upkt[0].Token;
                    Assert.AreEqual(token.H, CreateGroupElement(ip.Gq, vectors["h"]), "h");
                    Assert.AreEqual(token.SigmaZPrime, CreateGroupElement(ip.Gq, vectors["sigmaZPrime"]), "sigmaZPrime");
                    Assert.AreEqual(token.SigmaCPrime, Zq.GetElement(HexToBytes(vectors["sigmaCPrime"])), "sigmaCPrime");
                    Assert.AreEqual(token.SigmaRPrime, Zq.GetElement(HexToBytes(vectors["sigmaRPrime"])), "sigmaRPrime");
                    Assert.IsTrue(HexToBytes(vectors["UIDt"]).SequenceEqual(ProtocolHelper.ComputeTokenID(ip, token)), "UIDt");
                    Assert.IsTrue(supportDevice == token.IsDeviceProtected);

                    /*
                     * presentation
                     */

                    int[] disclosed = Array.ConvertAll<string, int>(vectors["D"].Split(','), new Converter<string, int>(stringToInt));
                    int[] committed = Array.ConvertAll<string, int>(vectors["C"].Split(','), new Converter<string, int>(stringToInt));
                    byte[] m = HexToBytes(vectors["m"]);
                    byte[] md = null;
                    IDevicePresentationContext deviceContext = null;
                    if (supportDevice)
                    {
                        md = HexToBytes(vectors["md"]);
                        deviceContext = device.GetPresentationContext();
                    }
                    int p;
                    if (!int.TryParse(vectors["p"], out p))
                    {
                        p = PresentationProof.DeviceAttributeIndex;
                    }
                    byte[] s = HexToBytes(vectors["s"]);
                    int commitmentIndex = committed[0];
                    ProverPresentationProtocolParameters pppp = new ProverPresentationProtocolParameters(ip, disclosed, m, upkt[0], A);
                    pppp.Committed = committed;
                    pppp.PseudonymAttributeIndex = p;
                    pppp.PseudonymScope = s;
                    pppp.DeviceMessage = md;
                    pppp.DeviceContext = deviceContext;
                    pppp.RandomData = new ProofGenerationRandomData(
                            Zq.GetElement(HexToBytes(vectors["w0"])),
                            new FieldZqElement[] { 
                                Zq.GetElement(HexToBytes(vectors["w1"])), 
                                Zq.GetElement(HexToBytes(vectors["w3"])),
                                Zq.GetElement(HexToBytes(vectors["w4"]))
                            },
                            supportDevice ? Zq.GetElement(HexToBytes(vectors["wd"])) : null,
                            new FieldZqElement[] { 
                                Zq.GetElement(HexToBytes(vectors["tildeO" + commitmentIndex])), 
                            },
                            new FieldZqElement[] { 
                                Zq.GetElement(HexToBytes(vectors["tildeW" + commitmentIndex]))
                            });
                    CommitmentPrivateValues cpv;
                    PresentationProof proof = PresentationProof.Generate(pppp, out cpv);
                    Assert.IsTrue(HexToBytes(vectors["a"]).SequenceEqual(proof.A), "a");
                    Assert.AreEqual(ProtocolHelper.GenerateScopeElement(ip.Gq, s), CreateGroupElement(ip.Gq, vectors["gs"]));
                    Assert.IsTrue(HexToBytes(vectors["ap"]).SequenceEqual(proof.Ap), "ap");
                    Assert.AreEqual(proof.Ps, CreateGroupElement(ip.Gq, vectors["Ps"]), "Ps");
                    Assert.IsTrue(HexToBytes(vectors["A2"]).SequenceEqual(proof.DisclosedAttributes[0]), "A2");
                    Assert.IsTrue(HexToBytes(vectors["A5"]).SequenceEqual(proof.DisclosedAttributes[1]), "A5");
                    Assert.AreEqual(proof.R[0], Zq.GetElement(HexToBytes(vectors["r0"])), "r0");
                    Assert.AreEqual(proof.R[1], Zq.GetElement(HexToBytes(vectors["r1"])), "r1");
                    Assert.AreEqual(proof.R[2], Zq.GetElement(HexToBytes(vectors["r3"])), "r3");
                    Assert.AreEqual(proof.R[3], Zq.GetElement(HexToBytes(vectors["r4"])), "r4");
                    if (supportDevice)
                    {
                        Assert.AreEqual(proof.R[4], Zq.GetElement(HexToBytes(vectors["rd"])), "rd");
                    }
                    Assert.AreEqual(proof.Commitments[0].TildeR, Zq.GetElement(HexToBytes(vectors["tildeR" + commitmentIndex])), "tildeR" + commitmentIndex);
                    Assert.IsTrue(cpv.TildeO.Length == 1);
                    Assert.AreEqual(cpv.TildeO[0], Zq.GetElement(HexToBytes(vectors["tildeO" + commitmentIndex])), "tildeO" + commitmentIndex);
                    VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ip, disclosed, m, upkt[0].Token);
                    vppp.Committed = committed;
                    vppp.PseudonymAttributeIndex = p;
                    vppp.PseudonymScope = s;
                    vppp.DeviceMessage = md;
                    proof.Verify(vppp);

                }
            }

            sw.Stop();
            Debug.WriteLine("Protocol Test Elapsed Time: " + sw.ElapsedMilliseconds + "ms");
        }