public void TestIEWithSerialized()
        {
            // Does a complete encrypt/decrypt sequence from serialized values.
            // Kind of redundant because each of the testmethods above test serialization
            // of individual data types

            //Serialize and deserialize all objects
            IDEscrowParams     ieParam2 = ip.Deserialize <IDEscrowParams>(ip.Serialize(ieParam));
            IDEscrowPublicKey  pk2      = ip.Deserialize <IDEscrowPublicKey>(ip.Serialize(pk));
            IDEscrowPrivateKey sk2      = ip.Deserialize <IDEscrowPrivateKey>(ip.Serialize(sk));

            // Encrypt
            FieldZq        F    = ip.Zq;
            FieldZqElement xb2  = F.GetRandomElement(true);
            FieldZqElement ob2  = F.GetRandomElement(true);
            GroupElement   Cxb2 = ip.Gq.G.Exponentiate(xb2);  // Cxb = g^xb

            Cxb2 = Cxb2.Multiply(ip.G[1].Exponentiate(ob2));  // Cxb = (g^xb)*(g1^ob)
            GroupElement PE2 = ieParam2.Ge.Exponentiate(xb2);

            IDEscrowCiphertext ctext2 = IDEscrowFunctions.VerifiableEncrypt(ieParam2, pk2, tokenID, Cxb2, xb2, ob2, additionalInfo);

            ctext2 = ip.Deserialize <IDEscrowCiphertext>(ip.Serialize(ctext2));

            // Verify
            bool isValid = IDEscrowFunctions.Verify(ieParam2, ctext2, tokenID, pk2, Cxb2);

            Assert.IsTrue(isValid);

            // Decrypt
            GroupElement PEPrime = IDEscrowFunctions.Decrypt(ieParam2, ctext2, sk2);

            Assert.IsTrue(PE2.Equals(PEPrime));
        }
        public void TestIEEncrypt()
        {
            // Create a commitment and attribute value.
            // Need g, g1, Cxb, xb, ob
            FieldZq        F  = ip.Zq;
            FieldZqElement xb = F.GetRandomElement(true);
            FieldZqElement ob = F.GetRandomElement(true);

            Cxb = ip.Gq.G.Exponentiate(xb);               // Cxb = g^xb
            Cxb = Cxb.Multiply(ip.G[1].Exponentiate(ob)); // Cxb = (g^xb)*(g1^ob)

            // Create the pseudonym (which will be used later to check that decryption is correct)
            PE = ieParam.Ge.Exponentiate(xb);

            // Encrypt
            ctext = IDEscrowFunctions.VerifiableEncrypt(ieParam, pk, tokenID, Cxb, xb, ob, additionalInfo);

            // Serialize
            string ctextStr = ip.Serialize(ctext);

            Assert.IsFalse(ctextStr.Contains(":null"));

            // deserialize and compare
            IDEscrowCiphertext ctext2 = ip.Deserialize <IDEscrowCiphertext>(ctextStr);

            Assert.IsTrue(ctext.Equals(ctext2));
        }
Пример #3
0
 /// <summary>
 /// Generates a <code>IDEscrowProofGenerationRandomData</code> instance using the internal RNG.
 /// </summary>
 /// <param name="Zq">Field Zq</param>
 /// <returns>A pregenerated set of random values.</returns>
 internal static IDEscrowProofGenerationRandomData Generate(FieldZq Zq)
 {
     return(new IDEscrowProofGenerationRandomData(
                Zq.GetRandomElement(false),
                Zq.GetRandomElement(false),
                Zq.GetRandomElement(false),
                Zq.GetRandomElement(false)
                ));
 }
 /// <summary>
 /// Generates a <code>ProofGenerationRandomData</code> instance using the internal RNG.
 /// </summary>
 /// <param name="numUndisclosed">Number of undisclosed attributes.</param>
 /// <param name="numCommitted">Number of committed attributes.</param>
 /// <param name="Zq">Field Zq</param>
 /// <param name="isDeviceProtected">True if a toke is device-protected.</param>
 /// <returns>A pregenerated set of random values.</returns>
 internal static ProofGenerationRandomData Generate(int numUndisclosed, int numCommitted, FieldZq Zq, bool isDeviceProtected)
 {
     return(new ProofGenerationRandomData(
                Zq.GetRandomElement(false),
                Zq.GetRandomElements(numUndisclosed, false),
                isDeviceProtected ? Zq.GetRandomElement(false) : null,
                numCommitted > 0 ? Zq.GetRandomElements(numCommitted, false) : null,
                numCommitted > 0 ? Zq.GetRandomElements(numCommitted, false) : null
                ));
 }
Пример #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);
        }
