Parcourir la source

Fixing lucas sequences.

Michele Orrù il y a 11 ans
Parent
commit
828045bdda

+ 1 - 2
src/questions/include/qwilliams.h

@@ -4,8 +4,7 @@
 extern struct qa_question WilliamsQuestion;
 
 void lucas(BIGNUM *v, BIGNUM *w,
-           BIGNUM *h, BIGNUM *tau,
-           BIGNUM *n, BN_CTX *ctx);
+           BIGNUM *h, BN_CTX *ctx);
 
 
 #endif /* _QA_WILLIAMS_H_ */

+ 34 - 38
src/questions/tests/test_williams+1.c

@@ -8,49 +8,51 @@
 
 void test_lucas(void)
 {
-  BIGNUM *v = BN_new();
-  BIGNUM *w = BN_new();
-  BIGNUM *h = BN_new();
-  BIGNUM *n = BN_new();
-  BIGNUM *tau = BN_new();
   BIGNUM
-    *vcheck = BN_new(),
-    *wcheck = BN_new();
+    *v = BN_new(),
+    *h = BN_new(),
+    *n = BN_new(),
+    *vcheck = BN_new();
   BN_CTX *ctx = BN_CTX_new();
 
-  BN_copy(w, BN_value_two());
-  BN_dec2bn(&tau, "5");
-  BN_copy(v, tau);
+  BN_dec2bn(&v, "5");
   BN_dec2bn(&n, "100000000000");
 
-  /* <V₁, V₀> */
-  assert(!BN_cmp(v, tau));
-  assert(!BN_cmp(w, BN_value_two()));
   /* <V₃, V₂> */
   BN_dec2bn(&h, "3");
   BN_dec2bn(&vcheck, "110");
-  BN_dec2bn(&wcheck, "23");
-
-  lucas(v, w, h, tau, n, ctx);
-  assert(!BN_cmp(wcheck, w));
-  BN_print_fp(stderr, v);
+  lucas(v, h, n, ctx);
   assert(!BN_cmp(vcheck, v));
-
   /* <V₆, V₅> */
   BN_dec2bn(&h, "2");
   BN_dec2bn(&vcheck, "12098");
-  BN_dec2bn(&wcheck, "2525");
-
-  lucas(v, w, h, tau, n, ctx);
-  assert(!BN_cmp(wcheck, w));
+  lucas(v, h, n, ctx);
   assert(!BN_cmp(vcheck, v));
 
-  BN_free(tau);
+
+  /* another sequence */
+  BN_dec2bn(&v, "5");
+  BN_dec2bn(&n, "100");
+
+  BN_dec2bn(&h, "11");
+  BN_dec2bn(&vcheck, "45");
+  lucas(v, h, n, ctx);
+  assert(!BN_cmp(v, vcheck));
+
+  BN_dec2bn(&h, "9");
+  BN_dec2bn(&vcheck, "30");
+  lucas(v, h, n, ctx);
+  assert(!BN_cmp(v, vcheck));
+
+  BN_dec2bn(&h, "3");
+  BN_dec2bn(&vcheck, "10");
+  lucas(v, h, n, ctx);
+  assert(!BN_cmp(v, vcheck));
+
+
   BN_free(v);
-  BN_free(w);
   BN_free(h);
   BN_free(vcheck);
-  BN_free(wcheck);
   BN_CTX_free(ctx);
 }
 
