pollard.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. static BIGNUM *two = NULL;
  31. static int
  32. pollard1_question_setup(void)
  33. {
  34. /* create 2 */
  35. BN_dec2bn(&two, "2");
  36. return 1;
  37. }
  38. static int
  39. pollard1_question_teardown(void)
  40. {
  41. BN_free(two);
  42. return 1;
  43. }
  44. /**
  45. * \brief Pollard (p-1) factorization.
  46. *
  47. */
  48. static RSA*
  49. pollard1_question_ask_rsa(const RSA* rsa)
  50. {
  51. RSA *ret = NULL;
  52. BIGNUM
  53. *p = BN_new(),
  54. *b = BN_new(),
  55. *b1 = BN_new(),
  56. *q = BN_new(),
  57. *r = BN_new(),
  58. *g = BN_new();
  59. BN_CTX *ctx = BN_CTX_new();
  60. pit_t *it;
  61. long j;
  62. /* long back; */
  63. int e, k, m = 100;
  64. BN_pseudo_rand_range(b, rsa->n);
  65. BN_one(g);
  66. BN_one(q);
  67. for (it = primes_init();
  68. BN_is_one(g) && primes_next(it, p);
  69. ) {
  70. e = BN_num_bits(rsa->n) / BN_num_bits(p);
  71. for (k = 0; k < e && BN_is_one(g); k += m) {
  72. /* back = primes_tell(it); */
  73. for (j = (m > e) ? e : m; j; j--) {
  74. BN_mod_exp(b, b, p, rsa->n, ctx);
  75. BN_sub(b1, b, BN_value_one());
  76. BN_mod_mul(q, q, b1, rsa->n, ctx);
  77. }
  78. BN_gcd(g, q, rsa->n, ctx);
  79. }
  80. }
  81. /* replay latest epoch */
  82. /* if (BN_cmp(g, rsa->n)) { */
  83. /* primes_seek(it, back); */
  84. /* } */
  85. if (BN_cmp(g, rsa->n) && !BN_is_one(g))
  86. ret = qa_RSA_recover(rsa, g, ctx);
  87. BN_free(p);
  88. BN_free(q);
  89. BN_free(b);
  90. BN_free(b1);
  91. BN_free(r);
  92. BN_free(g);
  93. BN_CTX_free(ctx);
  94. return ret;
  95. }
  96. qa_question_t PollardQuestion = {
  97. .name = "p-1",
  98. .pretty_name = "Pollard's (p-1) factorization",
  99. .setup = pollard1_question_setup,
  100. .teardown = pollard1_question_teardown,
  101. .test = NULL,
  102. .ask_rsa = pollard1_question_ask_rsa,
  103. .ask_crt = NULL
  104. };