internal override MutableECPoint Dup()
        {
            MutableECPointPrime Q = new MutableECPointPrime(curve);

            Q.Set(this);
            return(Q);
        }
Exemple #2
0
        internal override MutableECPoint MakeGenerator()
        {
            /*
             * We do not have to check the generator, since
             * it was already done in the constructor.
             */
            MutableECPointPrime G = new MutableECPointPrime(this);

            G.Set(gx, gy, false);
            return(G);
        }
Exemple #3
0
        /*
         * Extra checks:
         * -- modulus is prime
         * -- subgroup order is prime
         * -- generator indeed generates subgroup
         */
        public override void CheckValid()
        {
            /*
             * Check that the modulus is prime.
             */
            if (!BigInt.IsPrime(mod))
            {
                throw new CryptoException(
                          "Invalid curve: modulus is not prime");
            }

            /*
             * Check that the subgroup order is prime.
             */
            if (!BigInt.IsPrime(SubgroupOrder))
            {
                throw new CryptoException(
                          "Invalid curve: subgroup order is not prime");
            }

            /*
             * Check that the G point is indeed a generator of the
             * subgroup. Note that since it has explicit coordinates,
             * it cannot be the point at infinity; it suffices to
             * verify that, when multiplied by the subgroup order,
             * it yields infinity.
             */
            MutableECPointPrime G = new MutableECPointPrime(this);

            G.Set(gx, gy, false);
            if (G.MulSpecCT(SubgroupOrder) == 0 || !G.IsInfinity)
            {
                throw new CryptoException(
                          "Invalid curve: generator does not match"
                          + " subgroup order");
            }

            /*
             * TODO: check cofactor.
             *
             * If the cofactor is small, then we can simply compute
             * the complete curve order by multiplying the cofactor
             * with the subgroup order, and see whether it is in the
             * proper range with regards to the field cardinal (by
             * using Hasse's theorem). However, if the cofactor is
             * larger than the subgroup order, then detecting a
             * wrong cofactor value is a bit more complex. We could
             * generate a few random points and multiply them by
             * the computed order, but this may be expensive.
             */
        }
        internal override uint MulSpecCT(byte[] n)
        {
            uint good = 0xFFFFFFFF;

            /*
             * Create and populate window.
             *
             * If this instance is 0, then we only add 0 to 0 and
             * double 0, for which DoubleCT() and AddCT() work
             * properly.
             *
             * If this instance (P) is non-zero, then x*P for all
             * x in the 1..16 range shall be non-zero and distinct,
             * since the subgroup order is prime and at least 17.
             * Thus, we never add two equal points together in the
             * window construction.
             *
             * We MUST ensure that all points are in the same
             * coordinate convention (affine or Jacobian) to ensure
             * constant-time execution. TODO: measure to see which
             * is best: all affine or all Jacobian. All affine implies
             * 14 or 15 extra divisions, but saves a few hundreds of
             * multiplications.
             */
            MutableECPointPrime[] w = new MutableECPointPrime[16];
            w[0] = new MutableECPointPrime(curve);
            w[0].ToJacobian();
            w[1] = new MutableECPointPrime(curve);
            w[1].Set(this);
            w[1].ToJacobian();
            for (int i = 2; (i + 1) < w.Length; i += 2)
            {
                w[i] = new MutableECPointPrime(curve);
                w[i].Set(w[i >> 1]);
                w[i].DoubleCT();
                w[i + 1] = new MutableECPointPrime(curve);
                w[i + 1].Set(w[i]);
                good &= w[i + 1].AddCT(this);
            }

            /* obsolete
             * for (int i = 0; i < w.Length; i ++) {
             *      w[i].ToAffine();
             *      w[i].Print("Win " + i);
             *      w[i].ToJacobian();
             * }
             * Console.WriteLine("good = {0}", (int)good);
             */

            /*
             * Set this value to 0. We also set it already to
             * Jacobian coordinates, since it will be done that
             * way anyway. This instance will serve as accumulator.
             */
            mx.Set(0);
            my.Set(0);
            mz.Set(0);
            affine = 0x00000000;

            /*
             * We process the multiplier by 4-bit nibbles, starting
             * with the most-significant one (the high nibble of the
             * first byte, since we use big-endian notation).
             *
             * For each nibble, we perform a constant-time lookup
             * in the window, to obtain the point to add to the
             * current value of the accumulator. Thanks to the
             * conditions on the operands (prime subgroup order and
             * so on), all the additions below must work.
             */
            MutableECPointPrime t = new MutableECPointPrime(curve);

            for (int i = (n.Length << 1) - 1; i >= 0; i--)
            {
                int b = n[n.Length - 1 - (i >> 1)];
                int j = (b >> ((i & 1) << 2)) & 0x0F;
                for (int k = 0; k < 16; k++)
                {
                    t.Set(w[k], ~(uint)(((j - k) | (k - j)) >> 31));
                }
                good &= AddCT(t);
                if (i > 0)
                {
                    DoubleCT();
                    DoubleCT();
                    DoubleCT();
                    DoubleCT();
                }
            }

            return(good);
        }
