Kaynağa Gözat

Everything is SO fucked up.

* implementing backups in pollard and williams;
* avoiding fucking memory leaks in the recovery of private rsa key
* fixing stupid string formatting bash
* asserting mathematic still works, specifically lehmer's theorem.
Michele Orrù 11 yıl önce
ebeveyn
işleme
31d54c5a60

+ 2 - 0
src/apps/gen.c

@@ -5,6 +5,7 @@
  */
 #define _GNU_SOURCE
 
+#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,6 +44,7 @@ pubkey_generation(RSA* rsa)
     rsa->n = BN_new();
     BN_mul(rsa->n, rsa->p, rsa->q, ctx);
   }
+  assert(BN_is_odd(rsa->n));
 
   PEM_write_RSAPublicKey(stdout, rsa);
 

+ 2 - 4
src/apps/tests/test_gen_pub.test

@@ -12,10 +12,8 @@ fi
 
 
 # <http://cryptowars2011.forumfree.it/?t=58954862>
-p='5596931086554284281185296406554840964858720713572245165038844132225787390922\
-226340619345603534845283511495476913891096668345376424228245705523358529690689'
-q='5596931086554284281185296406554840964858720713572245165038844132225787390922\
-226340619345603534845283511495476913891096668345376424228245705523358529692809'
+p='5596931086554284281185296406554840964858720713572245165038844132225787390922226340619345603534845283511495476913891096668345376424228245705523358529690689'
+q='5596931086554284281185296406554840964858720713572245165038844132225787390922226340619345603534845283511495476913891096668345376424228245705523358529692809'
 ./gen pub -p $p -q $q -e 29
 if [ $? -ne 0 ]
 then

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

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

+ 33 - 7
src/questions/pollard.c

@@ -49,36 +49,62 @@ pollard1_question_ask_rsa(const RSA* rsa)
   BN_CTX *ctx = BN_CTX_new();
   pit_t *it;
   long j;
-  /* long back; */
-  int e, k, m = 100;
+  struct {
+    BIGNUM *p;
+    BIGNUM *b;
+    int k;
+  } back = {BN_new(), BN_new(), 0};
 
+  int e, k, m = 100;
 
   BN_pseudo_rand_range(b, rsa->n);
+  /* initialize backup */
+  BN_copy(back.p, BN_value_two());
+  BN_copy(back.b, b);
+
   BN_one(g);
   BN_one(q);
   for (it = primes_init();
        BN_is_one(g) && primes_next(it, p);
        )  {
-    e = BN_num_bits(rsa->n) / BN_num_bits(p);
+    e = BN_num_bits(rsa->n) / BN_num_bits(p) + 1;
     for (k = 0; k < e && BN_is_one(g); k += m) {
-      /* back = primes_tell(it); */
       for (j = (m > e) ? e : m; j; j--) {
         BN_mod_exp(b, b, p, rsa->n, ctx);
         BN_sub(b1, b, BN_value_one());
         BN_mod_mul(q, q, b1, rsa->n, ctx);
       }
       BN_gcd(g, q, rsa->n, ctx);
+
+      /* epoch ended: backup */
+      if (BN_is_one(g)) {
+        BN_copy(back.p, p);
+        BN_copy(back.b, b);
+        back.k = k;
+      }
     }
   }
 
   /* replay latest epoch */
-  /* if (BN_cmp(g, rsa->n)) { */
-  /*   primes_seek(it, back); */
+  if (!BN_cmp(g, rsa->n)) {
+    fprintf(stderr, "rollback!\n");
+    BN_copy(p, back.p);
+    BN_one(g);
+    BN_copy(b, back.b);
+    e = BN_num_bits(rsa->n) / BN_num_bits(p) + 1;
+    for (k = back.k; k < e; k++) {
+      BN_mod_exp(b, b, p, rsa->n, ctx);
+      BN_sub(b1, b, BN_value_one());
+      BN_gcd(g, b1, rsa->n, ctx);
+      if (BN_is_one(g)) break;
+    }
+  }
 
-  /* } */
   if (BN_cmp(g, rsa->n) && !BN_is_one(g))
       ret = qa_RSA_recover(rsa, g, ctx);
 
+  BN_free(back.p);
+  BN_free(back.b);
   BN_free(p);
   BN_free(q);
   BN_free(b);

