Exemple #1
0
        //      ec-function: Y^2 = X^3 + a*X + b 'modulo' P
        //P = {Xp, Yp}; Q = {Xq, Yq}
        //ADD:    S = (Yp - Yq) / (Xp - Xq)
        //        RESULT = {Xr = S * S - Xp - Xq; Yr = S(Xp - Xr) - Yp}
        //DUB:    S = (3 * Xp * Xp + a) / (2 * Yp)
        //        RESULT = {Xr = S * S - 2 * Xp ; Yr = S(Xp - Xr) - Yp}
        public void GetDouble(ref OwnECPoint p)
        {   //return: 2 * p
            if (p.IsInfinity)
            {
                return;
            }
            if (IsZero(p.Y))
            {
                p.SetInfinity();
                return;
            }

            Let(S1, p.X);
            SquareModP(S1); AddScaledModP(S1, S1, 2);
            AddModP(S1, A);
            Let(S2, p.Y);
            AddModP(S2, S2);

            this.RemodFriendlyPrime(S1);
            this.RemodFriendlyPrime(S2);
            AsmX64Operations.DivideModuloPrime(S1, S2, P, N);

            Let(R1, S1);
            SquareModP(S1);
            SubScaledModP(S1, p.X, 2); //S1 = Rx = S * S - 2 * Px

            SubtractModP(p.X, S1, S2); //S2 = Px - Rx
            MultiplyModP(S2, R1);
            SubModP(S2, p.Y);          //S2 = S(Px - Rx) - Py

            p.SetFrom(S1, S2, false);
        }
Exemple #2
0
        //return: P * factor on the elliptic curves domain.
        public OwnECPoint MultiplyWithEndomorphism(OwnECPoint p, ulong[] factor)
        {
            OwnECPoint result;

            if (!this.SupportsEndomorphism)
            {
                result = this.Multiply(p, factor);
                return(result);
            }

            BigInteger lambda = W1ModOrder.ToBigInteger();
            BigInteger k = factor.ToBigInteger(), k1, k2;

            SplitKToHalfBits(k, lambda, out k1, out k2);

            OwnECPoint q = p.Copy();

            MultiplyModP(q.X, W1ModP);

            //OwnECPoint test1 = Multiply(p, W1ModOrder);
            //bool testok = test1.ToString() == q.ToString();
            //if (!testok)
            //{
            //    Debugger.Break();
            //}

            result = DualMultiply(p, k1, q, k2);
            return(result);
        }
Exemple #3
0
        public OwnECPoint Negative(OwnECPoint point)
        {
            OwnECPoint result = point.Copy();

            SubtractModP(this.P, result.Y, result.Y);
            return(result);
        }
Exemple #4
0
 public static bool IsSameAs(this OwnECPoint point1, ECPoint point2)
 {
     if (point1.IsInfinity || point2.IsInfinity)
     {
         return(point1.IsInfinity && point2.IsInfinity);
     }
     point2 = point2.Normalize();
     return(point1.X.ToBigInteger() == point2.X && point1.Y.ToBigInteger() == point2.Y);
 }
Exemple #5
0
 public bool IsSameAs(OwnECPoint other)
 {
     if (this.IsInfinity != other.IsInfinity)
     {
         return(false);
     }
     if (this.IsInfinity)
     {
         return(true);
     }
     return(this.X.IsEqual(other.X) && this.Y.IsEqual(other.Y));
 }
