Bladeren bron

Williams factorization method: implementing Lucas Sequence multiplier.

Correcting small errors in thesis about the recursive definition of lucas
sequence.
Implementing lucas() function, and testing it with a manual example.
Michele Orrù 11 jaren geleden
bovenliggende
commit
16914842cc

+ 5 - 5
book/pollard+1.tex

@@ -54,8 +54,8 @@ Therefore, the latter expression becomes:
 
 Three foundamental properties interpolate terms of Lucas Sequences:
 \begin{align}
-  & V_{2n+1} = \tau V_n - V_{n-1} \label{eq:ls:2n+1}\\
-  & V_{2n} = V_n^2 - 2 \label{eq:ls:2n}\\
+  & V_{2n+1} = \tau V_n^2 - V_n V_{n-1} - \tau \label{eq:ls:2n+1} \\
+  & V_{2n} = V_n^2 - 2 \label{eq:ls:2n} \\
   & V_{2n-1} = V_nV_{n-1} - \tau \label{eq:ls:2n-1}
 \end{align}
 
@@ -78,7 +78,7 @@ significant one: if it is zero, we use the multiplication formula
           \Comment by equation \ref{eq:ls:2n}
           \State $V' \gets VV' - \tau$
           \Comment by equation \ref{eq:ls:2n-1}
-          \State $v \gets V''$
+          \State $V \gets V''$
         \ElsIf{$a$ is odd}
           \State $V'' \gets \tau V^2 - VV' - \tau$
           \Comment by equation \ref{eq:ls:2n+1}
@@ -156,8 +156,8 @@ if $g = N$ start back from scratch, as $pq \mid g$.
   \begin{algorithmic}[1]
     \Require $\mathcal{P}$, the prime pool
     \Function{Factorize}{$N, \tau$}
-      \State $V \gets 2$
-      \State $V' \gets \tau$
+      \State $V \gets \tau$
+      \State $V' \gets 2$
       \For{$p_i \strong{ in } \mathcal{P}$}
       \Comment step (i)
         \State $e \gets \log \sqrt{N} // \log p_i$

+ 4 - 3
src/questions/Makefile.am

@@ -3,16 +3,17 @@ SUBDIRS = tests/
 # following the fucking manual, I am putting headers into the _SOURCES variable
 #  <https://www.gnu.org/software/automake/manual/html_node/Headers.html>
 EXAMPLE_QUESTION = example.c
-WIENER_QUESTION = wiener.c         include/qwiener.h
-POLLARD_QUESTION = pollard.c         include/qpollard.h
+WIENER_QUESTION = wiener.c    include/qwiener.h
+POLLARD_QUESTION = pollard.c    include/qpollard.h
 DIXON_QUESTION = dixon.c
 FERMAT_QUESTION = fermat.c
 METADATA_QUESTION = metadata.c
 POLLARDRHO_QUESTION = pollardrho.c
+WILLIAMS_QUESTION = williams+1.c    include/qwilliams.h
 
 QUESTIONS = $(WIENER_QUESTION) $(POLLARD_QUESTION) $(DIXON_QUESTION) \
 	    $(FERMAT_QUESTION) $(EXAMPLE_QUESTION) $(METADATA_QUESTION) \
-	    $(POLLARDRHO_QUESTION)
+	    $(POLLARDRHO_QUESTION) $(WILLIAMS_QUESTION)
 
 QLIBSOURCES =         qarith.c         include/qarith.h \
 	            qstrings.c         include/qstrings.h \

+ 9 - 0
src/questions/include/qwilliams.h

@@ -0,0 +1,9 @@
+#ifndef _QA_WILLIAMS_H_
+#define _QA_WILLIAMS_H_
+
+extern struct qa_question WilliamsQuestion;
+
+void lucas(BIGNUM *v, BIGNUM *w, BIGNUM *h, BIGNUM * tau, BN_CTX *ctx);
+
+
+#endif /* _QA_WILLIAMS_H_ */

+ 62 - 0
src/questions/tests/test_williams+1.c

