home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1993 David I. Bell
- * Permission is granted to use, distribute, or modify this source,
- * provided that this copyright notice remains intact.
- *
- * Attempt to factor numbers using elliptic functions.
- * y^2 = x^3 + a*x + b (mod N).
- *
- * Many points (x,y) (mod N) are found that solve the above equation,
- * starting from a trivial solution and 'multiplying' that point together
- * to generate high powers of the point, looking for such a point whose
- * order contains a common factor with N. The order of the group of points
- * varies almost randomly within a certain interval for each choice of a
- * and b, and thus each choice provides an independent opportunity to
- * factor N. To generate a trivial solution, a is chosen and then b is
- * selected so that (1,1) is a solution. The multiplication is done using
- * the basic fact that the equation is a cubic, and so if a line hits the
- * curve in two rational points, then the third intersection point must
- * also be rational. Thus by drawing lines between known rational points
- * the number of rational solutions can be made very large. When modular
- * arithmetic is used, solving for the third point requires the taking of a
- * modular inverse (instead of division), and if this fails, then the GCD
- * of the failing value and N provides a factor of N. This description is
- * only an approximation, read "A Course in Number Theory and Cryptography"
- * by Neal Koblitz for a good explanation.
- *
- * factor(iN, ia, B, force)
- * iN is the number to be factored.
- * ia is the initial value of a in the equation, and each successive
- * value of a is an independent attempt at factoring (default 1).
- * B is the limit of the primes that make up the high power that the
- * point is raised to for each factoring attempt (default 100).
- * force is a flag to attempt to factor numbers even if they are
- * thought to already be prime (default FALSE).
- *
- * Making B larger makes the power the point being raised to contain more
- * prime factors, thus increasing the chance that the order of the point
- * will be made up of those factors. The higher B is then, the greater
- * the chance that any individual attempt will find a factor. However,
- * a higher B also slows down the number of independent functions being
- * examined. The order of the point for any particular function might
- * contain a large prime and so won't succeed even for a really large B,
- * whereas the next function might have an order which is quickly found.
- * So you want to trade off the depth of a particular search with the
- * number of searches made. For example, for factoring 30 digits, I make
- * B be about 1000 (probably still too small).
- *
- * If you have lots of machines available, then you can run parallel
- * factoring attempts for the same number by giving different starting
- * values of ia for each machine (e.g. 1000, 2000, 3000).
- *
- * The output as the function is running is (occasionally) the value of a
- * when a new function is started, the prime that is being included in the
- * high power being calculated, and the current point which is the result
- * of the powers so far.
- *
- * If a factor is found, it is returned and is also saved in the global
- * variable f. The number being factored is also saved in the global
- * variable N.
- */
-
- obj point {x, y};
- global N; /* number to factor */
- global a; /* first coefficient */
- global b; /* second coefficient */
- global f; /* found factor */
-
-
- define factor(iN, ia, B, force)
- {
- local C, x, p;
-
- if (!force && ptest(iN, 50))
- return 1;
- if (isnull(B))
- B = 100;
- if (isnull(ia))
- ia = 1;
- obj point x;
- a = ia;
- b = -ia;
- N = iN;
- C = isqrt(N);
- C = 2 * C + 2 * isqrt(C) + 1;
- f = 0;
- while (f == 0) {
- print "A =", a;
- x.x = 1;
- x.y = 1;
- print 2, x;
- x = x ^ (2 ^ (highbit(C) + 1));
- for (p = 3; ((p < B) && (f == 0)); p += 2) {
- if (!ptest(p, 1))
- continue;
- print p, x;
- x = x ^ (p ^ ((highbit(C) // highbit(p)) + 1));
- }
- a++;
- b--;
- }
- return f;
- }
-
-
- define point_print(p)
- {
- print "(" : p.x : "," : p.y : ")" :;
- }
-
-
- define point_mul(p1, p2)
- {
- local r, m;
-
- if (p2 == 1)
- return p1;
- if (p1 == p2)
- return point_square(&p1);
- obj point r;
- m = (minv(p2.x - p1.x, N) * (p2.y - p1.y)) % N;
- if (m == 0) {
- if (f == 0)
- f = gcd(p2.x - p1.x, N);
- r.x = 1;
- r.y = 1;
- return r;
- }
- r.x = (m^2 - p1.x - p2.x) % N;
- r.y = ((m * (p1.x - r.x)) - p1.y) % N;
- return r;
- }
-
-
- define point_square(p)
- {
- local r, m;
-
- obj point r;
- m = ((3 * p.x^2 + a) * minv(p.y << 1, N)) % N;
- if (m == 0) {
- if (f == 0)
- f = gcd(p.y << 1, N);
- r.x = 1;
- r.y = 1;
- return r;
- }
- r.x = (m^2 - p.x - p.x) % N;
- r.y = ((m * (p.x - r.x)) - p.y) % N;
- return r;
- }
-
-
- define point_pow(p, pow)
- {
- local bit, r, t;
-
- r = 1;
- if (isodd(pow))
- r = p;
- t = p;
- for (bit = 2; ((bit <= pow) && (f == 0)); bit <<= 1) {
- t = point_square(&t);
- if (bit & pow)
- r = point_mul(&t, &r);
- }
- return r;
- }
-
- global lib_debug;
- if (lib_debug >= 0) {
- print "factor(N, I, B, force) defined";
- }
-