Exemple #5
0
        /*
         * Checks enforced by the constructor:
         * -- modulus is odd and at least 80-bit long
         * -- subgroup order is odd and at least 30-bit long
         * -- parameters a[] and b[] are lower than modulus
         * -- coordinates gx and gy are lower than modulus
         * -- coordinates gx and gy match curve equation
         */
        internal ECCurvePrime(string name, byte[] mod, byte[] a, byte[] b,
                              byte[] gx, byte[] gy, byte[] subgroupOrder, byte[] cofactor)
            : base(subgroupOrder, cofactor)
        {
            this.mod = mod = BigInt.NormalizeBE(mod);
            int modLen = BigInt.BitLength(mod);

            if (modLen < 80)
            {
                throw new CryptoException(
                          "Invalid curve: modulus is too small");
            }
            if ((mod[mod.Length - 1] & 0x01) == 0)
            {
                throw new CryptoException(
                          "Invalid curve: modulus is even");
            }
            int sgLen = BigInt.BitLength(subgroupOrder);

            if (sgLen < 30)
            {
                throw new CryptoException(
                          "Invalid curve: subgroup is too small");
            }
            if ((subgroupOrder[subgroupOrder.Length - 1] & 0x01) == 0)
            {
                throw new CryptoException(
                          "Invalid curve: subgroup order is even");
            }

            mp    = new ModInt(mod);
            flen  = (modLen + 7) >> 3;
            pMod4 = mod[mod.Length - 1] & 3;

            this.a = a = BigInt.NormalizeBE(a);
            this.b = b = BigInt.NormalizeBE(b);
            if (BigInt.CompareCT(a, mod) >= 0 ||
                BigInt.CompareCT(b, mod) >= 0)
            {
                throw new CryptoException(
                          "Invalid curve: out-of-range parameter");
            }
            ma = mp.Dup();
            ma.Decode(a);
            ma.Add(3);
            aIsM3 = ma.IsZero;
            ma.Sub(3);
            mb = mp.Dup();
            mb.Decode(b);

            this.gx = gx = BigInt.NormalizeBE(gx);
            this.gy = gy = BigInt.NormalizeBE(gy);
            if (BigInt.CompareCT(gx, mod) >= 0 ||
                BigInt.CompareCT(gy, mod) >= 0)
            {
                throw new CryptoException(
                          "Invalid curve: out-of-range coordinates");
            }
            MutableECPointPrime G = new MutableECPointPrime(this);

            G.Set(gx, gy, true);

            hashCode = (int)(BigInt.HashInt(mod)
                             ^ BigInt.HashInt(a) ^ BigInt.HashInt(b)
                             ^ BigInt.HashInt(gx) ^ BigInt.HashInt(gy));

            if (name == null)
            {
                name = string.Format("generic prime {0}/{1}",
                                     modLen, sgLen);
            }
            this.name = name;
        }