Ver código fonte

Introducting continued fractions over bignums.

Shifting the current implementation of cf to a bignum type, for holding rsa
keys.
Note: the code may contain some fucks here and there.
Michele Orrù 11 anos atrás
pai
commit
d51f701dca

+ 1 - 1
src/questions/allquestions.c

@@ -20,5 +20,5 @@ void register_all_questions(void)
   LIST_INIT(&questions);
 
   REGISTER_QUESTION(ExampleQuestion);
-
+  REGISTER_QUESTION(WienerQuestion);
 }

+ 19 - 11
src/questions/qwiener.h

@@ -2,19 +2,27 @@
 #define _QA_WIENER_H
 
 #include <stdlib.h>
+#include <openssl/bn.h>
 
-struct cf {
-  struct fraction {
-    long h;
-    long k;
-  } fs[3];
-  short int i;
-  double x;
-  long a;
-};
+/**
+ * Fractions made of bignums.
+ */
+typedef struct bigfraction {
+  BIGNUM* h;
+  BIGNUM* k;
+} bigfraction_t;
 
-void cfrac_init(struct cf* f, double x);
-struct fraction* cfrac_next(struct cf* f);
+typedef struct cf {
+  bigfraction_t fs[3];
+  short i;
+  bigfraction_t x;
+  BIGNUM* a;
+  BN_CTX* ctx;
+} cf_t;
+
+cf_t* cf_new(void);
+cf_t* cf_init(cf_t *f, BIGNUM *num, BIGNUM *b);
+bigfraction_t* cf_next(cf_t *f);
 
 extern struct qa_question WienerQuestion;
 #endif

+ 32 - 20
src/questions/test/test_wiener.c

@@ -4,15 +4,22 @@
 #include "questions.h"
 #include "qwiener.h"
 
+
 /**
  * \brief Testing the continued fractions generator.
  */
 void test_cf(void)
 {
-  double x;
-  struct cf f;
-  struct fraction *it;
+  bigfraction_t x = {NULL, NULL};
+  cf_t* f;
   size_t i;
+  bigfraction_t *it;
+  BIGNUM* expected;
+
+  f = cf_new();
+  x.h = BN_new();
+  x.k = BN_new();
+  expected = BN_new();
 
    /*
    *  Testing aᵢ
@@ -24,17 +31,18 @@ void test_cf(void)
    *                 2 + …
    *
    */
-  x = sqrt(2);
-  cfrac_init(&f, x);
+  BN_dec2bn(&x.h, "14142135623730951");
+  BN_dec2bn(&x.k, "10000000000000000");
+  BN_dec2bn(&expected, "2");
+  cf_init(f, x.h, x.k);
 
-  it = cfrac_next(&f);
-  assert(it && f.a == 1);
-  it = cfrac_next(&f);
-  for (i=0; i!=10 && it; i++) {
-    assert(f.a == 2);
-    it = cfrac_next(&f);
+  it = cf_next(f);
+  assert(BN_is_one(f->a));
+  for (i=0; i!=5 && it; i++) {
+    it = cf_next(f);
+    assert(!BN_cmp(f->a, expected));
   }
-  assert(i==10);
+  assert(i==5);
 
   /*
    * Testing hᵢ/kᵢ
@@ -45,16 +53,20 @@ void test_cf(void)
    *                      1 + ⎽⎽⎽⎽⎽
    *                          1 + …
    */
-  int fib[] = {1, 1, 2, 3, 5, 8, 13};
-  x = (1 + sqrt(5))/2;
-  cfrac_init(&f, x);
-  it = cfrac_next(&f);
+  const char* fib[] = {"1", "1", "2", "3", "5", "8", "13"};
+  BN_dec2bn(&x.h, "323606797749979");
+  BN_dec2bn(&x.k, "200000000000000");
+  cf_init(f, x.h, x.k);
+  it = cf_next(f);
   for (i=1; i!=7; i++) {
-    assert(it->h == fib[i] &&
-           it->k == fib[i-1]);
-    it=cfrac_next(&f);
-  }
+    BN_dec2bn(&expected, fib[i]);
+    assert(!BN_cmp(it->h, expected));
 
+    BN_dec2bn(&expected, fib[i-1]);
+    assert(!BN_cmp(it->k, expected));
+
+    it=cf_next(f);
+  }
 }
 
 

