|
@@ -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",
|