factorization_with_difference_of_prime_factors.pl 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 09 August 2017
  4. # https://github.com/trizen
  5. # Theorem:
  6. # If the absolute difference between the prime factors of a
  7. # semiprime `n` is known, then `n` can be factored in polynomial time.
  8. # For example:
  9. # n = 97 * 43
  10. # n = 4171
  11. #
  12. # d = 97 - 43
  13. # d = 54
  14. # Then the factors of `n` are:
  15. # 43 = abs((-54 + sqrt(54^2 + 4*4171)) / 2)
  16. # 97 = abs((-54 - sqrt(54^2 + 4*4171)) / 2)
  17. # In general:
  18. # n = p * q
  19. # d = abs(p - q)
  20. # From which `n` can be factored as:
  21. # n = abs((-d + sqrt(d^2 + 4*n)) / 2) *
  22. # abs((-d - sqrt(d^2 + 4*n)) / 2)
  23. #
  24. # Based on the following quadratic equation:
  25. # x^2 + (a - b)*x - a*b = 0
  26. #
  27. # which has the solutions:
  28. # x₁ = -a
  29. # x₂ = +b
  30. use 5.010;
  31. use strict;
  32. use warnings;
  33. use ntheory qw(random_nbit_prime);
  34. use Math::AnyNum qw(:overload isqrt);
  35. my $p = Math::AnyNum->new(random_nbit_prime(100));
  36. my $q = Math::AnyNum->new(random_nbit_prime(100));
  37. my $d = abs($p - $q);
  38. my $n = $p * $q;
  39. say "n = $p * $q";
  40. say "d = $d";
  41. sub integer_quadratic_formula {
  42. my ($x, $y, $z) = @_;
  43. (
  44. ((-$y + isqrt($y**2 - 4 * $x * $z)) / (2 * $x)),
  45. ((-$y - isqrt($y**2 - 4 * $x * $z)) / (2 * $x)),
  46. );
  47. }
  48. my ($x1, $x2) = integer_quadratic_formula(1, $d, -$n);
  49. printf("n = %s * %s\n", abs($x1), abs($x2));
  50. if (abs($x1) * abs($x2) != $n) {
  51. die "error: $x1 * $x2 != $n\n";
  52. }