@@ -58,18 +60,15 @@ void test_lehmer_thm(void)
 {
   BIGNUM
     *v = BN_new(),
-    *w = BN_new(),
+    *v2 = BN_new(),
     *h = BN_new(),
     *n = BN_new(),
-    *tau = BN_new(),
     *p = BN_new(),
     *q = BN_new(),
     *g = BN_new();
   BN_CTX *ctx = BN_CTX_new();
 
-  BN_copy(w, BN_value_two());
-  BN_dec2bn(&tau, "2");
-  BN_copy(v, tau);
+  BN_dec2bn(&v, "1");
   BN_dec2bn(&p,
             "181857351165158586099319592412492032999818333818932850952491024"
             "131283899677766672100915923041329384157985577418702469610834914"
@@ -84,17 +83,14 @@ void test_lehmer_thm(void)
             "181857351165158586099319592412492032999818333818932850952491024"
             "131283899677766672100915923041329384157985577418702469610834914"
             "6296393743554494871840505600");
-  lucas(v, w, h, tau, n, ctx);
-  BN_sub(v, v, BN_value_two());
-  BN_gcd(g, v, n, ctx);
-  assert(!BN_is_one(g) && !BN_cmp(g, n));
-
+  lucas(v, h, n, ctx);
+  BN_sub(v2, v, BN_value_two());
+  BN_gcd(g, v2, n, ctx);
+  assert(!BN_is_one(g));
 
   BN_free(q);
   BN_free(p);
-  BN_free(tau);
   BN_free(v);
-  BN_free(w);
   BN_free(h);
 
   BN_CTX_free(ctx);

+ 26 - 30
src/questions/williams+1.c

@@ -22,46 +22,52 @@
  * compute <Vₕᵢ, Vₕᵢ₋₁>
  */
 void
-lucas(BIGNUM *v, BIGNUM *w,
-      BIGNUM *h, BIGNUM *tau,
+lucas(BIGNUM *v, BIGNUM *h,
       BIGNUM *n, BN_CTX *ctx)
 {
+  BIGNUM *w;
   BIGNUM *vv;
   BIGNUM *vw;
   BIGNUM *u;
+  BIGNUM *tau;
+  int i;
+
+  w = BN_dup(BN_value_two());
+  tau = BN_dup(v);
 
   vv = BN_new();
   vw = BN_new();
   u = BN_new();
 
-  for (;
-       !BN_is_one(h);
-       BN_rshift1(h, h)) {
-    if (BN_is_odd(h)) {
+  for (i = BN_num_bits(h); !BN_is_bit_set(h, i); i--);
+  for (i--; i >= 0; i--) {
+    if (BN_is_bit_set(h, i)) {
       BN_mod_sqr(vv, v, n, ctx);
       /* v = τv² - vw - τ */
       BN_mod_mul(u, tau, vv, n, ctx);
       BN_mod_mul(vw, v, w, n, ctx);
-      BN_sub(u, u, vw);
-      BN_sub(u, u, tau);
+      BN_mod_sub(u, u, vw, n, ctx);
+      BN_mod_sub(u, u, tau, n, ctx);
       /* w = w² - 2 */
       BN_sub(w, vv, BN_value_two());
     } else {
-      BN_mod_sqr(vv, v, n, ctx);
+      BN_sqr(vv, v, ctx);
       /* v = v² - 2 */
       BN_sub(u, vv, BN_value_two());
       /* w = vw - τ */
-      BN_mod_mul(vw, v, w, n, ctx);
+      BN_mul(vw, v, w, ctx);
       BN_sub(w, vw, tau);
     }
     BN_copy(v, u);
   }
 
+  BN_free(w);
   BN_free(u);
   BN_free(vv);
   BN_free(vw);
 }
 
+
 /**
  * \brief William's p+1 factorization.
  *
@@ -73,41 +79,34 @@ williams_question_ask_rsa(const RSA* rsa)
   BIGNUM
     *v = BN_new(),
     *v2 = BN_new(),
-    *w = BN_new(),
     *n = rsa->n,
-    *tau = BN_new(),
     *q = BN_new(),
     *p = BN_new(),
     *g = BN_new();
-  int e, k, j, m = 50;
+  int e, k, j, m = 100;
   BN_CTX *ctx = BN_CTX_new();
   pit_t *pit;
   struct {
     BIGNUM *p;
     BIGNUM *v;
-    BIGNUM *w;
     int k;
-  } back = {BN_new(), BN_new(), BN_new(), 0};
+  } back = {BN_new(), BN_new(), 0};
 
-  BN_one(w); BN_uiadd1(w);
-  BN_pseudo_rand_range(tau, n);
-  BN_copy(v, tau);
+  BN_pseudo_rand(v, BN_num_bits(n) / 2 + 2, 0, 0);
   BN_copy(back.v, v);
-  BN_copy(back.w, w);
   BN_copy(back.p, BN_value_two());
-  back.k = 0;
 
   BN_one(g);
   BN_one(q);
   for (pit = primes_init();
        BN_is_one(g) && primes_next(pit, p);
        ) {
-    e = BN_num_bits(n) / (BN_num_bits(p)) + 1;
+    e = 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, w, p, tau, n, ctx);
+        lucas(v, p, n, ctx);
         /* q = v - 2 */
-        BN_sub(v2, v, BN_value_two());
+        BN_mod_sub(v2, v, BN_value_two(), n, ctx);
         BN_mod_mul(q, q, v2, n, ctx);
       }
       /* gcd test */
@@ -116,34 +115,31 @@ williams_question_ask_rsa(const RSA* rsa)
       if (BN_is_one(g)) {
         BN_copy(back.p, p);
         BN_copy(back.v, v);
-        BN_copy(back.w, w);
         back.k = k;
       }
     }
   }
 
   if (!BN_cmp(g, n)) {
+    printf("rollback!\n");
     BN_copy(p, back.p);
     BN_one(g);
     BN_copy(v, back.v);
-    BN_copy(w, back.w);
+    e = BN_num_bits(n) / BN_num_bits(p) + 5;
     for (k = back.k; k < e; k++) {
-      lucas(v, w, p, tau, n, ctx);
+      lucas(v, p, n, ctx);
       BN_sub(v2, v, BN_value_two());
       BN_gcd(g, v2, n, ctx);
-      if (BN_is_one(g)) break;
+      if (!BN_is_one(g)) break;
     }
   }
   if (!BN_is_one(g) && BN_cmp(g, n))
     ret = qa_RSA_recover(rsa, g, ctx);
 
   BN_free(back.v);
-  BN_free(back.w);
   BN_free(back.p);
   BN_free(v);
   BN_free(v2);
-  BN_free(w);
-  BN_free(tau);
   BN_free(p);
   BN_free(q);
   BN_free(g);