Exemple #6
0
        public void Add(ref OwnECPoint p, OwnECPoint q, bool subtract = false)
        {   //returns: P + Q
            if (p.IsInfinity || q.IsInfinity)
            {
                if (!q.IsInfinity)
                {
                    p.SetFrom(q.X, q.Y, q.IsInfinity);
                    if (subtract)
                    {
                        SubtractModP(P, p.Y, p.Y);
                    }
                }
                return;
            }

            SubtractModP(p.X, q.X, S2);     //s2 = Px - Qx
            if (subtract)
            {                               //s1 = Py - Qy; in case of subtract real Q.Y is -Q.Y so we add the value modulo P.
                AdditionModP(p.Y, q.Y, S1); //s1 = Py - Qy
            }
            else
            {
                SubtractModP(p.Y, q.Y, S1);
            }

            if (IsZero(S2))
            {     //Px == Qx
                if (IsZero(S1))
                { // P == Q
                    GetDouble(ref p);
                    return;
                }
                p.SetInfinity();
                return;
            }

            this.RemodFriendlyPrime(S1);
            this.RemodFriendlyPrime(S2);
            AsmX64Operations.DivideModuloPrime(S1, S2, P, N);        //S = s1 = s1 / s2 'modulo' P.

            Let(R1, S1);
            SquareModP(S1);
            SubModP(S1, p.X);
            SubModP(S1, q.X);          //s1 = Result.x = S * S - Px - Qx

            SubtractModP(p.X, S1, S2); //s2 = Px - Rx
            MultiplyModP(S2, R1);
            SubModP(S2, p.Y);          //s2 = S(Px - Rx) - Py

            p.SetFrom(S1, S2, false);
        }
Exemple #7
0
 public bool Verify(OwnECPoint point)
 {   //Y^2 = X^3 + a*X + b 'modulo' P
     if (point.IsInfinity)
     {
         return(true);
     }
     Let(x1, point.X);
     Let(y1, point.Y);
     SquareModP(y1);
     SquareModP(x1);
     AddModP(x1, A);
     MultiplyModP(x1, point.X);
     AddModP(x1, B);
     SubModP(x1, y1);
     return(IsZero(x1));
 }
Exemple #8
0
        //https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates#Mixed_Addition_(with_affine_point)_(8M_+_3S)
        //U1 = X1  [*Z2^2]
        //U2 = X2*Z1^2
        //S1 = Y1  [*Z2^3]
        //S2 = Y2*Z1^3
        //if (U1 == U2)
        //  if (S1 != S2)
        //    return POINT_AT_INFINITY
        //  else
        //    return POINT_DOUBLE(X1, Y1, Z1)
        //H = U2 - U1
        //R = S2 - S1
        //X3 = R^2 - H^3 - 2*U1*H^2
        //Y3 = R*(U1*H^2 - X3) - S1*H^3
        //Z3 = H*Z1*Z2
        //return (X3, Y3, Z3)

        //http://www.hyperelliptic.org/EFD/oldefd/jacobian.html#mADD
        //Z2 = [p.Z]^2
        //S1 = [q.X] * Z2 - [p.X]
        //R1 = [+/-q.Y] * [p.Z] * Z2 - [p.Y]
        //S2 = S1^2
        //Z3 = ([p.Z]+S1)^2 - S2 - Z2
        //S2 *= 4
        //S1 *= S2
        //R1 = 2*R1
        //Y3 = [p.X]*S2
        //X3 = R1^2-S1-2*Y3
        //Y3 = R1*(Y3-X3)-2*[p.y]*S1
        public void Add(ref JacobianECPoint p, OwnECPoint q, bool subtract = false)
        {   //Mixed addition returns p + q in "7M + 4S"
            if (p.IsInfinity || q.IsInfinity)
            {
                if (!q.IsInfinity)
                {
                    p.SetFrom(q.X, q.Y, One, q.IsInfinity);
                    if (subtract)
                    {
                        SubtractModP(P, p.Y, p.Y);
                    }
                }
                return;
            }

            Let(Z2, p.Z); SquareModP(Z2);                         //Z2 = [p.Z]^2
            Let(S1, q.X); MultiplyModP(S1, Z2); SubModP(S1, p.X); //S1 = [q.X] * Z2 - [p.X]
            Let(R1, q.Y);
            if (subtract)
            {
                SubtractModP(P, R1, R1);
            }
            MultiplyModP(R1, p.Z); MultiplyModP(R1, Z2); SubModP(R1, p.Y);   //R1 = [+/-q.Y] * [p.Z] * Z2 - [p.Y]

            if (IsZero(S1))
            {
                if (IsZero(R1))
                {   //now: p == q
                    GetDouble(ref p);
                    return;
                }
                p.SetInfinity();
                return;
            }

            Let(S2, S1); SquareModP(S2);                                                            //S2 = S1^2
            Let(Z3, p.Z); AddModP(Z3, S1); SquareModP(Z3); SubModP(Z3, S2); SubModP(Z3, Z2);        //Z3 = ([p.Z]+S1)^2 - S2 - Z2

            AddScaledModP(S2, S2, 3);                                                               //S2 *= 4
            MultiplyModP(S1, S2);                                                                   //S1 *= S2
            AddModP(R1, R1);                                                                        //R1 = 2*R1
            Let(y1, p.X); MultiplyModP(y1, S2);                                                     //Y3 = [p.X]*S2
            Let(x1, R1); SquareModP(x1); SubModP(x1, S1); SubScaledModP(x1, y1, 2);                 //X3 = R1^2-S1-2*Y3
            MultiplyModP(S1, p.Y); SubModP(y1, x1); MultiplyModP(y1, R1); SubScaledModP(y1, S1, 2); //Y3 = R1*(Y3-X3)-2*[p.y]*S1

            p.SetFrom(x1, y1, Z3, false);
        }