+ 41 - 5
src/questions/weiner.c

@@ -1,16 +1,52 @@
-int wiener_setup(void)
+#include <openssl/x509.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "questions.h"
+#include "weiner.h"
+
+int wiener_question_setup(void) { return 0; }
+int wiener_question_teardown(void) { return 0; }
+
+int wiener_question_test(X509* cert) { return 1; }
+
+
+void cfrac_init(struct cf* f, double x)
 {
-  return 0;
+  f->fs[0].h = 0;
+  f->fs[0].k = 1;
+
+  f->fs[1].h = 1;
+  f->fs[1].k = 0;
+
+  f->i = 2;
+  f->x = x;
+}
+
+struct fraction cfrac_next(struct cf* f)
+{
+  long a = lrint(floor(f->x));
+  struct fraction ith_cf, *fs = f->fs;
+
+  ith_cf.h = fs[f->i%3].h = a*fs[(f->i-1)%3].h + fs[(f->i-2)%3].h;
+  ith_cf.k = fs[f->i%3].k = a*fs[(f->i-1)%3].k + fs[(f->i-2)%3].k;
+  f->x = 1./(f->x-a);
+  f->i = (f->i+1) % 3;
+
+  return ith_cf;
 }
 
-int wiener_teardown(void)
+int wiener_question_ask(X509* cert)
 {
   return 0;
 }
 
 
 
