Example #1
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);
        }
Example #2
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);
        }
Example #3
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);
        }
Example #4
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);
        }
Example #5
0
        public void GetDouble(ref JacobianECPoint p)
        {   //return: 2 * p in "3M + 4S" for a = 0 and "3M + 5S" for a = -3.
            if (p.IsInfinity)
            {
                return;
            }
            if (IsZero(p.Y))
            {
                p.SetInfinity();
                return;
            }

            if (AIsZero)
            {
                //https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
                //if (Y == 0)
                //  return POINT_AT_INFINITY
                //S = 4 * X * Y^2
                //M = 3*X^2 [+ a* Z^4]
                //X' = M^2 - 2*S
                //Y' = M*(S - X') - 8*Y^4
                //Z' = 2*Y*Z = (Y+Z)^2 - Y^2 - Z^2
                //return (X', Y', Z')
                Let(R1, p.Y); SquareModP(R1); AddModP(R1, R1);                                //R1 = 2 * Y^2
                Let(Z3, R1); SquareModP(Z3);                                                  //Z3 = 4 * Y^4
                Let(S1, p.X); MultiplyModP(S1, R1); AddModP(S1, S1);                          //S1 = S = 4 * X * Y^2

                Let(S2, p.X); SquareModP(S2); AddScaledModP(S2, S2, 2);                       //S2 = M = 3*X^2 [+ a* Z^4]   because a == 0.

                Let(x1, S2); SquareModP(x1); SubScaledModP(x1, S1, 2);                        //X' = M^2 - 2*S
                Let(y1, S1); SubModP(y1, x1); MultiplyModP(y1, S2); SubScaledModP(y1, Z3, 2); //Y' = M*(S - X') - 8*Y^4
                Let(Z3, p.Y); AddModP(Z3, Z3); MultiplyModP(Z3, p.Z);                         //Z' = 2*Y*Z

                p.SetFrom(x1, y1, Z3, false);
            }
            else if (AIsMinus3)
            {
                //http://www.hyperelliptic.org/EFD/oldefd/jacobian.html#a3DBL
                //delta:=Z1^2;
                //gamma:=Y1^2;
                //beta:=4*X1*gamma;
                //alpha:=3*(X1-delta)*(X1+delta);
                //X3:=alpha^2-2*beta;
                //Z3:=(Y1+Z1)^2-gamma-delta;
                //Y3:=alpha*(beta-X3)-8*gamma^2;
                Let(Z2, p.Z); SquareModP(Z2);                                 //Z2:= delta:=Z1^2;
                Let(y1, p.Y); SquareModP(y1);                                 //y1:= gamma:=Y1^2;
                Let(R1, p.X); MultiplyModP(R1, y1); AddScaledModP(R1, R1, 3); //R1:= beta:=4*X1*gamma;

                SubtractModP(p.X, Z2, S1);
                AdditionModP(p.X, Z2, S2);
                MultiplyModP(S1, S2);
                AddScaledModP(S1, S1, 2);                                                        //S1:= alpha:=3*(X1-delta)*(X1+delta)       because a == -3

                AddModP(Z2, y1);                                                                 //delta = delta + gamma
                Let(x1, S1); SquareModP(x1); SubScaledModP(x1, R1, 2);                           //X3:= alpha^2-2*beta;
                Let(Z3, p.Y); AddModP(Z3, p.Z); SquareModP(Z3); SubModP(Z3, Z2);                 //Z3 = (Y1+Z1)^2-delta
                SubModP(R1, x1); MultiplyModP(R1, S1); SquareModP(y1); SubScaledModP(R1, y1, 8); //Y3 = alpha*(beta-X3)-8*gamma^2

                p.SetFrom(x1, R1, Z3, false);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Example #6
0
 public void Subtract(ref JacobianECPoint p, OwnECPoint q)
 {
     Add(ref p, q, true);
 }