/*
         * Mixed comparison: P1 is in Jacobian coordinates, P2 is in
         * affine coordinates.
         */
        uint EqCTMixed(MutableECPointPrime P1, MutableECPointPrime P2)
        {
            /*
             * If either P1 or P2 is infinity, then they are equal
             * if and only if they both are infinity.
             *
             * If neither is infinity, then we must check the following:
             *    X1 = X2*(Z1^2)
             *    Y1 = Y2*(Z1^3)
             * Beware that X1, Y1 and Z1 are in Montgomery representation,
             * while X2 and Y2 are not.
             */
            mt1.Set(P1.mz);
            mt1.MontySquare();
            mt2.Set(P2.mx);
            mt2.MontyMul(mt1);
            mt3.Set(P1.mx);
            mt3.FromMonty();
            uint r = mt2.EqCT(mt3);

            mt1.MontyMul(P1.mz);
            mt1.MontyMul(P2.my);
            mt2.Set(P1.my);
            mt2.FromMonty();
            r &= mt1.EqCT(mt2);
            uint z1z = P1.mz.IsZeroCT;
            uint z2z = P2.mz.IsZeroCT;

            return((r & ~(z1z | z2z)) ^ (z1z & z2z));
        }
        internal override MutableECPoint Dup()
        {
            MutableECPointPrime Q = new MutableECPointPrime(curve);

            Q.Set(this);
            return(Q);
        }
Example #3
0
        internal override MutableECPoint Decode(byte[] enc)
        {
            MutableECPointPrime P = new MutableECPointPrime(this);

            P.Decode(enc);
            return(P);
        }
 void SetMuxInner(uint ctl,
                  MutableECPointPrime P1, MutableECPointPrime P2)
 {
     mx.CopyMux(ctl, P1.mx, P2.mx);
     my.CopyMux(ctl, P1.my, P2.my);
     mz.CopyMux(ctl, P1.mz, P2.mz);
     affine = P2.affine ^ (ctl & (P1.affine ^ P2.affine));
 }
        internal override void Set(MutableECPoint Q, uint ctl)
        {
            MutableECPointPrime R = SameCurve(Q);

            mx.CondCopy(R.mx, ctl);
            my.CondCopy(R.my, ctl);
            mz.CondCopy(R.mz, ctl);
            affine ^= ctl & (affine ^ R.affine);
        }
        internal override void Set(MutableECPoint Q)
        {
            MutableECPointPrime R = SameCurve(Q);

            mx.Set(R.mx);
            my.Set(R.my);
            mz.Set(R.mz);
            affine = R.affine;
        }
        MutableECPointPrime SameCurve(MutableECPoint Q)
        {
            MutableECPointPrime R = Q as MutableECPointPrime;

            if (R == null || !curve.Equals(R.curve))
            {
                throw new CryptoException("Mixed curves");
            }
            return(R);
        }
        internal override uint EqCT(MutableECPoint Q)
        {
            MutableECPointPrime R = SameCurve(Q);

            if (affine != 0)
            {
                if (R.affine != 0)
                {
                    return(mx.EqCT(R.mx)
                           & my.EqCT(R.my)
                           & mz.EqCT(R.mz));
                }
                else
                {
                    return(EqCTMixed(R, this));
                }
            }
            else if (R.affine != 0)
            {
                return(EqCTMixed(this, R));
            }

            /*
             * Both points are in Jacobian coordinates.
             * If Z1 and Z2 are non-zero, then equality is
             * achieved if and only if both following equations
             * are true:
             *     X1*(Z2^2) = X2*(Z1^2)
             *     Y1*(Z2^3) = Y2*(Z1^3)
             * If Z1 or Z2 is zero, then equality is achieved
             * if and only if both are zero.
             */
            mt1.Set(mz);
            mt1.MontySquare();
            mt2.Set(R.mz);
            mt2.MontySquare();
            mt3.Set(mx);
            mt3.MontyMul(mt2);
            mt4.Set(R.mx);
            mt4.MontyMul(mt1);
            uint r = mt3.EqCT(mt4);

            mt1.MontyMul(mz);
            mt2.MontyMul(R.mz);
            mt3.Set(my);
            mt3.MontyMul(mt2);
            mt4.Set(R.my);
            mt4.MontyMul(mt1);
            r &= mt3.EqCT(mt4);
            uint z1z = mz.IsZeroCT;
            uint z2z = R.mz.IsZeroCT;

            return((r & ~(z1z | z2z)) ^ (z1z & z2z));
        }
Example #9
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);
        }
Example #10
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.
             */
        }
Example #11
0
        internal override uint AddCT(MutableECPoint Q)
        {
            MutableECPointPrime P2 = SameCurve(Q);

            if (P2.affine != 0)
            {
                ms4.Set(P2.mx);
                ms5.Set(P2.my);
                ms6.Set(P2.mz);
                ms4.ToMonty();
                ms5.ToMonty();
                ms6.SetMonty(~ms6.IsZeroCT);
                return(AddCTInner(ms4, ms5, ms6, true));
            }
            else
            {
                return(AddCTInner(P2.mx, P2.my, P2.mz, false));
            }
        }
Example #12
0
        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);
        }
Example #13
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;
        }