-struct qa_question q_wiener = {
+struct qa_question WienerQuestion = {
   .name = "Wiener",
-  -question_setup = wiener_setup,
+  .setup = wiener_question_setup,
+  .teardown = wiener_question_teardown,
+  .test = wiener_question_test,
+  .ask = wiener_question_ask
 };

+ 109 - 21
src/questions/wiener.c

@@ -1,16 +1,61 @@
-#include <openssl/x509.h>
 #include <math.h>
 #include <stdlib.h>
 
+#include <openssl/x509.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+
 #include "questions.h"
 #include "qwiener.h"
 
-#define EPS 1e-10
+char * print_bignum(BIGNUM* n)
+{
+  char * dec;
 
-int wiener_question_setup(void) { return 0; }
-int wiener_question_teardown(void) { return 0; }
+  dec = (char *) malloc(BN_num_bytes(n));
+  return dec = BN_bn2dec(n);
+  printf("%s\n", dec);
+
+  free(dec);
+}
+
+
+cf_t* cf_new(void)
+{
+  cf_t *f;
+
+  f = (cf_t *) malloc(sizeof(cf_t));
+
+  size_t i;
+
+  for (i=0; i!=3; i++) {
+    f->fs[i].h = BN_new();
+    f->fs[i].k = BN_new();
+  }
+  f->a = BN_new();
+  f->x.h = BN_new();
+  f->x.k = BN_new();
+
+  f->ctx = BN_CTX_new();
+
+  return f;
+}
+
+void cf_free(cf_t* f)
+{
+  size_t i;
+
+  for (i=0; i!=3; i++) {
+    BN_free(f->fs[i].h);
+    BN_free(f->fs[i].k);
+  }
+  BN_free(f->a);
+  BN_free(f->x.h);
+  BN_free(f->x.k);
+
+  free(f);
+}
 
-int wiener_question_test(X509* cert) { return 1; }
 
 /**
  * \brief Initialized a continued fraction.
@@ -32,25 +77,38 @@ int wiener_question_test(X509* cert) { return 1; }
  *   a₋₁ = 0
  *   h₋₁ = 1    h₋₂ = 0
  *   k₋₁ = 0    k₋₂ = 1
+ *
+ * \param f     A continued fraction structure. If f is NULL, a new one is
+ *              allocated.
+ * \param num   Numerator to be used as initial numerator for the fraction to be
+ *              approximated.
+ * \param den   Denominator to be used as denominator for the fraction to be
+ *              approximated.
+ *
+ * \return the continued fraction fiven as input.
  */
-void cfrac_init(struct cf* f, double x)
+cf_t* cf_init(cf_t* f, BIGNUM* num, BIGNUM* den)
 {
-  f->fs[0].h = 0;
-  f->fs[0].k = 1;
+  if (!f) f = cf_new();
+
+  BN_zero(f->fs[0].h);
+  BN_one(f->fs[0].k);
 
-  f->fs[1].h = 1;
-  f->fs[1].k = 0;
+  BN_one(f->fs[1].h);
+  BN_zero(f->fs[1].k);
 
   f->i = 2;
-  f->x = x;
-  f->a = 0;
+  if (!BN_copy(f->x.h, num)) return NULL;
+  if (!BN_copy(f->x.k, den)) return NULL;
+
+  return f;
 }
 
 
 /**
  * \brief Produces the next fraction.
  *
- * Each new approximation hᵢ/kᵢ is defined recursively as:
+ * Each new approximation hᵢ/kᵢ is defined rec ursively as:
  *   hᵢ = aᵢhᵢ₋₁ + hᵢ₋₂
  *   kᵢ = aᵢkᵢ₋₁ + kᵢ₋₂
  * Meanwhile each new aᵢ is simply the integer part of x.
@@ -60,25 +118,55 @@ void cfrac_init(struct cf* f, double x)
  * \return NULL if the previous fraction approximates at its best the number,
  *         a pointer to the next fraction in the series othw.
  */
-struct fraction* cfrac_next(struct cf* f)
+bigfraction_t* cf_next(cf_t *f)
 {
-  struct fraction *fs = f->fs;
-  struct fraction *ith_fs = &fs[f->i];
+  bigfraction_t *ith_fs = &f->fs[f->i];
+  BIGNUM* rem = BN_new();
 
-  f->a = lrint(floor(f->x));
-  if (f->x - f->a < EPS) return NULL;
+  if (BN_is_zero(f->x.h)) return NULL;
+  BN_div(f->a, rem, f->x.h, f->x.k, f->ctx);
 
-  fs[f->i].h = f->a * fs[(f->i-1+3) % 3].h + fs[(f->i-2+3) % 3].h;
-  fs[f->i].k = f->a * fs[(f->i-1+3) % 3].k + fs[(f->i-2+3) % 3].k;
+  /* computing hᵢ */
+  if (!BN_mul(f->fs[f->i].h , f->a, f->fs[(f->i-1+3) % 3].h, f->ctx)) goto oh_fuck;
+  if (!BN_add(f->fs[f->i].h, f->fs[f->i].h, f->fs[(f->i-2+3) % 3].h)) goto oh_fuck;
+  /* computing kᵢ */
+  if (!BN_mul(f->fs[f->i].k , f->a, f->fs[(f->i-1+3) % 3].k, f->ctx)) goto oh_fuck;
+  if (!BN_add(f->fs[f->i].k, f->fs[f->i].k, f->fs[(f->i-2+3) % 3].k)) goto oh_fuck;
 
   f->i = (f->i + 1) % 3;
-  f->x = 1. / (f->x - f->a);
+  /* update x. */
+  if (!BN_copy(f->x.h, f->x.k)) goto oh_fuck;
+  if (!BN_copy(f->x.k, rem))    goto oh_fuck;
 
   return ith_fs;
+
+ oh_fuck:
+  printf("of fuck!\n");
+  exit(EXIT_FAILURE);
 }
 
+int wiener_question_setup(void) { return 0; }
+int wiener_question_teardown(void) { return 0; }
+
+int wiener_question_test(X509* cert) { return 1; }
+
+
 int wiener_question_ask(X509* cert)
 {
+  struct rsa_st *rsa;
+  BIGNUM *n, *e;
+  BN_CTX* ctx;
+  cf_t* cf;
+
+  ctx = BN_CTX_new();
+  rsa = X509_get_pubkey(cert)->pkey.rsa;
+  n = rsa->n;
+  e = rsa->e;
+
+  cf = cf_init(NULL, n, e);
+  while
+
+
   return 0;
 }