|
@@ -9,6 +9,7 @@
|
|
|
#include <openssl/rsa.h>
|
|
|
#include <openssl/bn.h>
|
|
|
|
|
|
+#include "qa/questions/primes.h"
|
|
|
#include "qa/questions/qarith.h"
|
|
|
#include "qa/questions/questions.h"
|
|
|
|
|
@@ -60,15 +61,64 @@ void lucas(BIGNUM *v, BIGNUM *w,
|
|
|
BN_free(vw);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * \brief William's p+1 factorization.
|
|
|
+ *
|
|
|
+ */
|
|
|
static RSA*
|
|
|
williams_question_ask_rsa(const RSA* rsa)
|
|
|
{
|
|
|
RSA *ret = NULL;
|
|
|
+ BIGNUM *p = BN_new();
|
|
|
+ BIGNUM *gcd = BN_new();
|
|
|
+ BIGNUM
|
|
|
+ *v = BN_new(),
|
|
|
+ *w = BN_new();
|
|
|
+ BIGNUM *n;
|
|
|
+ BIGNUM *tau = BN_new();
|
|
|
+ BIGNUM *q = BN_new();
|
|
|
+ int e, i;
|
|
|
+ BN_CTX *ctx = BN_CTX_new();
|
|
|
+
|
|
|
+ n = rsa->n;
|
|
|
+ BN_one(gcd);
|
|
|
+ BN_one(w); BN_uiadd1(w);
|
|
|
+ BN_pseudo_rand(tau, 512, 0, 0);
|
|
|
+ BN_copy(v, tau);
|
|
|
+ /* In the future, accumulated values: BN_one(q); */
|
|
|
+
|
|
|
+ for (primes_init(); primes_next(p); ) {
|
|
|
+ e = BN_num_bits(n) / (BN_num_bits(p));
|
|
|
+ for (i=0; i < e; i++) {
|
|
|
+ lucas(v, w, p, tau, ctx);
|
|
|
+ /* XXX. unsafe. */
|
|
|
+ BN_mod(v, v, n, ctx);
|
|
|
+ BN_mod(w, w, n, ctx);
|
|
|
+ /* q = v - 2 */
|
|
|
+ BN_sub(q, v, BN_value_one());
|
|
|
+ BN_sub(q, q, BN_value_one());
|
|
|
+ /* gcd test */
|
|
|
+ BN_gcd(gcd, q, n, ctx);
|
|
|
+ if (BN_cmp(gcd, BN_value_one()) == 1) goto end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ end:
|
|
|
+ BN_free(p);
|
|
|
+
|
|
|
+ if (BN_ucmp(gcd, n) != 0) {
|
|
|
+ ret = RSA_new();
|
|
|
+ ret->n = rsa->n;
|
|
|
+ ret->e = rsa->e;
|
|
|
+ ret->p = BN_dup(gcd);
|
|
|
+ ret->q = BN_new();
|
|
|
+ BN_div(ret->q, NULL, n, gcd, ctx);
|
|
|
+ }
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
qa_question_t WilliamsQuestion = {
|
|
|
.name = "p+1",
|
|
|
- .pretty_name = "William's p+1 factorization",
|
|
|
+ .pretty_name = "Williams' p+1 factorization",
|
|
|
.ask_rsa = williams_question_ask_rsa
|
|
|
};
|