Пример #6
0
        public ProverSetMembershipParameters GeneratePSMParameters(int indexOfCommittedValue, int memberSetLength)
        {
            if (indexOfCommittedValue >= memberSetLength)
            {
                throw new ArgumentException("indexOfCommittedValue should be less than memberSetLength");
            }

            FieldZq            fieldZq        = FieldZq.CreateFieldZq(_cryptoParameters.Group.Q);
            FieldZqElement     committedValue = fieldZq.GetRandomElement(true);
            PedersenCommitment ped            = new PedersenCommitment(committedValue, _cryptoParameters);

            FieldZqElement[] memberSet = fieldZq.GetRandomElements(memberSetLength, true);
            memberSet[indexOfCommittedValue] = committedValue;

            return(new ProverSetMembershipParameters(ped, memberSet, _cryptoParameters));
        }
        public void EncodingTest()
        {
            // a large value
            byte[] modulus = new byte[] {
                0xef, 0x09, 0x90, 0x06, 0x1d, 0xb6, 0x7a, 0x9e,
                0xae, 0xba, 0x26, 0x5f, 0x1b, 0x8f, 0xa1, 0x2b,
                0x55, 0x33, 0x90, 0xa8, 0x17, 0x5b, 0xcb, 0x3d,
                0x0c, 0x2e, 0x5e, 0xe5, 0xdf, 0xb8, 0x26, 0xe2,
                0x29, 0xad, 0x37, 0x43, 0x11, 0x48, 0xce, 0x31,
                0xf8, 0xb0, 0xe5, 0x31, 0x77, 0x7f, 0x19, 0xc1,
                0xe3, 0x81, 0xc6, 0x23, 0xe6, 0x00, 0xbf, 0xf7,
                0xc5, 0x5a, 0x23, 0xa8, 0xe6, 0x49, 0xcc, 0xbc,
                0xf8, 0x33, 0xf2, 0xdb, 0xa9, 0x9e, 0x6a, 0xd6,
                0x6e, 0x52, 0x37, 0x8e, 0x92, 0xf7, 0x49, 0x2b,
                0x24, 0xff, 0x8c, 0x1e, 0x6f, 0xb1, 0x89, 0xfa,
                0x84, 0x34, 0xf5, 0x40, 0x2f, 0xe4, 0x15, 0x24,
                0x9a, 0xe0, 0x2b, 0xf9, 0x2b, 0x3e, 0xd8, 0xea,
                0xaa, 0xa2, 0x20, 0x2e, 0xc3, 0x41, 0x7b, 0x20,
                0x79, 0xda, 0x4f, 0x35, 0xe9, 0x85, 0xbb, 0x42,
                0xa4, 0x21, 0xcf, 0xab, 0xa8, 0x16, 0x0b, 0x66,
                0x94, 0x99, 0x83, 0x38, 0x4e, 0x56, 0x36, 0x5a,
                0x44, 0x86, 0xc0, 0x46, 0x22, 0x9f, 0xc8, 0xc8,
                0x18, 0xf9, 0x30, 0xb8, 0x0a, 0x60, 0xd6, 0xc2,
                0xc2, 0xe2, 0x0c, 0x5d, 0xf8, 0x80, 0x53, 0x4d,
                0x42, 0x40, 0xd0, 0xd8, 0x1e, 0x9a, 0x37, 0x0e,
                0xef, 0x67, 0x6a, 0x1c, 0x3b, 0x0e, 0xd1, 0xd8,
                0xff, 0x30, 0x34, 0x0a, 0x96, 0xb2, 0x1b, 0x89,
                0xf6, 0x9c, 0x54, 0xce, 0xb8, 0xf3, 0xdf, 0x17,
                0xe3, 0x1b, 0xc2, 0x0c, 0x5b, 0x60, 0x1e, 0x99,
                0x44, 0x45, 0xa1, 0xd3, 0x47, 0xa4, 0x5d, 0x95,
                0xf4, 0x1a, 0xe0, 0x71, 0x76, 0xc7, 0x38, 0x0c,
                0x60, 0xdb, 0x2a, 0xce, 0xdd, 0xee, 0xda, 0x5c,
                0x59, 0x80, 0x96, 0x43, 0x62, 0xe3, 0xa8, 0xdd,
                0x3f, 0x97, 0x3d, 0x6d, 0x4b, 0x24, 0x1b, 0xcf,
                0x91, 0x0c, 0x7f, 0x7a, 0x02, 0xed, 0x3b, 0x60,
                0x38, 0x3a, 0x01, 0x02, 0xd8, 0x06, 0x0c, 0x27
            };

            FieldZq field = FieldZq.CreateFieldZq(modulus);

            for (int i = 0; i < 20; i++)
            {
                FieldZqElement r  = field.GetRandomElement(false);
                FieldZqElement r2 = field.GetElement(r.ToByteArray());
                Assert.AreEqual <FieldZqElement>(r, r2);
            }
        }
        private void RandomElementTest(int fieldSize, bool nonZero, bool checkDistribution)
        {
            byte[] modulusBytes = BitConverter.GetBytes(fieldSize);
            Array.Reverse(modulusBytes); // need big endian
            FieldZq field = FieldZq.CreateFieldZq(modulusBytes);

            Dictionary <FieldZqElement, int> counts = new Dictionary <FieldZqElement, int>();

            int rangeSize = (nonZero) ? fieldSize - 1 : fieldSize;
            int iters     = (checkDistribution) ? 1000 * rangeSize : 5 * rangeSize;

            for (int i = 0; i < iters; i++)
            {
                FieldZqElement el = field.GetRandomElement(nonZero);

                if (counts.ContainsKey(el))
                {
                    int val = counts[el];
                    val++;
                    counts.Remove(el);
                    counts.Add(el, val);
                }
                else
                {
                    counts.Add(el, 1);
                }

                if (nonZero)
                {
                    Assert.AreNotEqual(el, field.Zero);
                }
            }

            double expectedHitRate = 1.0f / (double)rangeSize;
            double errorMargin     = .3 * expectedHitRate;

            foreach (KeyValuePair <FieldZqElement, int> kvp in counts)
            {
                double hitRate = (double)kvp.Value / (double)iters;

                if (Math.Abs(hitRate - expectedHitRate) > errorMargin)
                {
                    Assert.Fail("Random number generator did not produce a good distribution");
                }
            }
        }
        public void BDDecompositionTest()
        {
            FieldZqElement zero;
            FieldZqElement one;
            FieldZqElement two;
            FieldZqElement five;
            FieldZqElement ten;
            BitArray       dec;
            FieldZqElement recompose;

            for (int paramIndex = 0; paramIndex < _parameters.Length; ++paramIndex)
            {
                FieldZq field = _parameters[paramIndex].FieldZq;
                zero = field.Zero;
                one  = field.One;
                two  = field.GetElement(2);
                five = field.GetElement(5);
                ten  = field.GetElement(10);

                dec       = VerifierBitDecompositionParameters.GetBitDecomposition(one, 10, field);
                recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field);
                Assert.AreEqual(one, recompose);
                Assert.AreEqual(true, dec.Get(0), "first bit should be one");
                Assert.AreEqual(false, dec.Get(1), "second  bit should be zero");
                Assert.AreEqual(10, dec.Length, "decomposition length should be 10");

                dec       = VerifierBitDecompositionParameters.GetBitDecomposition(two, 20, field);
                recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field);
                Assert.AreEqual(20, dec.Length, "decomposition length should be 10");
                Assert.AreEqual(two, recompose);
                Assert.AreEqual(false, dec[0], "first bit is 0");
                Assert.AreEqual(true, dec[1], "second bit is 1");
                Assert.AreEqual(false, dec[2], "third bit is 0");
                Assert.AreEqual(false, dec[19], "last bit is 0");

                dec       = VerifierBitDecompositionParameters.GetBitDecomposition(five, 30, field);
                recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field);
                Assert.AreEqual(30, dec.Length, "decomposition length should be 30");
                Assert.AreEqual(five, recompose);
                Assert.AreEqual(true, dec[0], "first bit is 1");
                Assert.AreEqual(false, dec[1], "second bit is 0");
                Assert.AreEqual(true, dec[2], "third bit is 1");
                Assert.AreEqual(false, dec[3], "fourth bit is 0");
                Assert.AreEqual(false, dec[4], "fifth bit is 0");
                Assert.AreEqual(false, dec[29], "last bit is 0");

                dec       = VerifierBitDecompositionParameters.GetBitDecomposition(ten, 30, field);
                recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field);
                Assert.AreEqual(30, dec.Length, "decomposition length should be 30");
                Assert.AreEqual(ten, recompose);
                Assert.AreEqual(false, dec[0], "first bit is 0");
                Assert.AreEqual(true, dec[1], "second bit is 1");
                Assert.AreEqual(false, dec[2], "third bit is 0");
                Assert.AreEqual(true, dec[3], "fourth bit is 1");
                Assert.AreEqual(false, dec[4], "fifth bit is 0");
                Assert.AreEqual(false, dec[29], "last bit is 0");


                FieldZqElement random = field.GetRandomElement(true);
                dec       = VerifierBitDecompositionParameters.GetBitDecomposition(random, 0, field);
                recompose = VerifierBitDecompositionParameters.GetBitComposition(dec, field);
                Assert.AreEqual(random, recompose, "recomposition failed");
            }
        }
 /// <summary>
 /// Generates a <code>SetMembershipProofGenerationRandomData</code> instance using the internal RNG.
 /// </summary>
 /// <param name="Zq">Field Zq.</param>
 /// <param name="length">Desired length of the <c>c</c> and <c>r</c> arrays.</param>
 /// <returns>A pregenerated set of random values.</returns>
 public static SetMembershipProofGenerationRandomData Generate(FieldZq Zq, int length)
 {
     return(new SetMembershipProofGenerationRandomData(Zq.GetRandomElements(length, false), Zq.GetRandomElements(length, false), Zq.GetRandomElement(false)));
 }
Пример #11
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));
        }