|
@@ -16,19 +16,26 @@
|
|
* exponent.
|
|
* exponent.
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdlib.h>
|
|
|
|
+#include <strings.h>
|
|
|
|
|
|
#include <openssl/bn.h>
|
|
#include <openssl/bn.h>
|
|
|
|
|
|
|
|
+#include "qarith.h"
|
|
#include "questions.h"
|
|
#include "questions.h"
|
|
|
|
|
|
-
|
|
|
|
|
|
+#define EPOCHS 100
|
|
|
|
+#define REPOP_EPOCHS 50
|
|
#define BPOOL_EXTEND_STEP 42
|
|
#define BPOOL_EXTEND_STEP 42
|
|
#define BPOOL_STARTING_BITS 7
|
|
#define BPOOL_STARTING_BITS 7
|
|
#define RPOOL_EXTEND_STEP 42
|
|
#define RPOOL_EXTEND_STEP 42
|
|
|
|
+#define U_SIZE 10
|
|
|
|
|
|
#define qa_rand rand
|
|
#define qa_rand rand
|
|
|
|
|
|
|
|
+static BIGNUM* zero;
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* \struct dixon_number_t
|
|
* \struct dixon_number_t
|
|
* \brief Auxiliary structure holding informations for R_pool.
|
|
* \brief Auxiliary structure holding informations for R_pool.
|
|
@@ -50,13 +57,19 @@ static BIGNUM** B_pool = NULL;
|
|
static size_t B_size = 0;
|
|
static size_t B_size = 0;
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * \brief Extends the factor base, and then adjusts R_pool
|
|
|
|
+ *
|
|
|
|
+ */
|
|
static void extend_B_pool(int max_bits)
|
|
static void extend_B_pool(int max_bits)
|
|
{
|
|
{
|
|
- size_t i, old_B_size;
|
|
|
|
|
|
+ size_t i, j, old_B_size;
|
|
int bits;
|
|
int bits;
|
|
|
|
|
|
old_B_size = B_size;
|
|
old_B_size = B_size;
|
|
B_size += BPOOL_EXTEND_STEP;
|
|
B_size += BPOOL_EXTEND_STEP;
|
|
|
|
+ /* check for size_t overflow */
|
|
|
|
+ assert(old_B_size < B_size);
|
|
|
|
|
|
B_pool = realloc(B_pool, B_size * sizeof(BIGNUM*));
|
|
B_pool = realloc(B_pool, B_size * sizeof(BIGNUM*));
|
|
|
|
|
|
@@ -64,7 +77,11 @@ static void extend_B_pool(int max_bits)
|
|
bits = 1 + qa_rand() % max_bits;
|
|
bits = 1 + qa_rand() % max_bits;
|
|
B_pool[i] = BN_generate_prime(NULL, bits, 0, NULL, NULL, NULL, NULL);
|
|
B_pool[i] = BN_generate_prime(NULL, bits, 0, NULL, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
- /* XXX. reallocate space for vectors in R_pool */
|
|
|
|
|
|
+ /* reallocate space for vectors in R_pool */
|
|
|
|
+ for (i=0; i!=R_size; i++) {
|
|
|
|
+ R_pool[i].v = realloc(R_pool[i].v, sizeof(BIGNUM*) * B_size);
|
|
|
|
+ for (j=old_B_size; j!=B_size; j++) R_pool[i].v[j] = NULL;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
#define B_pool_free() free(B_pool)
|
|
#define B_pool_free() free(B_pool)
|
|
@@ -84,45 +101,183 @@ static void extend_B_pool(int max_bits)
|
|
* 3. Find an r = √(s + tN) , t ∈ {1..N-1}
|
|
* 3. Find an r = √(s + tN) , t ∈ {1..N-1}
|
|
* This algorithm shall have complexity O(k|B| + (N-1)lg N)
|
|
* This algorithm shall have complexity O(k|B| + (N-1)lg N)
|
|
*/
|
|
*/
|
|
-static void extend_R_pool(BIGNUM* max_s)
|
|
|
|
|
|
+static void extend_R_pool(BIGNUM* N)
|
|
{
|
|
{
|
|
|
|
+ const size_t old_R_size = R_size;
|
|
size_t i, j;
|
|
size_t i, j;
|
|
|
|
+ int e_bits;
|
|
|
|
+ BN_CTX *ctx = BN_CTX_new();
|
|
|
|
+ BIGNUM
|
|
|
|
+ *e,
|
|
|
|
+ *tmp = BN_new(),
|
|
|
|
+ *rem = BN_new(),
|
|
|
|
+ *t = BN_new();
|
|
dixon_number_t *d;
|
|
dixon_number_t *d;
|
|
|
|
|
|
- i = R_size;
|
|
|
|
R_size += RPOOL_EXTEND_STEP;
|
|
R_size += RPOOL_EXTEND_STEP;
|
|
|
|
+ /* size_t overflow */
|
|
|
|
+ assert(R_size > old_R_size);
|
|
R_pool = realloc(R_pool, sizeof(dixon_number_t));
|
|
R_pool = realloc(R_pool, sizeof(dixon_number_t));
|
|
|
|
+ /*
|
|
|
|
+ * XXX. There is much more to think about this.
|
|
|
|
+ * We are trying to generate some random exponents e₀…eₖ such that s < N .
|
|
|
|
+ * Hence, log(N) = ae₀ + be₁ + … + leₖ
|
|
|
|
+ */
|
|
|
|
+ e_bits = BN_num_bits(N) / 5;
|
|
|
|
|
|
- for (; i!= R_size; i++) {
|
|
|
|
|
|
+ for (i=old_R_size; i!= R_size; i++) {
|
|
d = &R_pool[i];
|
|
d = &R_pool[i];
|
|
d->s = BN_new();
|
|
d->s = BN_new();
|
|
|
|
+ d->r = BN_new();
|
|
|
|
+
|
|
/* generate exponents and calculate s */
|
|
/* generate exponents and calculate s */
|
|
- while (BN_cmp(d->s, max_s) != -1) {
|
|
|
|
- for (j=0; j != B_size; j++) {
|
|
|
|
- ;
|
|
|
|
- }
|
|
|
|
|
|
+ for (j=0; j != B_size && BN_cmp(N, d->s) == 1; j++) {
|
|
|
|
+ e = d->v[j] = BN_new();
|
|
|
|
+ /* XXX. better check for error here. */
|
|
|
|
+ BN_pseudo_rand(e, e_bits, -1, 0);
|
|
|
|
+ BN_exp(tmp, B_pool[j], e, ctx);
|
|
|
|
+ BN_mul(d->s, tmp, d->s, ctx);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* Find an r = √(s + tN) , t ∈ {1..N-1} */
|
|
|
|
+ BN_sqr(tmp, N, ctx);
|
|
|
|
+ BN_one(t);
|
|
|
|
+ for (BN_add(t, t, N); BN_cmp(tmp, t) == 1; BN_add(t, t, N))
|
|
|
|
+ if (BN_sqrtmod(d->r, rem, t, ctx)) break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ BN_CTX_free(ctx);
|
|
|
|
+ BN_free(rem);
|
|
|
|
+ BN_free(tmp);
|
|
|
|
+ BN_free(t);
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
#define R_pool_free() free(R_pool)
|
|
#define R_pool_free() free(R_pool)
|
|
|
|
|
|
int dixon_question_setup(void)
|
|
int dixon_question_setup(void)
|
|
{
|
|
{
|
|
|
|
+ extern BIGNUM* zero;
|
|
|
|
+ zero = BN_new();
|
|
|
|
+ BN_zero(zero);
|
|
|
|
+
|
|
extend_B_pool(BPOOL_STARTING_BITS);
|
|
extend_B_pool(BPOOL_STARTING_BITS);
|
|
- extend_R_pool();
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int dixon_question_teardown(void) {
|
|
int dixon_question_teardown(void) {
|
|
|
|
+ BN_free(zero);
|
|
|
|
+
|
|
B_pool_free();
|
|
B_pool_free();
|
|
R_pool_free();
|
|
R_pool_free();
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-int dixon_question_test(X509* cert) { return 1; }
|
|
|
|
|
|
+int dixon_question_test(X509* cert) {
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int is_vzero(void *v, size_t len)
|
|
|
|
+{
|
|
|
|
+ char unsigned *s = (char unsigned *) v;
|
|
|
|
+ while (len--)
|
|
|
|
+ if (*(s++)) return 0;
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
|
|
int dixon_question_ask(X509* cert) {
|
|
int dixon_question_ask(X509* cert) {
|
|
|
|
+ RSA *rsa;
|
|
|
|
+ /* key data */
|
|
|
|
+ BIGNUM
|
|
|
|
+ *n, *e,
|
|
|
|
+ *p, *q;
|
|
|
|
+ /* x, y */
|
|
|
|
+ BIGNUM
|
|
|
|
+ *x, *x2,
|
|
|
|
+ *y, *y2;
|
|
|
|
+ BN_CTX *ctx;
|
|
|
|
+ /* U ⊆ R */
|
|
|
|
+ ssize_t *U_bucket;
|
|
|
|
+ /* internal data */
|
|
|
|
+ int epoch;
|
|
|
|
+ BIGNUM *tmp;
|
|
|
|
+ char *even_powers;
|
|
|
|
+ size_t i, j, k;
|
|
|
|
+
|
|
|
|
+ rsa = X509_get_pubkey(cert)->pkey.rsa;
|
|
|
|
+ n = rsa->n;
|
|
|
|
+ e = rsa->e;
|
|
|
|
+ U_bucket = malloc(sizeof(ssize_t) * U_SIZE);
|
|
|
|
+ even_powers = malloc(sizeof(char) * B_size);
|
|
|
|
+ ctx = BN_CTX_new();
|
|
|
|
+ x = BN_new();
|
|
|
|
+ y = BN_new();
|
|
|
|
+ x2 = BN_new();
|
|
|
|
+ y2 = BN_new();
|
|
|
|
+ tmp = BN_new();
|
|
|
|
+
|
|
|
|
+ /* mainloop: iterate until a key is found, or convergence. */
|
|
|
|
+ for (epoch=0; epoch < EPOCHS; epoch++) {
|
|
|
|
+ /* depending on the epoch, populate R_pool and B_pool */
|
|
|
|
+ if (epoch % REPOP_EPOCHS) extend_R_pool(n);
|
|
|
|
+
|
|
|
|
+ /* reset variables */
|
|
|
|
+ for (i=0; i!=U_SIZE; i++) U_bucket[i] = -1;
|
|
|
|
+ bzero(even_powers, B_size * sizeof(char));
|
|
|
|
+ j = 0;
|
|
|
|
+
|
|
|
|
+ /* choose a subset of R such that the product of primes can be squared */
|
|
|
|
+ do {
|
|
|
|
+ for (i=0; i!=B_size && j < U_SIZE; i++) {
|
|
|
|
+ /* choose whether to take or not R_pool[i] */
|
|
|
|
+ if (qa_rand() % 2) continue;
|
|
|
|
+
|
|
|
|
+ /* add the number */
|
|
|
|
+ U_bucket[j++] = i;
|
|
|
|
+ for (k=0; k!=B_size; k++)
|
|
|
|
+ even_powers[k] ^= BN_is_odd(R_pool[i].v[j]);
|
|
|
|
+ }
|
|
|
|
+ } while (!is_vzero(even_powers, B_size * sizeof(char)));
|
|
|
|
+
|
|
|
|
+ /* let x = Πᵢ rᵢ , y² = Πᵢ sᵢ */
|
|
|
|
+ BN_one(x);
|
|
|
|
+ BN_one(y2);
|
|
|
|
+ for (i=0; i != U_SIZE; i++) {
|
|
|
|
+ if (U_bucket[i] == -1) continue;
|
|
|
|
+
|
|
|
|
+ j = U_bucket[i];
|
|
|
|
+ BN_mul(x, x, R_pool[j].r, ctx);
|
|
|
|
+ BN_mul(y2, y2, R_pool[j].s, ctx);
|
|
|
|
+ }
|
|
|
|
+ /* retrieve x² from x */
|
|
|
|
+ BN_sqr(x2, x, ctx);
|
|
|
|
+ /* retrieve y from y² */
|
|
|
|
+ /* test: shall *always* be a perfect square */
|
|
|
|
+ if (!BN_sqrtmod(y, tmp, y2, ctx)) continue;
|
|
|
|
+ /* test: assert that x ≡ y (mod N) */
|
|
|
|
+ if (!BN_cmp(x, y)) continue;
|
|
|
|
+
|
|
|
|
+ /* p, q found :) */
|
|
|
|
+ p = BN_new();
|
|
|
|
+ q = BN_new();
|
|
|
|
+
|
|
|
|
+ BN_uadd(tmp, x, y);
|
|
|
|
+ BN_gcd(p, tmp, n, ctx);
|
|
|
|
+ assert(!BN_is_one(p) && BN_cmp(p, n));
|
|
|
|
+ BN_usub(tmp, x, y);
|
|
|
|
+ BN_gcd(q, tmp, n, ctx);
|
|
|
|
+ assert(!BN_is_one(q) && BN_cmp(q, n));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BN_free(x);
|
|
|
|
+ BN_free(x2);
|
|
|
|
+ BN_free(y);
|
|
|
|
+ BN_free(y2);
|
|
|
|
+ free(U_bucket);
|
|
|
|
+ free(even_powers);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|