phi-finder_factorization_method.pl 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/perl
  2. # A new factorization algorithm for semiprimes, by estimating phi(n).
  3. # The algorithm is called "Phi-Finder" and is due to Kyle Kloster (2010), described in his thesis:
  4. # Factoring a semiprime n by estimating φ(n)
  5. # See also:
  6. # http://gregorybard.com/papers/phi_version_may_7.pdf
  7. use 5.020;
  8. use strict;
  9. use warnings;
  10. use experimental qw(signatures);
  11. use Math::GMPz;
  12. use ntheory qw(is_prime is_square sqrtint logint powmod random_nbit_prime);
  13. sub phi_factor($n) {
  14. return () if $n <= 1;
  15. return ($n) if is_prime($n);
  16. if (is_square($n)) {
  17. return sqrtint($n);
  18. }
  19. $n = Math::GMPz->new($n);
  20. my $E = $n - 2 * sqrtint($n) + 1;
  21. my $E0 = Math::GMPz->new(powmod(2, -$E, $n));
  22. my $L = logint($n, 2);
  23. my $i = 0;
  24. while ($E0 & ($E0 - 1)) {
  25. $E0 <<= $L;
  26. $E0 %= $n;
  27. ++$i;
  28. }
  29. my $t = 0;
  30. foreach my $k (0 .. $L) {
  31. if (powmod(2, $k, $n) == $E0) {
  32. $t = $k;
  33. last;
  34. }
  35. }
  36. my $phi = abs($i * $L - $E - $t);
  37. my $q = ($n - $phi + 1);
  38. my $p = ($q + sqrtint($q * $q - 4 * $n)) >> 1;
  39. return $p;
  40. }
  41. foreach my $k (10 .. 30) {
  42. my $n = Math::GMPz->new(random_nbit_prime($k)) * random_nbit_prime($k);
  43. my $p = phi_factor($n);
  44. say "$n = ", $p, ' * ', $n / $p;
  45. }