williams+1.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /**
  2. * \file williams+1.c
  3. * \brief An implementation of William's p+1 Attack.
  4. *
  5. * William's attack, published in 1982, describes a factorization algorithm
  6. * based on lucas sequences and Lehmer's theorem.
  7. *
  8. */
  9. #include "config.h"
  10. #include <stdint.h>
  11. #include <openssl/rsa.h>
  12. #include <openssl/bn.h>
  13. #include "qa/questions/primes.h"
  14. #include "qa/questions/qarith.h"
  15. #include "qa/questions/questions.h"
  16. #include "qa/questions/qwilliams.h"
  17. #define MAX_ATTEMPTS 10
  18. #define PRIMES_LIM 1000
  19. /**
  20. * \brief Lucas Sequence Multiplier.
  21. *
  22. * Given a pair <Vᵢ, Vᵢ₋₁>, terms of a lucas sequence with parameter τ,
  23. * compute <Vₕᵢ, Vₕᵢ₋₁>
  24. */
  25. void
  26. lucas(BIGNUM *v, BIGNUM *h,
  27. BIGNUM *n, BN_CTX *ctx)
  28. {
  29. BIGNUM *w;
  30. BIGNUM *vv;
  31. BIGNUM *vw;
  32. BIGNUM *tau;
  33. int i;
  34. w = BN_new();
  35. vv = BN_new();
  36. vw = BN_new();
  37. tau = BN_dup(v);
  38. BN_mod_sqr(vv, v, n, ctx);
  39. BN_mod_sub(w, vv, BN_value_two(), n, ctx);
  40. for (i = BN_num_bits(h); !BN_is_bit_set(h, i); i--);
  41. for (i--; i >= 0; i--) {
  42. if (BN_is_bit_set(h, i)) {
  43. /* v = vw - τ (mod N) */
  44. BN_mod_mul(vw, v, w, n, ctx);
  45. BN_mod_sub(v, vw, tau, n, ctx);
  46. /* w = w² - 2 */
  47. BN_mod_sqr(vv, w, n, ctx);
  48. BN_mod_sub(w, vv, BN_value_two(), n, ctx);
  49. } else {
  50. /* w = vw - τ (mod N) */
  51. BN_mul(vw, v, w, ctx);
  52. BN_mod_sub(w, vw, tau, n, ctx);
  53. /* v = v² - 2 */
  54. BN_mod_sqr(vv, v, n, ctx);
  55. BN_mod_sub(v, vv, BN_value_two(), n, ctx);
  56. }
  57. }
  58. BN_free(w);
  59. BN_free(tau);
  60. BN_free(vv);
  61. BN_free(vw);
  62. }
  63. static BIGNUM*
  64. williams_factorize(BIGNUM *n, BIGNUM *v, BN_CTX *ctx)
  65. {
  66. BIGNUM *ret = NULL;
  67. BIGNUM
  68. *v2 = BN_new(),
  69. *q = BN_new(),
  70. *p = BN_new(),
  71. *g = BN_new();
  72. int e, k, j, m = 100;
  73. pit_t *pit;
  74. struct {
  75. BIGNUM *p;
  76. BIGNUM *v;
  77. int k;
  78. } back = {BN_new(), BN_new(), 0};
  79. BN_copy(back.v, v);
  80. BN_copy(back.p, BN_value_two());
  81. BN_one(g);
  82. BN_one(q);
  83. #ifdef HAVE_OPENMPI
  84. for (pit = primes_init();
  85. BN_is_one(g) && primes_next(pit, p);
  86. ) {
  87. #else
  88. pit = primes_init();
  89. for (int lim=PRIMES_LIM;
  90. lim && BN_is_one(g) && primes_next(pit, p);
  91. lim--) {
  92. #endif
  93. #ifdef DEBUG
  94. fprintf(stderr, "Testing prime: ");
  95. BN_print_fp(stderr, p);
  96. fprintf(stderr, "\r");
  97. #endif
  98. e = 10; // BN_num_bits(n) / BN_num_bits(p) + 1;
  99. for (k = 0; k < e && BN_is_one(g); k += m) {
  100. for (j = (m > e) ? e : m; j; j--) {
  101. lucas(v, p, n, ctx);
  102. /* q = v - 2 */
  103. BN_mod_sub(v2, v, BN_value_two(), n, ctx);
  104. BN_mod_mul(q, q, v2, n, ctx);
  105. }
  106. /* gcd test */
  107. BN_gcd(g, q, n, ctx);
  108. if (BN_is_one(g)) {
  109. BN_copy(back.p, p);
  110. BN_copy(back.v, v);
  111. back.k = k;
  112. }
  113. }
  114. }
  115. if (!BN_cmp(g, n)) {
  116. #ifdef DEBUG
  117. printf("rollback!\n");
  118. #endif
  119. BN_copy(p, back.p);
  120. BN_one(g);
  121. BN_copy(v, back.v);
  122. e = BN_num_bits(n) / BN_num_bits(p) + 5;
  123. for (k = back.k; k < e; k++) {
  124. lucas(v, p, n, ctx);
  125. BN_sub(v2, v, BN_value_two());
  126. BN_gcd(g, v2, n, ctx);
  127. if (!BN_is_one(g)) break;
  128. }
  129. }
  130. if (!BN_is_one(g) && BN_cmp(g, n))
  131. ret = g;
  132. else
  133. BN_free(g);
  134. BN_free(back.v);
  135. BN_free(back.p);
  136. BN_free(v2);
  137. BN_free(p);
  138. BN_free(q);
  139. prime_iterator_free(pit);
  140. return ret;
  141. }
  142. /**
  143. * \brief William's p+1 factorization.
  144. *
  145. */
  146. static RSA*
  147. williams_question_ask_rsa(const RSA* rsa)
  148. {
  149. int i;
  150. BIGNUM* v = BN_new();
  151. BN_CTX *ctx = BN_CTX_new();
  152. BIGNUM *g;
  153. RSA *ret = NULL;
  154. for (i=0; !ret && i!= MAX_ATTEMPTS; i++) {
  155. BN_pseudo_rand_range(v, rsa->n);
  156. g = williams_factorize(rsa->n, v, ctx);
  157. if (g)
  158. ret = qa_RSA_recover(rsa, g, ctx);
  159. }
  160. BN_free(v);
  161. BN_CTX_free(ctx);
  162. return ret;
  163. }
  164. qa_question_t WilliamsQuestion = {
  165. .name = "p+1",
  166. .pretty_name = "Williams' p+1 factorization",
  167. .ask_rsa = williams_question_ask_rsa
  168. };