Exemplo n.º 1
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;
        }
        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));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Computes the revocation witness for a specific user attribute.
        /// </summary>
        /// <param name="revoked">Set of revoked values.</param>
        /// <param name="xid">The user attribute.</param>
        /// <returns>A revocation witness.</returns>
        public RevocationWitness ComputeRevocationWitness(HashSet <FieldZqElement> revoked, FieldZqElement xid)
        {
            if (revoked.Contains(xid))
            {
                throw new ArgumentException("xid cannot be in revoked set");
            }
            Group          Gq             = RAParameters.group;
            FieldZq        Zq             = Gq.FieldZq;
            FieldZqElement d              = Zq.One;
            FieldZqElement deltaPlusXProd = Zq.One;

            foreach (var x in revoked)
            {
                if (x + this.PrivateKey == Zq.Zero)
                {
                    throw new ArgumentException("revocationList cannot contain the negation of the private key");
                }
                d *= (x - xid);
                deltaPlusXProd *= (this.PrivateKey + x);
            }

            GroupElement W = RAParameters.gt.Exponentiate((deltaPlusXProd - d) * (PrivateKey + xid).Invert());
            GroupElement Q = Gq.MultiExponentiate(new GroupElement[] { Accumulator, W, RAParameters.gt }, new FieldZqElement[] { Zq.One, xid.Negate(), d.Negate() });

            return(new RevocationWitness(d, W, Q));
        }
Exemplo n.º 5
0
        public void MultiExponentiateTest()
        {
            // make sure test works with both subgroup and ECC
            string[] groupOIDs = { SubgroupParameterSets.ParamSet_SG_2048256_V1Name, ECParameterSets.ParamSet_EC_P256_V1Name };
            foreach (string groupOID in groupOIDs)
            {
                ParameterSet set;
                ParameterSet.TryGetNamedParameterSet(groupOID, out set);

                Group          Gq     = set.Group;
                FieldZq        Zq     = FieldZq.CreateFieldZq(Gq.Q);
                int            length = 10;
                GroupElement[] bases  = new GroupElement[length];
                System.Array.Copy(set.G, bases, length);
                FieldZqElement[] exponents = Zq.GetRandomElements(length, false);

                GroupElement value = Gq.Identity;
                for (int i = 0; i < length; i++)
                {
                    value = value * bases[i].Exponentiate(exponents[i]);
                }

                Assert.AreEqual(value, Gq.MultiExponentiate(bases, exponents));
            }
        }
Exemplo n.º 6
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.º 7
0
        /// <summary>
        /// Generates the third issuance message.
        /// </summary>
        /// <param name="message">The second issuance message.</param>
        /// <returnn>The third issuance message.</returnn>
        public ThirdIssuanceMessage GenerateThirdMessage(SecondIssuanceMessage message)
        {
            if (state != State.First)
            {
                throw new InvalidOperationException("GenerateFirstMessage must be called first");
            }

            if (message.sigmaC.Length != numberOfTokens)
            {
                throw new ArgumentException("invalid sigmaC array length");
            }

            FieldZqElement[] sigmaR = new FieldZqElement[message.sigmaC.Length];
            Group            Gq     = ikap.IssuerParameters.Gq;
            FieldZq          Zq     = ikap.IssuerParameters.Zq;

            for (int i = 0; i < message.sigmaC.Length; i++)
            {
                sigmaR[i] = message.sigmaC[i] * ikap.PrivateKey + w[i];
                w[i]      = Zq.Zero;
            }
            w     = null;
            state = State.Third;
            return(new ThirdIssuanceMessage(sigmaR));
        }
Exemplo n.º 8
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;
        }
Exemplo n.º 9
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;
        }
