|
@@ -0,0 +1,79 @@
|
|
|
+/**
|
|
|
+ * \file pollardrho.c
|
|
|
+ *
|
|
|
+ * \brief Pollard's ρ factorization method.
|
|
|
+ *
|
|
|
+ * This file contains two implementations of the pollard's ρ algorithm, used in
|
|
|
+ * order to attempt a factorization of N.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <openssl/x509.h>
|
|
|
+
|
|
|
+#include <qa/questions/qarith.h>
|
|
|
+#include <qa/questions/questions.h>
|
|
|
+
|
|
|
+
|
|
|
+static RSA*
|
|
|
+pollardrho_question_ask_rsa(const RSA *rsa)
|
|
|
+{
|
|
|
+ RSA *ret = NULL;
|
|
|
+ BIGNUM
|
|
|
+ *x = NULL,
|
|
|
+ *y = NULL;
|
|
|
+ BIGNUM *n;
|
|
|
+ BIGNUM* two;
|
|
|
+ BIGNUM *tmp;
|
|
|
+ BIGNUM *gcd;
|
|
|
+ BN_CTX *ctx;
|
|
|
+
|
|
|
+ ctx = BN_CTX_new();
|
|
|
+ gcd = BN_new();
|
|
|
+ x = BN_new();
|
|
|
+ y = BN_new();
|
|
|
+ tmp = BN_new();
|
|
|
+ n = rsa->n;
|
|
|
+ two = BN_new();
|
|
|
+
|
|
|
+ /* initialization */
|
|
|
+ BN_one(gcd);
|
|
|
+ BN_pseudo_rand(x, 512, 0, 0);
|
|
|
+ BN_copy(y, x);
|
|
|
+ BN_one(two); BN_uiadd1(two);
|
|
|
+
|
|
|
+
|
|
|
+ while (!BN_cmp(gcd, BN_value_one())) {
|
|
|
+ /* x ← x² + 1 (mod N) */
|
|
|
+ BN_mod_sqr(x, x, n, ctx);
|
|
|
+ BN_uiadd1(x);
|
|
|
+ /* y ← y⁴ + 2y² + 2 (mod N) */
|
|
|
+ BN_mod_sqr(tmp, y, n, ctx);
|
|
|
+ BN_mod_sqr(y, tmp, n, ctx);
|
|
|
+ BN_lshift1(tmp, tmp);
|
|
|
+ BN_mod_add(y, y, tmp, n, ctx);
|
|
|
+ BN_mod_add(y, y, two, n, ctx);
|
|
|
+ /* gcd(|x-y|, N) */
|
|
|
+ BN_mod_sub(tmp, x, y, n, ctx);
|
|
|
+ BN_gcd(gcd, tmp, n, ctx);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ BN_free(tmp);
|
|
|
+ BN_free(x);
|
|
|
+ BN_free(y);
|
|
|
+ BN_free(gcd);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+qa_question_t PollardRhoQuestion = {
|
|
|
+ .name = "pollardrho",
|
|
|
+ .pretty_name = "Pollard's rho factorization",
|
|
|
+ .ask_rsa = pollardrho_question_ask_rsa
|
|
|
+};
|