|
@@ -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);
|