Exemplo n.º 10
0
 /// <summary>
 /// Takes as input a series of commitments to 0 and 1, and composes them into a single Pedersen commitment:
 /// output.CommittedValue = product (2^i * committedBits[i].CommittedValue)
 /// </summary>
 /// <param name="committedBits">Array of commitments to Zero and One. Each commitment must use the same bases G and H.</param>
 /// <param name="fieldZq">Field corresponding to all PedersenCommitments</param>
 /// <param name="composition">Output paramter.</param>
 /// <returns>True on success, false on failure.</returns>
 private static bool ComposeCommitments(PedersenCommitment[] committedBits, FieldZq fieldZq, out PedersenCommitment composition)
 {
     try
     {
         FieldZqElement        two               = fieldZq.GetElement(2);
         FieldZqElement        powerOfTwo        = fieldZq.One;
         DLRepOfGroupElement[] bitsExpPowerOfTwo = new DLRepOfGroupElement[committedBits.Length];
         for (int i = 0; i < committedBits.Length; ++i)
         {
             bitsExpPowerOfTwo[i] = committedBits[i].Exponentiate(powerOfTwo);
             powerOfTwo           = powerOfTwo * two;
         }
         DLRepOfGroupElement actualComposition;
         bool success = DLRepOfGroupElement.TryStrictMultiply(bitsExpPowerOfTwo, out actualComposition);
         if (success)
         {
             composition = new PedersenCommitment(actualComposition);
             return(true);
         }
     }
     catch (Exception)
     {
         // do nothing
     }
     composition = null;
     return(false);
 }
Exemplo n.º 11
0
        public void FieldZqTest()
        {
            Group   group  = SubgroupParameterSets.ParamSetL2048N256V1.Group;
            FieldZq field1 = group.FieldZq;
            FieldZq field2 = group.FieldZq;

            Assert.ReferenceEquals(field1, field2);
        }
Exemplo n.º 12
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)
                ));
 }
