| 
					
				 | 
			
			
				@@ -98,6 +98,102 @@ kernel(matrix_t *m) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \brief Check for smoothness, incuding negative numbers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * As there is no reason to reject negative numbers, provided that the product is positive, we are going to include the sign into the fist element of `v`, as to indicate the sign. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int dixon_smooth(BIGNUM *y, BN_CTX *ctx, char *v, size_t len) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  short neg, ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* is yᵢ smooth? */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  neg = BN_is_negative(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (neg) BN_set_negative(y, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ret = smooth(y, ctx, v+1, len-1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (neg) BN_set_negative(y, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  v[0] = neg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static RSA* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+dixon_question_ask_rsa(const RSA *rsa) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t primes = 5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t r = primes + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t f = primes + 5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i, j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  RSA *ret = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *x, *y, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *sqy, *rem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *gcd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX *ctx = BN_CTX_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  struct bnpair { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BIGNUM *x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BIGNUM *y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } *R; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  matrix_t *m; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  matrix_t *h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** STEP 1: INITIALIZATION **/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* plus one for the sign */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  m = matrix_new(f, r); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  R = malloc(sizeof(struct bnpair) * f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i != r; R[i].x = BN_new(), R[i].y = BN_new(), i++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** STEP 2: GENERATING R, THE POOL OF B-SMOOTH NUMBERS */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i < r; ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_pseudo_rand_range(R[i].x, rsa->n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* yᵢ = xᵢ² - N */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_sqr(R[i].y, R[i].x, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_sub(R[i].y, R[i].y, rsa->n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (dixon_smooth(R[i].y, ctx, m->M[i], r)) i++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fprintf(stderr, "dio can\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** STEP 3: FINDING EVEN POWERS AND ATTEMPTING FACTORIZATION **/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  h = kernel(m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  x = BN_new(); BN_one(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sqy = BN_new(); BN_one(sqy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  y = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rem = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gcd = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i!=f; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* if we found an even power */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (is_vzero(m->M[i], f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* compute x, y² */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (j=0; j!=f; j++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (h->M[i][j]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          BN_mul(x, x, R[j].x, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          BN_mul(sqy, sqy, R[j].y, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_sqrtmod(y, rem, sqy, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!BN_is_zero(rem)) { fprintf(stderr, "Fatal sqrt() error!\n"); exit(1);} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      BN_gcd(gcd, x, y, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (BN_cmp(gcd, rsa->n) < 0 && BN_cmp(gcd, BN_value_one()) > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ret = RSA_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ret->p = BN_dup(gcd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ret->q = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BN_div(ret->q, NULL, ret->p, rsa->n, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ret->n = BN_dup(rsa->n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(sqy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(rem); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(gcd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX_free(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  matrix_free(m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 qa_question_t DixonQuestion = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   .name = "dixon", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   .pretty_name = "Dixon's Factorization" 
			 |