Exemple #9
0
        //return: P * factor on the elliptic curves domain.
        public OwnECPoint Multiply(OwnECPoint p, ulong[] factor)
        {
            ulong[] exp  = new ulong[factor.Length + 1];
            ulong[] exp3 = new ulong[factor.Length + 1];
            factor.CopyTo(exp, 0);
            exp3[factor.Length] = AsmX64Operations.MultiplyDigitAndAdd(exp, 3, exp3, factor.Length);
            for (int i = exp.Length; --i >= 0;)
            {
                exp3[i] ^= exp[i];  //exp3= (exp*3) ^ exp
            }
            int high = HighBit(exp3);

            if (high < 0)
            {
                return(new OwnECPoint(p.X, p.Y, true));
            }
            JacobianECPoint x    = new JacobianECPoint(p.X, p.Y, true);
            ulong           mask = 1UL << (high & 63);

            for (int i = high; --i >= 0;)
            {
                GetDouble(ref x);
                if ((exp3[(i + 1) >> 6] & mask) != 0)
                {
                    if ((exp[(i + 1) >> 6] & mask) != 0)
                    {
                        Subtract(ref x, p);
                    }
                    else
                    {
                        Add(ref x, p);
                    }
                }
                mask = (mask >> 1) | (mask << 63);
            }
            OwnECPoint result = x.ToECPoint(this);

            return(result);
        }
Exemple #10
0
        //return: P * factor on the elliptic curves domain.
        public OwnECPoint MultiplyReference(OwnECPoint p, ulong[] factor)
        {
            int high = HighBit(factor);

            if (high < 0)
            {
                return(new OwnECPoint(p.X, p.Y, true));
            }
            OwnECPoint result = p.Copy();

            for (int i = high; --i >= 0;)
            {
                GetDouble(ref result);
                if ((factor[i >> 6] & (1UL << (i & 63))) != 0)
                {
                    Add(ref result, p);
                }
            }
            RemodFriendlyPrime(result.X);
            RemodFriendlyPrime(result.Y);
            return(result);
        }