Exemplo n.º 13
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[]   batchAccBases = new GroupElement[numberOfTokens];
            FieldZqElement[] s             = null;
            if (!skipTokenValidation)
            {
                s = Zq.GetRandomElements(numberOfTokens, true, batchValidationSecurityLevel);
            }
            for (int i = 0; i < numberOfTokens; i++)
            {
                sigmaRPrime[i] = message.sigmaR[i] + beta2[i];
                if (doBatchValidation)
                {
                    phoAR           += (s[i] * alpha[i] * sigmaRPrime[i]);
                    phoR            += (s[i] * sigmaRPrime[i]);
                    phoAC           += (s[i] * alpha[i] * sigmaCPrime[i]);
                    phoC            += (s[i] * sigmaCPrime[i]);
                    batchAccBases[i] = sigmaAPrime[i] * sigmaBPrime[i];
                }
                else if (doNormalValidation)
                {
                    if (!(sigmaAPrime[i] * sigmaBPrime[i]).Equals(
                            Gq.MultiExponentiate(new GroupElement[] { Gq.G *h[i], ip.G[0] * sigmaZPrime[i] },
                                                 new FieldZqElement[] { sigmaRPrime[i], 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 &&
                (Gq.MultiExponentiate(batchAccBases, s) !=
                 Gq.MultiExponentiate(new GroupElement[] { Gq.G, gamma, ip.G[0], sigmaZ },
                                      new FieldZqElement[] { phoR, phoAR, phoC.Negate(), phoAC.Negate() })))      // TODO: batch validation with blinded gamma needs to multiply beta0inverse to phoAR
            {
                throw new InvalidUProveArtifactException("Invalid token signature");
            }

            state = State.Tokens;
            return(ukat);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Create a verifiable encryption of a pseudonym.  The output IECiphertext
        /// object will contain the ciphertext and proof that it was formed correctly.
        /// The pseudonym that is encrypted is (param.Ge)^(x_b), where x_b is an attribute
        /// from the token.
        /// </summary>
        /// <param name="param"> Paramters of the ID escrow scheme.</param>
        /// <param name="pk"> Public key of the Auditor (the authority who can decrypt the output ciphertex).</param>
        /// <param name="tokenID"> The ID of the U-Prove token this ciphertext is assocaited with.</param>
        /// <param name="Cxb"> The commitment value (commitment to x_b, with bases g, g1).</param>
        /// <param name="x_b"> The attributed commited to by <c>Cxb</c></param>
        /// <param name="o_b"> The randomizer value used to create <c>Cxb</c></param>
        /// <param name="additionalInfo"> Arbitrary data that will be cryptographically bound to the ciphertext,
        ///   but <b>NOT</b> encrypted, and will be included with the output ciphertext.
        ///   The integrity of the <c>additionalInfo</c> is protected, i.e., modifying
        ///   the <c>additionalInfo</c> included in the ciphertext will cause verification/decryption to fail.
        ///   The <c>additionalInfo</c> field is sometimes referred to in the cryptographic literature
        ///   as a <i>label</i>. </param>
        /// <param name="preGenRandom">Optional pre-generated random values to be used in the protocol.
        /// Set to <c>null</c> if unused.  The primary use of this field is for testing with test vectors.</param>
        /// <returns>An <c>IECiphertext</c> object with the ciphertext and proof.</returns>
        /// <remarks>
        /// The additionalInfo field may be null to signify that there is no input, all other input
        /// paramters must be non-null.
        ///
        /// Input validation is limited to checking for non-null. We assume that all group & field elements are consistent
        /// with the parameters specified by the IdEscrowParams.
        /// </remarks>
        public static IDEscrowCiphertext VerifiableEncrypt(IDEscrowParams param, IDEscrowPublicKey pk, byte[] tokenID, GroupElement Cxb,
                                                           FieldZqElement x_b, FieldZqElement o_b, byte[] additionalInfo, IDEscrowProofGenerationRandomData preGenRandom = null)
        {
            // Notation & numbering follows draft spec -- subject to change.
            GroupElement g  = param.ip.Gq.G; // first base for commitment Cxb
            GroupElement g1 = param.ip.G[1]; // second base for Cxb

            if (param == null || pk == null || tokenID == null || Cxb == null || g == null || g1 == null || x_b == null || o_b == null)
            {
                throw new ArgumentNullException("Null input to VerifiableEncrypt");
            }
            if (tokenID.Length == 0)
            {
                throw new ArgumentOutOfRangeException("tokenID has length 0");
            }

            Group   G = param.G;
            FieldZq F = param.Zq;

            if (preGenRandom == null || preGenRandom.HasNullValue())
            {
                preGenRandom = IDEscrowProofGenerationRandomData.Generate(F);
            }

            // [1.] Encrypt
            // Compute E1
            FieldZqElement r  = preGenRandom.R;
            GroupElement   E1 = param.Ge.Exponentiate(r);       // E1 = (g_e)^r

            // Compute E2 = (g_e)^x_b * H^r
            GroupElement E2 = G.MultiExponentiate(new GroupElement[] { pk.H, param.Ge }, new FieldZqElement[] { r, x_b });

            // [2.] Generate proof of correctness
            // [2.a]
            FieldZqElement xbPrime = preGenRandom.XbPrime;
            FieldZqElement rPrime  = preGenRandom.RPrime;
            FieldZqElement obPrime = preGenRandom.ObPrime;

            // [2.b]
            GroupElement CxbPrime = G.MultiExponentiate(new GroupElement[] { g, g1 }, new FieldZqElement[] { xbPrime, obPrime });         // Cxb' = (g^xb')*(g1^ob')
            GroupElement E1Prime  = param.Ge.Exponentiate(rPrime);                                                                        // E1' = (ge)^r'
            GroupElement E2Prime  = G.MultiExponentiate(new GroupElement[] { param.Ge, pk.H }, new FieldZqElement[] { xbPrime, rPrime }); // E2' = ((g_e)^xb')*(H^r')

            // [2.c]
            FieldZqElement c = ComputeChallenge(param.ip, tokenID, pk, Cxb, E1, E2, CxbPrime, E1Prime, E2Prime, additionalInfo);

            // [2.d]
            FieldZqElement rXb = ComputeResponse(xbPrime, c, x_b);
            FieldZqElement rR  = ComputeResponse(rPrime, c, r);
            FieldZqElement rOb = ComputeResponse(obPrime, c, o_b);

            IDEscrowProof      proof = new IDEscrowProof(c, rXb, rR, rOb);
            IDEscrowCiphertext ctext = new IDEscrowCiphertext(E1, E2, proof, additionalInfo);

            return(ctext);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Verifies that an <c>IECiphertext</c> was computed correctly.
        /// </summary>
        /// <param name="param">Paramters of the ID escrow scheme.</param>
        /// <param name="ctext"> A ciphertext created with <c>param</c> and <c>pk</c>.</param>
        /// <param name="tokenID">The ID of the U-Prove token this ciphertext is assocaited with.</param>
        /// <param name="pk">Public key of the Auditor (the authority who can decrypt <c>ctext</c>).</param>
        /// <param name="Cxb"> The commitment value (commitment to x_b, with bases g, g1).</param>
        /// <returns><c>true</c> if the ciphertext is valid, and <c>false</c> otherwise.</returns>
        /// <remarks>
        /// The input <c>pk</c> is assumed to be valid, coming from a
        /// trusted source (e.g., a certificate or a trusted store of parameters), and that they
        /// are consistent with the group specified by <c>param</c>.
        /// </remarks>
        public static bool Verify(IDEscrowParams param, IDEscrowCiphertext ctext, byte[] tokenID, IDEscrowPublicKey pk, GroupElement Cxb)
        {
            GroupElement g  = param.ip.Gq.G;   // first base for commitment
            GroupElement g1 = param.ip.G[1];   // second base for commitment

            if (param == null || ctext == null || tokenID == null || pk == null || Cxb == null || g == null || g1 == null)
            {
                throw new ArgumentNullException("null input to Verify");
            }
            if (tokenID.Length == 0)
            {
                throw new ArgumentOutOfRangeException("tokenID has length 0");
            }

            Group         G     = param.ip.Gq;
            FieldZq       F     = param.Zq;
            IDEscrowProof proof = ctext.proof;

            // [1.]Checks on inputs.  These should be done during deserialization -- but we do
            // them explicitly anyway, in case they were missed
            if (!IsGroupElement(G, ctext.E1) || !IsGroupElement(G, ctext.E2) || !IsGroupElement(G, Cxb))
            {
                return(false);
            }

            if (!F.IsElement(proof.c) || !F.IsElement(proof.rOb) ||
                !F.IsElement(proof.rR) || !F.IsElement(proof.rXb))
            {
                return(false);
            }

            // [2.] Recompute inputs to hash (using tilde{x} instead of x'' for this section.)
            GroupElement tildeCxb = G.MultiExponentiate(
                new GroupElement[] { g, g1, Cxb },
                new FieldZqElement[] { proof.rXb, proof.rOb, proof.c }); // tildeCxb = (g^rXb)*(g1^rOb)*(Cxb^c)


            GroupElement tildeE1 = G.MultiExponentiate(
                new GroupElement[] { param.Ge, ctext.E1 },
                new FieldZqElement[] { proof.rR, proof.c }); // tildeE1 = (E1^c)*(ge^rR)

            GroupElement tildeE2 = G.MultiExponentiate(
                new GroupElement[] { param.Ge, pk.H, ctext.E2 },
                new FieldZqElement[] { proof.rXb, proof.rR, proof.c }); // tildeE2 = (ge^rXb)*(H^rR)*(E2^c)

            // [3.]
            FieldZqElement cPrime = ComputeChallenge(param.ip, tokenID, pk, Cxb, ctext.E1, ctext.E2, tildeCxb, tildeE1, tildeE2, ctext.additionalInfo);

            // [4.]
            if (cPrime.Equals(proof.c))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 16
0
 internal void OnDeserialized(StreamingContext context)
 {
     // begin by deserializing the algebra context
     if (_group == null)
     {
         throw new SerializationException("_group cannot be null.");
     }
     this.Group   = _group.ToGroup();
     this.FieldZq = FieldZq.CreateFieldZq(this.Group.Q);
 }
Exemplo n.º 17
0
        public void NegateTest()
        {
            FieldZq Zq = FieldZq.CreateFieldZq(new byte[] { 0x05 });

            Assert.AreEqual <FieldZqElement>(Zq.Zero.Negate(), Zq.Zero);
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(1).Negate(), Zq.GetElement(4));
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(2).Negate(), Zq.GetElement(3));
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(3).Negate(), Zq.GetElement(2));
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(4).Negate(), Zq.GetElement(1));
        }
Exemplo n.º 18
0
        public void NegativeOneTest()
        {
            FieldZq        Zq     = FieldZq.CreateFieldZq(new byte[] { 0x05 });
            FieldZqElement negone = Zq.NegativeOne;

            Assert.AreEqual <FieldZqElement>(Zq.One.Negate(), negone, "test first time.");

            FieldZqElement negoneAgain = Zq.NegativeOne;

            Assert.ReferenceEquals(negone, negoneAgain);
            Assert.AreEqual(Zq.One.Negate(), negoneAgain, "negone again");
        }
Exemplo n.º 19
0
 /// <summary>
 /// Convert a base64 string to a FieldElement.
 /// </summary>
 /// <param name="encodedString">The encoded string to convert.</param>
 /// <param name="Zq">The FieldZq object to which the encoded element belongs.</param>
 /// <returns>The converted object.</returns>
 public static FieldZqElement ToFieldZqElement(this String encodedString, FieldZq Zq)
 {
     if (encodedString == null)
     {
         return(null);
     }
     if (Zq == null)
     {
         throw new ArgumentNullException("Zq");
     }
     return(Zq.GetElement(Convert.FromBase64String(encodedString)));
 }
Exemplo n.º 20
0
 /// <summary>
 /// Private constructor - takes and sets all fields.
 /// </summary>
 /// <param name="Gq">The group</param>
 /// <param name="gd">The device generator</param>
 /// <param name="Zq">The Field associated to the group <c>Gq</c></param>
 /// <param name="xd">The xd.</param>
 /// <param name="preGenWdPrime">The pre gen wd prime.</param>
 VirtualDevice(Group Gq, GroupElement gd, FieldZq Zq, FieldZqElement xd, FieldZqElement preGenWdPrime)
 {
     if (xd != null && !Zq.IsElement(xd))
     {
         throw new ArgumentException("xd is not a valid Zq element");
     }
     this.Gd      = gd;
     this.Gq      = Gq;
     this.Zq      = Zq;
     this.xd      = xd ?? this.Zq.GetRandomElement(true); // assign xd a random value if null
     this.wdPrime = preGenWdPrime;
     this.hd      = this.Gd.Exponentiate(this.xd);
 }
Exemplo n.º 21
0
        /// <summary>
        /// Verifies a non-revocation proof.
        /// </summary>
        /// <param name="ip">The issuer parameters associated with the proof.</param>
        /// <param name="revocationCommitmentIndex">The 0-based index corresponding to the revocation commitment in the proof.</param>
        /// <param name="proof">The presentation proof.</param>
        /// <param name="nrProof">The non-revocation proof.</param>
        /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception>
        public void VerifyNonRevocationProof(IssuerParameters ip, int revocationCommitmentIndex, PresentationProof proof, NonRevocationProof nrProof)
        {
            Group        Gq       = ip.Gq;
            FieldZq      Zq       = Gq.FieldZq;
            GroupElement tildeCid = proof.Commitments[revocationCommitmentIndex].TildeC;
            // T1 = (V Y^-1 Cd^-1)^c' * X^s1 * (tildeCid K)^-s2 * g1^s3
            GroupElement T1 = Gq.MultiExponentiate(
                new GroupElement[] {
                Accumulator *nrProof.Y.Exponentiate(Zq.NegativeOne) * nrProof.Cd.Exponentiate(Zq.NegativeOne),      // TODO: is there a better way to calculate this
                nrProof.X,
                tildeCid * RAParameters.K,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[0],          // s1
                nrProof.s[1].Negate(), // s2
                nrProof.s[2]           // s3
            });
            // T2 = tildeCid^c' g^s1 g1^s4
            GroupElement T2 = Gq.MultiExponentiate(
                new GroupElement[] {
                tildeCid,
                RAParameters.g,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[0],     // s1
                nrProof.s[3],     // s4
            });
            // T3 = gt^c' Cd^s5 g1^s6
            GroupElement T3 = Gq.MultiExponentiate(
                new GroupElement[] {
                RAParameters.gt,
                nrProof.Cd,
                RAParameters.g1
            },
                new FieldZqElement[] {
                nrProof.cPrime,
                nrProof.s[4],     // s5
                nrProof.s[5],     // s6
            });

            if (!nrProof.cPrime.Equals(Zq.GetElementFromDigest(RAParameters.ComputeChallenge(tildeCid, nrProof.X, nrProof.Y, nrProof.Cd, T1, T2, T3))) ||
                !nrProof.Y.Equals(nrProof.X.Exponentiate(PrivateKey)))
            {
                throw new InvalidUProveArtifactException("Invalid non-revocation proof");
            }
        }
Exemplo n.º 22
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);
        }
Exemplo n.º 23
0
        public void GetElementIntTest()
        {
            FieldZq Zq = FieldZq.CreateFieldZq(new byte[] { 0x05 });

            Assert.AreEqual <FieldZqElement>(Zq.GetElement(0), Zq.GetElement(-0), "-0");
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(1).Negate(), Zq.GetElement(-1), "-1");
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(2).Negate(), Zq.GetElement(-2), "-2");
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(3).Negate(), Zq.GetElement(-3), "-3");
            Assert.AreEqual <FieldZqElement>(Zq.GetElement(4).Negate(), Zq.GetElement(-4), "-4");

            ParameterSet parameters = ECParameterSets.ParamSet_EC_P256_V1;

            Assert.AreEqual <FieldZqElement>(parameters.Group.FieldZq.GetElement(456).Negate(), parameters.Group.FieldZq.GetElement(-456), "-456");
            Assert.AreEqual <FieldZqElement>(parameters.Group.FieldZq.GetElement(1).Negate(), parameters.Group.FieldZq.GetElement(-1), "-1");
            Assert.AreEqual <FieldZqElement>(parameters.Group.FieldZq.GetElement(10000034).Negate(), parameters.Group.FieldZq.GetElement(-10000034), "-10000034");
        }
