Browse Source

Williams: perform multiple attempts for the initial v_i.

We are looking for a particoular legendre symbol for the initial V₀, so many
attempts might be necessary.
Michele Orrù 10 years ago
parent
commit
cb7242c80c
2 changed files with 67 additions and 17 deletions
  1. 20 1
      src/questions/tests/test_williams+1.c
  2. 47 16
      src/questions/williams+1.c

+ 20 - 1
src/questions/tests/test_williams+1.c

@@ -68,7 +68,7 @@ void test_lehmer_thm(void)
     *g = BN_new();
   BN_CTX *ctx = BN_CTX_new();
 
-  BN_dec2bn(&v, "1");
+  BN_dec2bn(&v, "2");
   BN_dec2bn(&p,
             "181857351165158586099319592412492032999818333818932850952491024"
             "131283899677766672100915923041329384157985577418702469610834914"
@@ -88,9 +88,28 @@ void test_lehmer_thm(void)
   BN_gcd(g, v2, n, ctx);
   assert(!BN_is_one(g));
 
+  /* another test */
+  BN_dec2bn(&v, "3");
+  BN_dec2bn(&p,
+            "181857351165158586099319592412492032999818333818932850952491024"
+            "131283899677766672100915923041329384157985577418702469610834914"
+            "62963937435544948718405055999");
+  BN_generate_prime(q, 512, 1, NULL, NULL, NULL, NULL);
+  BN_mul(n, p, q, ctx);
+
+  BN_sub(h, p, BN_value_one());
+  BN_mul(h, h, BN_value_two(), ctx);
+  lucas(v, h, n, ctx);
+
+  BN_mod_sub(v2, v, BN_value_two(), n, ctx);
+  BN_gcd(g, v2, n, ctx);
+  assert(!BN_is_one(g));
+  assert(BN_cmp(g, n));
+
   BN_free(q);
   BN_free(p);
   BN_free(v);
+  BN_free(v2);
   BN_free(h);
 
   BN_CTX_free(ctx);

+ 47 - 16
src/questions/williams+1.c

@@ -6,6 +6,8 @@
  * based on lucas sequences and Lehmer's theorem.
  *
  */
+#include "config.h"
+
 #include <stdint.h>
 
 #include <openssl/rsa.h>
@@ -16,6 +18,9 @@
 #include "qa/questions/questions.h"
 #include "qa/questions/qwilliams.h"
 
+
+#define MAX_ATTEMPTS 10
+
 /**
  * \brief Lucas Sequence Multiplier.
  *
@@ -65,24 +70,16 @@ lucas(BIGNUM *v, BIGNUM *h,
   BN_free(vw);
 }
 
-
-/**
- * \brief William's p+1 factorization.
- *
- */
-static RSA*
-williams_question_ask_rsa(const RSA* rsa)
+static BIGNUM*
+williams_factorize(BIGNUM *n, BIGNUM *v, BN_CTX *ctx)
 {
-  RSA *ret = NULL;
+  BIGNUM *ret = NULL;
   BIGNUM
-    *v = BN_new(),
     *v2 = BN_new(),
-    *n = rsa->n,
     *q = BN_new(),
     *p = BN_new(),
     *g = BN_new();
   int e, k, j, m = 100;
-  BN_CTX *ctx = BN_CTX_new();
   pit_t *pit;
   struct {
     BIGNUM *p;
@@ -90,7 +87,6 @@ williams_question_ask_rsa(const RSA* rsa)
     int k;
   } back = {BN_new(), BN_new(), 0};
 
-  BN_pseudo_rand(v, BN_num_bits(n) / 2 + 2, 0, 0);
   BN_copy(back.v, v);
   BN_copy(back.p, BN_value_two());
 
@@ -99,7 +95,13 @@ williams_question_ask_rsa(const RSA* rsa)
   for (pit = primes_init();
        BN_is_one(g) && primes_next(pit, p);
        ) {
-    e = BN_num_bits(n) / BN_num_bits(p) + 1;
+#ifdef DEBUG
+    fprintf(stderr, "Testing prime: ");
+    BN_print_fp(stderr, p);
+    fprintf(stderr, "\r");
+#endif
+
+    e = 10; // BN_num_bits(n) / BN_num_bits(p) + 1;
     for (k = 0; k < e && BN_is_one(g); k += m) {
       for (j = (m > e) ? e : m; j; j--) {
         lucas(v, p, n, ctx);
@@ -119,7 +121,9 @@ williams_question_ask_rsa(const RSA* rsa)
   }
 
   if (!BN_cmp(g, n)) {
+#ifdef DEBUG
     printf("rollback!\n");
+#endif
     BN_copy(p, back.p);
     BN_one(g);
     BN_copy(v, back.v);
@@ -132,20 +136,47 @@ williams_question_ask_rsa(const RSA* rsa)
     }
   }
   if (!BN_is_one(g) && BN_cmp(g, n))
-    ret = qa_RSA_recover(rsa, g, ctx);
+    ret = g;
+  else
+    BN_free(g);
 
   BN_free(back.v);
   BN_free(back.p);
-  BN_free(v);
   BN_free(v2);
   BN_free(p);
   BN_free(q);
-  BN_free(g);
   prime_iterator_free(pit);
 
   return ret;
 }
 
+/**
+ * \brief William's p+1 factorization.
+ *
+ */
+static RSA*
+williams_question_ask_rsa(const RSA* rsa)
+{
+  int i;
+  BIGNUM* v = BN_new();
+  BN_CTX *ctx = BN_CTX_new();
+  BIGNUM *g;
+  RSA *ret = NULL;
+
+  for (i=0; !ret &&  i!= MAX_ATTEMPTS; i++) {
+    BN_pseudo_rand_range(v, rsa->n);
+    g = williams_factorize(rsa->n, v, ctx);
+    if (g)
+      ret = qa_RSA_recover(rsa, g, ctx);
+  }
+
+  BN_free(v);
+  BN_CTX_free(ctx);
+  return ret;
+}
+
+
+
 qa_question_t WilliamsQuestion = {
   .name = "p+1",
   .pretty_name = "Williams' p+1 factorization",