+ 3 - 2
src/questions/primes.c

@@ -48,8 +48,9 @@ int primes_next(pit_t *it, BIGNUM* p)
 {
   static char sp[10];
   /* overlow on me, yeah */
-  fscanf(it, "%s", sp);
-  BN_dec2bn(&p, sp);
+  if (fscanf(it, "%s", sp) == 1)
+    BN_dec2bn(&p, sp);
+  else return 0;
 
   return 1;
 }

+ 23 - 8
src/questions/qarith.c

@@ -192,32 +192,45 @@ RSA* qa_RSA_recover(const RSA *rsapub,
                     const BIGNUM *p,
                     BN_CTX *ctx)
 {
-  RSA *rsapriv = RSA_new();
+  static const char *errmsg = "[!] Incorrect vaues for RSA recovery\n";
+  RSA *rsapriv = NULL;
   BIGNUM *p1 = BN_new();
   BIGNUM *q1 = BN_new();
   BIGNUM *phi = BN_new();
+  BIGNUM *n = BN_new();
 
   /* guard for most common errors */
   if (BN_is_zero(rsapub->n) ||
+      !BN_is_odd(rsapub->n) ||
       BN_is_zero(p) ||
       !BN_cmp(rsapub->n, p) ||
       !BN_cmp(p, BN_value_one())) {
-    fprintf(stderr, "[!] Incorrect vaues for RSA recovery\n");
-    return NULL;
+    fprintf(stderr, errmsg);
+    goto end;
   }
 
-  /* copy public key informations */
-  rsapriv->n = BN_dup(rsapub->n);
-  rsapriv->e = BN_dup(rsapub->e);
-  /* retrieve the second prime */
+
+  rsapriv = RSA_new();
   rsapriv->p = BN_dup(p);
   rsapriv->q = BN_new();
-  BN_div(rsapriv->q, NULL, rsapriv->n, rsapriv->p, ctx);
+  BN_div(rsapriv->q, NULL, rsapub->n, rsapriv->p, ctx);
+  BN_mul(n, rsapriv->p, rsapriv->q, ctx);
+  if (BN_cmp(n, rsapub->n)) {
+    fprintf(stderr, errmsg);
+    BN_free(rsapriv->p);
+    BN_free(rsapriv->q);
+    RSA_free(rsapriv);
+    rsapriv = NULL;
+    goto end;
+  }
+
+  rsapriv->n = BN_dup(rsapub->n);
   /* retrieve phi */
   BN_sub(p1, rsapriv->p, BN_value_one());
   BN_sub(q1, rsapriv->q, BN_value_one());
   BN_mul(phi, p1, q1, ctx);
   /* retrieve the private exponent */
+  rsapriv->e = BN_dup(rsapub->e);
   rsapriv->d = BN_new();
   BN_mod_inverse(rsapriv->d, rsapriv->e, phi, ctx);
   /* some other openssl shit */
@@ -225,6 +238,8 @@ RSA* qa_RSA_recover(const RSA *rsapub,
   BN_mod(rsapriv->dmp1, rsapriv->d, p1, ctx);
   BN_mod_inverse(rsapriv->iqmp, rsapriv->q, rsapriv->p, ctx);
 
+ end:
+  BN_free(n);
   BN_free(q1);
   BN_free(p1);
   BN_free(phi);

+ 50 - 2
src/questions/tests/test_williams+1.c

@@ -11,6 +11,7 @@ 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(),
@@ -20,6 +21,7 @@ void test_lucas(void)
   BN_copy(w, BN_value_two());
   BN_dec2bn(&tau, "5");
   BN_copy(v, tau);
+  BN_dec2bn(&n, "100000000000");
 
   /* <V₁, V₀> */
   assert(!BN_cmp(v, tau));
@@ -29,7 +31,7 @@ void test_lucas(void)
   BN_dec2bn(&vcheck, "110");
   BN_dec2bn(&wcheck, "23");
 
-  lucas(v, w, h, tau, ctx);
+  lucas(v, w, h, tau, n, ctx);
   assert(!BN_cmp(wcheck, w));
   BN_print_fp(stderr, v);
   assert(!BN_cmp(vcheck, v));
@@ -39,7 +41,7 @@ void test_lucas(void)
   BN_dec2bn(&vcheck, "12098");
   BN_dec2bn(&wcheck, "2525");
 
-  lucas(v, w, h, tau, ctx);
+  lucas(v, w, h, tau, n, ctx);
   assert(!BN_cmp(wcheck, w));
   assert(!BN_cmp(vcheck, v));
 
@@ -50,11 +52,57 @@ void test_lucas(void)
   BN_free(vcheck);
   BN_free(wcheck);
   BN_CTX_free(ctx);
+}
+
+void test_lehmer_thm(void)
+{
+  BIGNUM
+    *v = BN_new(),
+    *w = 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(&p,
+            "181857351165158586099319592412492032999818333818932850952491024"
+            "131283899677766672100915923041329384157985577418702469610834914"
+            "6296393743554494871840505599");
+  BN_dec2bn(&q,
+            "220481921324130321200060036818685031159071785249502660004347524"
+            "831733577485433929892260897846567483448177204481081755191897197"
+            "38283711758138566145322943999");
+  BN_mul(n, p, q, ctx);
+  /* p + 1 */
+  BN_dec2bn(&h,
+            "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));
 
+
+  BN_free(q);
+  BN_free(p);
+  BN_free(tau);
+  BN_free(v);
+  BN_free(w);
+  BN_free(h);
+
+  BN_CTX_free(ctx);
 }
 
 
 int main(int argc, char **argv)
 {
   test_lucas();
+  test_lehmer_thm();
 }

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

@@ -24,7 +24,7 @@
 void
 lucas(BIGNUM *v, BIGNUM *w,
       BIGNUM *h, BIGNUM *tau,
-      BN_CTX *ctx)
+      BIGNUM *n, BN_CTX *ctx)
 {
   BIGNUM *vv;
   BIGNUM *vw;
@@ -35,23 +35,23 @@ lucas(BIGNUM *v, BIGNUM *w,
   u = BN_new();
 
   for (;
-       BN_ucmp(h, BN_value_one()) > 0;
+       !BN_is_one(h);
        BN_rshift1(h, h)) {
     if (BN_is_odd(h)) {
-      BN_sqr(vv, v, ctx);
+      BN_mod_sqr(vv, v, n, ctx);
       /* v = τv² - vw - τ */
-      BN_mul(u, tau, vv, ctx);
-      BN_mul(vw, v, w, ctx);
+      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);
       /* w = w² - 2 */
       BN_sub(w, vv, BN_value_two());
     } else {
-      BN_sqr(vv, v, ctx);
+      BN_mod_sqr(vv, v, n, ctx);
       /* v = v² - 2 */
       BN_sub(u, vv, BN_value_two());
       /* w = vw - τ */
-      BN_mul(vw, v, w, ctx);
+      BN_mod_mul(vw, v, w, n, ctx);
       BN_sub(w, vw, tau);
     }
     BN_copy(v, u);
@@ -79,39 +79,67 @@ williams_question_ask_rsa(const RSA* rsa)
     *q = BN_new(),
     *p = BN_new(),
     *g = BN_new();
-  int e, k, j, m = 100;
+  int e, k, j, m = 50;
   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};
 
-  BN_one(g);
   BN_one(w); BN_uiadd1(w);
-  BN_pseudo_rand(tau, 512, 0, 0);
+  BN_pseudo_rand_range(tau, n);
   BN_copy(v, tau);
-  BN_one(q);
+  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));
+    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, ctx);
-        /* XXX. unsafe. */
-        BN_mod(v, v, n, ctx);
-        BN_mod(w, w, n, ctx);
+        lucas(v, w, p, tau, n, ctx);
         /* q = v - 2 */
-        BN_sub(v2, v, BN_value_one());
-        BN_sub(v2, v2, BN_value_one());
+        BN_sub(v2, v, BN_value_two());
         BN_mod_mul(q, q, v2, n, ctx);
       }
       /* gcd test */
       BN_gcd(g, q, n, ctx);
+
+      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))
+  if (!BN_cmp(g, n)) {
+    BN_copy(p, back.p);
+    BN_one(g);
+    BN_copy(v, back.v);
+    BN_copy(w, back.w);
+    for (k = back.k; k < e; k++) {
+      lucas(v, w, p, tau, 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) && 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);