@@ -0,0 +1,62 @@
+#include <assert.h>
+
+#include <openssl/bn.h>
+
+#include "qa/questions/questions.h"
+#include "qa/questions/qarith.h"
+#include "qa/questions/qwilliams.h"
+
+void test_lucas(void)
+{
+  BIGNUM *two = BN_new();
+  BIGNUM *v = BN_new();
+  BIGNUM *w = BN_new();
+  BIGNUM *h = BN_new();
+  BIGNUM *tau = BN_new();
+  BIGNUM
+    *vcheck = BN_new(),
+    *wcheck = BN_new();
+  BN_CTX *ctx = BN_CTX_new();
+
+  BN_one(two); BN_uiadd1(two);
+  BN_copy(w, two);
+  BN_dec2bn(&tau, "5");
+  BN_copy(v, tau);
+
+  /* <V₁, V₀> */
+  assert(!BN_cmp(v, tau));
+  assert(!BN_cmp(w, two));
+  /* <V₃, V₂> */
+  BN_dec2bn(&h, "3");
+  BN_dec2bn(&vcheck, "110");
+  BN_dec2bn(&wcheck, "23");
+
+  lucas(v, w, h, tau, ctx);
+  assert(!BN_cmp(wcheck, w));
+  BN_print_fp(stderr, v);
+  assert(!BN_cmp(vcheck, v));
+
+  /* <V₆, V₅> */
+  BN_dec2bn(&h, "2");
+  BN_dec2bn(&vcheck, "12098");
+  BN_dec2bn(&wcheck, "2525");
+
+  lucas(v, w, h, tau, ctx);
+  assert(!BN_cmp(wcheck, w));
+  assert(!BN_cmp(vcheck, v));
+
+  BN_free(tau);
+  BN_free(v);
+  BN_free(w);
+  BN_free(h);
+  BN_free(vcheck);
+  BN_free(wcheck);
+  BN_CTX_free(ctx);
+
+}
+
+
+int main(int argc, char **argv)
+{
+  test_lucas();
+}

+ 74 - 0
src/questions/williams+1.c

@@ -0,0 +1,74 @@
+/**
+ * \file williams+1.c
+ * \brief An implementation of William's p+1 Attack.
+ *
+ * William's attack, published in 1982, describes a factorization algorithm
+ * based on lucas sequences and Lehmer's theorem.
+ *
+ */
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+
+#include "qa/questions/qarith.h"
+#include "qa/questions/questions.h"
+
+/**
+ * \brief Lucas Sequence Multiplier.
+ *
+ * Given a pair <Vᵢ, Vᵢ₋₁>, terms of a lucas sequence with parameter τ,
+ * compute <Vₕᵢ, Vₕᵢ₋₁>
+ */
+void lucas(BIGNUM *v, BIGNUM *w,
+           BIGNUM *h, BIGNUM *tau,
+           BN_CTX *ctx)
+{
+  BIGNUM *vv;
+  BIGNUM *vw;
+  BIGNUM *u;
+
+  vv = BN_new();
+  vw = BN_new();
+  u = BN_new();
+
+  for (;
+       BN_ucmp(h, BN_value_one()) > 0;
+       BN_rshift1(h, h)) {
+    if (BN_is_odd(h)) {
+      BN_sqr(vv, v, ctx);
+      /* v = τv² - vw - τ */
+      BN_mul(u, tau, vv, ctx);
+      BN_mul(vw, v, w, ctx);
+      BN_sub(u, u, vw);
+      BN_sub(u, u, tau);
+      /* w = w² - 2 */
+      BN_sub(w, vv, BN_value_one());
+      BN_sub(w, w, BN_value_one());
+    } else {
+      BN_sqr(vv, v, ctx);
+      /* v = v² - 2*/
+      BN_sub(u, vv, BN_value_one());
+      BN_sub(u, u, BN_value_one());
+      /* w = vw - τ */
+      BN_mul(vw, v, w, ctx);
+      BN_sub(w, vw, tau);
+    }
+    BN_copy(v, u);
+  }
+
+  BN_free(u);
+  BN_free(vv);
+  BN_free(vw);
+}
+
+static RSA*
+williams_question_ask_rsa(const RSA* rsa)
+{
+  RSA *ret = NULL;
+  return ret;
+}
+
+qa_question_t WilliamsQuestion = {
+  .name = "p+1",
+  .pretty_name = "William's p+1 factorization",
+  .ask_rsa = williams_question_ask_rsa
+};