pollard.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * \file pollard.c
  3. *
  4. * \brief Pollard's (p-1) factorization algorithm.
  5. *
  6. * This file contains an implementations of Pollard's (p-1) algorithm, used to
  7. * attack the public modulus of RSA.
  8. *
  9. * Consider the public modulus N = pq. Now,
  10. * (p-1) = q₀ᵉ⁰q₁ᵉ¹… qₖᵉᵏ . q₀ᵉ⁰ < q₁ᵉ¹ < … < qₖᵉᵏ ≤ B
  11. * implies that (p-1) | B! , since all factors of (p-1) belongs to {1, …, B}.
  12. * Consider a ≡ 2^(B!) (mod N)
  13. * a = 2^(B!) + kN = 2^(B!) + kqp → a ≡ 2^(B!) (mod p)
  14. * Since
  15. * <pre>
  16. *
  17. * ⎧ 2ᵖ⁻¹ ≡ 1 (mod p) ⎧ p | (a-1)
  18. * ⎨ → a ≡ 2^(B!) ≡ 1 (mod p) → ⎨ → p | gcd(a-1, N)
  19. * ⎩ p-1 | B! ⎩ p | N
  20. *
  21. * </pre>
  22. * And gcd(a-1, N) is a non-trivial factor of N, unless a = 1.
  23. */
  24. #include <openssl/x509.h>
  25. #include <openssl/err.h>
  26. #include "qa/questions/questions.h"
  27. #include "qa/questions/primes.h"
  28. #include "qa/questions/qarith.h"
  29. #include "qa/questions/qpollard.h"
  30. /* limits of primes. NOT used in cluster. */
  31. #define PRIMES_LIM 1000
  32. /**
  33. * \brief Pollard (p-1) factorization.
  34. *
  35. */
  36. static RSA*
  37. pollard1_question_ask_rsa(const RSA* rsa)
  38. {
  39. RSA *ret = NULL;
  40. BIGNUM
  41. *p = BN_new(),
  42. *b = BN_new(),
  43. *b1 = BN_new(),
  44. *q = BN_new(),
  45. *r = BN_new(),
  46. *g = BN_new();
  47. BN_CTX *ctx = BN_CTX_new();
  48. pit_t *it;
  49. long j;
  50. struct {
  51. BIGNUM *p;
  52. BIGNUM *b;
  53. int k;
  54. } back = {BN_new(), BN_new(), 0};
  55. int e, k, m = 100;
  56. BN_pseudo_rand_range(b, rsa->n);
  57. /* initialize backup */
  58. BN_copy(back.p, BN_value_two());
  59. BN_copy(back.b, b);
  60. BN_one(g);
  61. BN_one(q);
  62. #ifdef HAVE_OPENMPI
  63. for (it = primes_init();
  64. BN_is_one(g) && primes_next(it, p);
  65. ) {
  66. #else
  67. it = primes_init();
  68. for (int lim=PRIMES_LIM;
  69. lim && BN_is_one(g) && primes_next(it, p);
  70. lim--) {
  71. #endif
  72. e = BN_num_bits(rsa->n) / BN_num_bits(p) + 1;
  73. for (k = 0; k < e && BN_is_one(g); k += m) {
  74. for (j = (m > e) ? e : m; j; j--) {
  75. BN_mod_exp(b, b, p, rsa->n, ctx);
  76. BN_sub(b1, b, BN_value_one());
  77. BN_mod_mul(q, q, b1, rsa->n, ctx);
  78. }
  79. BN_gcd(g, q, rsa->n, ctx);
  80. /* epoch ended: backup */
  81. if (BN_is_one(g)) {
  82. BN_copy(back.p, p);
  83. BN_copy(back.b, b);
  84. back.k = k;
  85. }
  86. }
  87. }
  88. /* replay latest epoch */
  89. if (!BN_cmp(g, rsa->n)) {
  90. #ifdef DEBUG
  91. fprintf(stderr, "rollback!\n");
  92. #endif
  93. BN_copy(p, back.p);
  94. BN_one(g);
  95. BN_copy(b, back.b);
  96. e = BN_num_bits(rsa->n) / BN_num_bits(p) + 1;
  97. for (k = back.k; k < e; k++) {
  98. BN_mod_exp(b, b, p, rsa->n, ctx);
  99. BN_sub(b1, b, BN_value_one());
  100. BN_gcd(g, b1, rsa->n, ctx);
  101. if (BN_is_one(g)) break;
  102. }
  103. }
  104. if (BN_cmp(g, rsa->n) && !BN_is_one(g))
  105. ret = qa_RSA_recover(rsa, g, ctx);
  106. BN_free(back.p);
  107. BN_free(back.b);
  108. BN_free(p);
  109. BN_free(q);
  110. BN_free(b);
  111. BN_free(b1);
  112. BN_free(r);
  113. BN_free(g);
  114. BN_CTX_free(ctx);
  115. return ret;
  116. }
  117. qa_question_t PollardQuestion = {
  118. .name = "p-1",
  119. .pretty_name = "Pollard's (p-1) factorization",
  120. .setup = NULL,
  121. .teardown = NULL,
  122. .test = NULL,
  123. .ask_rsa = pollard1_question_ask_rsa,
  124. .ask_crt = NULL
  125. };