Exemple #11
0
        public static bool ECCUnitTest()
        {
            Random random = new Random(104);
            int    n      = 8;
            bool   ok     = true;

            TimeSpan
                elapsedInvertFast = TimeSpan.Zero,
                elapsedInvertSlow = TimeSpan.Zero;

            byte[] randomBytes = new byte[16 * n];
            for (int i = 20; --i >= 0;)
            {
                ulong[] a0 = new ulong[n * 2]; a0[0] = 1UL;
                random.NextBytes(randomBytes);
                ulong[] x = Enumerable.Range(0, n * 2).Select(idx => idx >= n ? 0 : BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                random.NextBytes(randomBytes);
                ulong[] p = Enumerable.Range(0, n).Select(idx => BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                p[0] |= 1;
                GetDivMod(a0, p, n);
                GetDivMod(x, p, n);
                ulong[] a1 = a0.ToArray();
                ulong[] a2 = a0.ToArray();

                var fx = new FastInteger(x);
                var fp = new FastInteger(p);
                var f0 = new FastInteger(a0);
                if (fx.ToString() != x.ToBigInteger().ToString() || fp.ToString() != p.ToBigInteger().ToString() || f0.ToString() != a0.ToBigInteger().ToString())
                {
                    ok = false;
                }
                FastInteger idv = f0.DivideModulo(fx, fp);
                elapsedInvertFast += MeasureTime(() =>
                {
                    AsmX64Operations.DivideModuloPrime(a1, x, p, n);
                });
                elapsedInvertSlow += MeasureTime(() =>
                {
                    AsmX64Operations.DivideModPSlow(a2, x, p, n);
                });

                if (a1.ToBigInteger().ToString() != idv.ToString())
                {
                    ok = false;
                }

                ulong[] r1 = new ulong[n * 2];
                Multiply(a1, x, r1, n);
                GetDivMod(r1, p, n);

                ulong[] r2 = new ulong[n * 2];
                Multiply(a2, x, r2, n);
                GetDivMod(r2, p, n);

                if (!Enumerable.Range(0, n).All(idx => r1[idx] == r2[idx]))
                {
                    ok = false;
                }
            }

            TimeSpan
                elapsedExponentiationSlow      = TimeSpan.Zero,
                elapsedExponentiation521       = TimeSpan.Zero,
                elapsedExponentiationBigInt    = TimeSpan.Zero,
                elapsedExponentiationFastInt   = TimeSpan.Zero,
                elapsedExponentiationBigInt521 = TimeSpan.Zero,
                elapsedExponentiationFast      = TimeSpan.Zero;
            SECP256K1Base           ecc        = new SECP256K1Base();
            SECP521R1Base           ecc2       = new SECP521R1Base();
            ECCSecP256K1FastInteger fastEcc    = new ECCSecP256K1FastInteger();
            ECCSecP521R1            ecc521     = new ECCSecP521R1();

            random = new Random(105);
            OwnECPoint point    = ecc.G;
            OwnECPoint point521 = ecc2.G;

            ok          = ok && ecc.Verify(point);
            ok          = ok && ecc2.Verify(point521);
            ok          = ok && ecc2.UnitTest();
            randomBytes = new byte[ecc.N * 8];
            ECC other = new ECC();
            int ops   = 1;

            ulong[] order521 = ecc2.Order.ToArray();
            order521[0]--;
            for (int i = ops; --i >= 0;)
            {
                random.NextBytes(randomBytes);
                BigInteger orderInteger = randomBytes.ToBigInteger();
                ulong[]    order        = Enumerable.Range(0, ecc.N).Select(idx => BitConverter.ToUInt64(randomBytes, idx * 8)).ToArray();
                OwnECPoint point2       = ecc.MultiplyReference(point, order);
                OwnECPoint point3       = new OwnECPoint();
                OwnECPoint point521_O   = new OwnECPoint();
                ECPoint    point8_521   = null;
                elapsedExponentiation521 += MeasureTime(() =>
                {
                    point521_O = ecc2.MultiplyWithEndomorphism(point521, order521);
                });
                elapsedExponentiationBigInt521 += MeasureTime(() =>
                {
                    point8_521 = ecc521.ECMultiplication(order521.ToBigInteger());
                });
                ok = ok && point521_O.X.IsEqual(point521.X) && point521_O.Y.ToBigInteger() + point521.Y.ToBigInteger() == (BigInteger.One << 521) - BigInteger.One;
                ok = ok && point8_521.X == point521.X.ToBigInteger() && point8_521.Y + point521.Y.ToBigInteger() == (BigInteger.One << 521) - BigInteger.One;
                FastECPoint point6 = ecc.ECMultiplication(randomBytes.ToFastInteger());
                OwnECPoint  point4 = new OwnECPoint();
                ECPoint     point5 = null;
                ECPoint     point7 = null;
                elapsedExponentiationSlow += MeasureTime(() =>
                {
                    point3 = ecc.Multiply(point, order);
                });
                elapsedExponentiationFast += MeasureTime(() =>
                {
                    point4 = ecc.MultiplyWithEndomorphism(point, order);
                });
                elapsedExponentiationBigInt += MeasureTime(() =>
                {
                    point5 = other.ECMultiplication(orderInteger);
                });
                elapsedExponentiationFastInt += MeasureTime(() =>
                {
                    point7 = fastEcc.ECMultiplication(orderInteger);
                });
                ok &= ecc.Verify(point2);
                ok &= ecc.Verify(point3);
                ok &= ecc.Verify(point4);
                ok &= other.Verify(point5);

                if (!ok || !point2.IsSameAs(point3) || !point2.IsSameAs(point4) || !point2.IsSameAs(point5) ||
                    !point2.IsSameAs(point6) || !point2.IsSameAs(point7))
                {
                    ok = false;
                }
            }
            //MessageBox.Show(
            //    "secP521r1 ecc multiplication: " + elapsedExponentiation521.ToString() + " ops/sec = " + (ops / elapsedExponentiation521.TotalSeconds).ToString("N3") + "\r\n" +
            //    "P521R1 BigInt ecc multiplication: " + elapsedExponentiationBigInt521.ToString() + " ops/sec = " + (ops / elapsedExponentiationBigInt521.TotalSeconds).ToString("N3") + "\r\n" +
            //    "Fast ecc multiplication: " + elapsedExponentiationFast.ToString() + " ops/sec = " + (ops / elapsedExponentiationFast.TotalSeconds).ToString("N3") + "\r\n" +
            //    "BigInteger ecc multiplication: " + elapsedExponentiationBigInt.ToString() + " ops/sec = " + (ops / elapsedExponentiationBigInt.TotalSeconds).ToString("N3") + "\r\n" +
            //    "FastInteger ecc multiplication: " + elapsedExponentiationFastInt.ToString() + " ops/sec = " + (ops / elapsedExponentiationFastInt.TotalSeconds).ToString("N3") + "\r\n" +
            //    "Slow ecc multiplication: " + elapsedExponentiationSlow.ToString() + " ops/sec = " + (ops / elapsedExponentiationSlow.TotalSeconds).ToString("N3") + "\r\n", "Time",
            //     MessageBoxButtons.OK, MessageBoxIcon.Information);

            return(ok);
        }
Exemple #12
0
        public bool UnitTest()
        {
            OwnECPoint S = new OwnECPoint(
                FromHex(@"000001d5 c693f66c 08ed03ad 0f031f93 7443458f 601fd098 d3d0227b 4bf62873 af50740b 0bb84aa1 57fc847b cf8dc16a 8b2b8bfd 8e2d0a7d 39af04b0 89930ef6 dad5c1b4"),
                FromHex(@"00000144 b7770963 c63a3924 8865ff36 b074151e ac33549b 224af5c8 664c5401 2b818ed0 37b2b7c1 a63ac89e baa11e07 db89fcee 5b556e49 764ee3fa 66ea7ae6 1ac01823"), false);
            OwnECPoint T = new OwnECPoint(
                FromHex(@"000000f4 11f2ac2e b971a267 b80297ba 67c322db a4bb21ce c8b70073 bf88fc1c a5fde3ba 09e5df6d 39acb2c0 762c03d7 bc224a3e 197feaf7 60d63240 06fe3be9 a548c7d5"),
                FromHex(@"000001fd f842769c 707c93c6 30df6d02 eff399a0 6f1b36fb 9684f0b3 73ed0648 89629abb 92b1ae32 8fdb4553 42683849 43f0e922 2afe0325 9b32274d 35d1b958 4c65e305"), false);
            OwnECPoint ST = new OwnECPoint(
                FromHex(@"00000126 4ae115ba 9cbc2ee5 6e6f0059 e24b52c8 04632160 2c59a339 cfb757c8 9a59c358 a9a8e1f8 6d384b3f 3b255ea3 f73670c6 dc9f45d4 6b6a196d c37bbe0f 6b2dd9e9"),
                FromHex(@"00000062 a9c72b8f 9f88a271 690bfa01 7a6466c3 1b9cadc2 fc544744 aeb81707 2349cfdd c5ad0e81 b03f1897 bd9c8c6e fbdf6823 7dc3bb00 445979fb 373b20c9 a967ac55"), false);
            OwnECPoint STSub = new OwnECPoint(
                FromHex(@"00000129 2cb58b17 95ba4770 63fef7cd 22e42c20 f57ae94c eaad86e0 d21ff229 18b0dd3b 076d63be 253de24b c20c6da2 90fa54d8 3771a225 deecf914 9f79a8e6 14c3c4cd"),
                FromHex(@"00000169 5e3821e7 2c7cacaa dcf62909 cd83463a 21c6d033 93c527c6 43b36239 c46af117 ab7c7ad1 9a4c8cf0 ae95ed51 72988546 1aa2ce27 00a6365b ca3733d2 920b2267"), false);
            OwnECPoint S2X = new OwnECPoint(
                FromHex(@"00000128 79442f24 50c119e7 119a5f73 8be1f1eb a9e9d7c6 cf41b325 d9ce6d64 3106e9d6 1124a91a 96bcf201 305a9dee 55fa7913 6dc70083 1e54c3ca 4ff2646b d3c36bc6"),
                FromHex(@"00000198 64a8b885 5c2479cb efe375ae 553e2393 271ed36f adfc4494 fc0583f6 bd035988 96f39854 abeae5f9 a6515a02 1e2c0eef 139e71de 610143f5 3382f410 4dccb543"), false);
            JacobianECPoint ST1 = S.ToJacobian;
            JacobianECPoint ST2 = S.ToJacobian;
            JacobianECPoint S2  = S.ToJacobian;

            Add(ref ST1, T, false);
            Add(ref ST2, T, true);
            GetDouble(ref S2);
            OwnECPoint ST1a = ST1.ToECPoint(this);
            OwnECPoint ST2a = ST2.ToECPoint(this);
            OwnECPoint S2a  = S2.ToECPoint(this);

            if (!IsEqual(ST1a.X, ST.X) || !IsEqual(ST1a.Y, ST.Y))
            {
                return(false);
            }
            if (!IsEqual(ST2a.X, STSub.X) || !IsEqual(ST2a.Y, STSub.Y))
            {
                return(false);
            }
            if (!IsEqual(S2a.X, S2X.X) || !IsEqual(S2a.Y, S2X.Y))
            {
                return(false);
            }
            ulong[]    factorD = FromHex(@"000001eb 7f81785c 9629f136 a7e8f8c6 74957109 73555411 1a2a866f a5a16669 9419bfa9 936c78b6 2653964d f0d6da94 0a695c72 94d41b2d 6600de6d fcf0edcf c89fdcb1");
            OwnECPoint dS      = new OwnECPoint(
                FromHex(@"00000091 b15d09d0 ca0353f8 f96b93cd b13497b0 a4bb582a e9ebefa3 5eee61bf 7b7d041b 8ec34c6c 00c0c067 1c4ae063 318fb75b e87af4fe 859608c9 5f0ab477 4f8c95bb"),
                FromHex(@"00000130 f8f8b5e1 abb4dd94 f6baaf65 4a2d5810 411e77b7 423965e0 c7fd79ec 1ae563c2 07bd255e e9828eb7 a03fed56 5240d2cc 80ddd2ce cbb2eb50 f0951f75 ad87977f"), false);
            OwnECPoint rsd = Multiply(S, factorD);

            if (!IsEqual(rsd.X, dS.X) || !IsEqual(rsd.Y, dS.Y))
            {
                return(false);
            }
            ulong[]    factorE = FromHex(@"00000137 e6b73d38 f153c3a7 57561581 2608f2ba b3229c92 e21c0d1c 83cfad92 61dbb17b b77a6368 2000031b 9122c2f0 cdab2af7 2314be95 254de429 1a8f85f7 c70412e3");
            OwnECPoint dSeT    = new OwnECPoint(
                FromHex(@"0000009d 3802642b 3bea152b eb9e05fb a247790f 7fc16807 2d363340 133402f2 585588dc 1385d40e bcb8552f 8db02b23 d687cae4 6185b275 28adb1bf 9729716e 4eba653d"),
                FromHex(@"0000000f e44344e7 9da6f49d 87c10637 44e5957d 9ac0a505 bafa8281 c9ce9ff2 5ad53f8d a084a2de b0923e46 501de579 7850c61b 229023dd 9cf7fc7f 04cd35eb b026d89d"), false);
            OwnECPoint ret = Multiply(T, factorE);

            Add(ref ret, rsd, false);
            if (!IsEqual(ret.X, dSeT.X) || !IsEqual(ret.Y, dSeT.Y))
            {
                return(false);
            }
            return(true);
        }
Exemple #13
0
 public override string ToString()
 {
     return(this.IsInfinity ? "Infinity" : "X = " + OwnECPoint.ToHexa(this.X) + " ; Y = " + OwnECPoint.ToHexa(this.Y) + " ; Z = " + OwnECPoint.ToHexa(this.Z));
 }
Exemple #14
0
        //return: P * factor on the elliptic curves domain.
        public OwnECPoint DualMultiply(OwnECPoint p1, BigInteger k1, OwnECPoint p2, BigInteger k2)
        {
            if (k1 < 0)
            {
                p1 = Negative(p1);
                k1 = -k1;
            }
            if (k2 < 0)
            {
                p2 = Negative(p2);
                k2 = -k2;
            }

            BigInteger      exp1     = k1 ^ (k1 * 3);
            BigInteger      exp2     = k2 ^ (k2 * 3);
            BigInteger      max      = BigInteger.Max(exp1, exp2);
            int             high     = max <= 0 ? 0 : 1 + (int)Math.Ceiling(BigInteger.Log(max, 2));
            JacobianECPoint x        = new JacobianECPoint(p1.X, p1.Y, true);
            OwnECPoint      cacheAdd = p1.Copy();
            OwnECPoint      cacheSub = p1.Copy();

            Add(ref cacheAdd, p2);
            Subtract(ref cacheSub, p2);

            BigInteger bit = BigInteger.One << high;

            for (int i = high; --i >= 0; bit >>= 1)
            {
                GetDouble(ref x);
                if ((exp1 & bit) != 0 && (exp2 & bit) != 0)
                {
                    int branch = ((k1 & bit) != 0 ? 0 : 1) + ((k2 & bit) != 0 ? 0 : 2);
                    switch (branch)
                    {
                    case 0: Subtract(ref x, cacheAdd); break;

                    case 1: Add(ref x, cacheSub); break;

                    case 2: Subtract(ref x, cacheSub); break;

                    case 3: Add(ref x, cacheAdd); break;
                    }
                    continue;
                }
                if ((exp1 & bit) != 0)
                {
                    if ((k1 & bit) != 0)
                    {
                        Subtract(ref x, p1);
                    }
                    else
                    {
                        Add(ref x, p1);
                    }
                    continue;
                }
                if ((exp2 & bit) != 0)
                {
                    if ((k2 & bit) != 0)
                    {
                        Subtract(ref x, p2);
                    }
                    else
                    {
                        Add(ref x, p2);
                    }
                    continue;
                }
            }

            OwnECPoint result = x.ToECPoint(this);

            return(result);
        }
Exemple #15
0
 public void Subtract(ref JacobianECPoint p, OwnECPoint q)
 {
     Add(ref p, q, true);
 }