Exemplo n.º 24
0
 /// <summary>
 /// Constructor. Takes the input group and creates the
 /// associated FieldZq object.
 /// </summary>
 /// <param name="group"></param>
 public Algebra(Group group)
 {
     if (group == null)
     {
         throw new ArgumentNullException("Could not create Algebra because group is null.");
     }
     this.Group = group;
     try
     {
         this.FieldZq = FieldZq.CreateFieldZq(group.Q);
     }
     catch (Exception e)
     {
         throw new ArgumentException("Could not create Algebra from input group because could not create associated field.", e);
     }
 }
Exemplo n.º 25
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));
        }
Exemplo n.º 26
0
        /// <summary>
        /// Takes as input a bit decomposition of some FieldZqElement and computes it.
        /// </summary>
        /// <param name="bitDecomposition">Array of zero and one in the field, in little endian order.</param>
        /// <param name="fieldZq">Field Zq</param>
        /// <returns>sum bitDecomposition[i] * 2^i</returns>
        public static FieldZqElement GetBitComposition(BitArray bitDecomposition, FieldZq fieldZq)
        {
            FieldZqElement powerOfTwo  = fieldZq.One;
            FieldZqElement two         = fieldZq.One + fieldZq.One;
            FieldZqElement composition = fieldZq.Zero;

            for (int exponent = 0; exponent < bitDecomposition.Length; ++exponent)
            {
                if (bitDecomposition.Get(exponent))
                {
                    composition += powerOfTwo;
                }
                powerOfTwo *= two;
            }
            return(composition);
        }
Exemplo n.º 27
0
        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 BDBadCompositionTest()
        {
            PedersenCommitment[] ped = new PedersenCommitment[2];
            ped[0] = new PedersenCommitment(_parameters[0].G, _parameters[0].H, _parameters[0].FieldZq.One, _parameters[0].FieldZq.One, _parameters[0].Group);
            ped[1] = new PedersenCommitment(_parameters[1].G, _parameters[1].H, _parameters[1].FieldZq.One, _parameters[1].FieldZq.One, _parameters[1].Group);
            PedersenCommitment composition = ped[0];
            FieldZq            field       = _parameters[0].FieldZq;

            PrivateType bdproof = new PrivateType(typeof(BitDecompositionProof));

            object [] inputParameters = new object[3] {
                ped, _parameters[0].FieldZq, composition
            };
            bool success = (bool)bdproof.InvokeStatic("ComposeCommitments", inputParameters);

            Assert.IsFalse(success, "success");
        }
Exemplo n.º 30
0
        public void GetRandomElementsTest()
        {
            FieldZq Zq = FieldZq.CreateFieldZq(new byte[] { 0x05 });

            // make sure that setting nonZero=true results in no no zero elements.
            FieldZqElement[] nonZeroElements = Zq.GetRandomElements(30, true);
            for (int i = 0; i < nonZeroElements.Length; ++i)
            {
                Assert.AreNotEqual(Zq.Zero, nonZeroElements[i], "element " + i + " is 0.");
            }

            // check that setting nonZero=false results in at least one zero element
            bool foundNonZero = false;

            FieldZqElement[] zeroElements = Zq.GetRandomElements(100, false);
            for (int i = 0; i < zeroElements.Length; ++i)
            {
                if (zeroElements[i] == Zq.Zero)
                {
                    foundNonZero = true;
                    break;
                }
            }
            if (!foundNonZero)
            {
                Assert.Inconclusive("GetRandomElements did not create a single zero value.  Try running this test again. Chances of failure on correct behavior is 0.0000000002.");
            }

            // check that setting maxBitLength=-1 results in at least one element 2, 3, or 4
            bool foundLargeElement = false;

            FieldZqElement[] fullScopeElements = Zq.GetRandomElements(100, false, -1);
            for (int i = 0; i < fullScopeElements.Length; ++i)
            {
                if ((fullScopeElements[i] != Zq.Zero) && fullScopeElements[i] != Zq.One)
                {
                    foundLargeElement = true;
                    break;
                }
            }
            if (!foundLargeElement)
            {
                Assert.Inconclusive("GetRandomElements did not create a single value in the set {2,3,4}.  Try running this test again. Chances of failure on correct behavior is 2.6 x 10^-40.");
            }
        }