| 
					
				 | 
			
			
				@@ -1,16 +1,54 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <openssl/x509.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \file wiener.c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <math.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <stdlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <openssl/x509.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <openssl/rsa.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <openssl/bn.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "questions.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "qwiener.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define EPS 1e-10 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int wiener_question_setup(void) { return 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int wiener_question_teardown(void) { return 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+cf_t* cf_new(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cf_t *f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f = (cf_t *) malloc(sizeof(cf_t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i!=3; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    f->fs[i].h = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    f->fs[i].k = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f->a = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f->x.h = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f->x.k = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  f->ctx = BN_CTX_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void cf_free(cf_t* f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; i!=3; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_free(f->fs[i].h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_free(f->fs[i].k); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(f->a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(f->x.h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(f->x.k); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  free(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-int wiener_question_test(X509* cert) { return 1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * \brief Initialized a continued fraction. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -32,25 +70,38 @@ int wiener_question_test(X509* cert) { return 1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *   a₋₁ = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *   h₋₁ = 1    h₋₂ = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *   k₋₁ = 0    k₋₂ = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \param f     A continued fraction structure. If f is NULL, a new one is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *              allocated. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \param num   Numerator to be used as initial numerator for the fraction to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *              approximated. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \param den   Denominator to be used as denominator for the fraction to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *              approximated. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \return the continued fraction fiven as input. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void cfrac_init(struct cf* f, double x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+cf_t* cf_init(cf_t* f, BIGNUM* num, BIGNUM* den) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->fs[0].h = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->fs[0].k = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!f) f = cf_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->fs[1].h = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->fs[1].k = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_zero(f->fs[0].h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_one(f->fs[0].k); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_one(f->fs[1].h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_zero(f->fs[1].k); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   f->i = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->x = x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->a = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_copy(f->x.h, num)) return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_copy(f->x.k, den)) return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * \brief Produces the next fraction. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Each new approximation hᵢ/kᵢ is defined recursively as: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Each new approximation hᵢ/kᵢ is defined rec ursively as: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *   hᵢ = aᵢhᵢ₋₁ + hᵢ₋₂ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *   kᵢ = aᵢkᵢ₋₁ + kᵢ₋₂ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * Meanwhile each new aᵢ is simply the integer part of x. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -60,31 +111,182 @@ void cfrac_init(struct cf* f, double x) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * \return NULL if the previous fraction approximates at its best the number, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *         a pointer to the next fraction in the series othw. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct fraction* cfrac_next(struct cf* f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bigfraction_t* cf_next(cf_t *f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct fraction *fs = f->fs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct fraction *ith_fs = &fs[f->i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bigfraction_t *ith_fs = &f->fs[f->i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM* rem = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->a = lrint(floor(f->x)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (f->x - f->a < EPS) return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (BN_is_zero(f->x.h)) return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_div(f->a, rem, f->x.h, f->x.k, f->ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fs[f->i].h = f->a * fs[(f->i-1+3) % 3].h + fs[(f->i-2+3) % 3].h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  fs[f->i].k = f->a * fs[(f->i-1+3) % 3].k + fs[(f->i-2+3) % 3].k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* computing hᵢ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_mul(f->fs[f->i].h , f->a, f->fs[(f->i-1+3) % 3].h, f->ctx)) goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_add(f->fs[f->i].h, f->fs[f->i].h, f->fs[(f->i-2+3) % 3].h)) goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* computing kᵢ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_mul(f->fs[f->i].k , f->a, f->fs[(f->i-1+3) % 3].k, f->ctx)) goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_add(f->fs[f->i].k, f->fs[f->i].k, f->fs[(f->i-2+3) % 3].k)) goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   f->i = (f->i + 1) % 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  f->x = 1. / (f->x - f->a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* update x. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_copy(f->x.h, f->x.k)) goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!BN_copy(f->x.k, rem))    goto oh_fuck; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return ith_fs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ oh_fuck: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  printf("of fuck!\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  exit(EXIT_FAILURE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void BN_int2bn(BIGNUM** a, short int i) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!*a) *a = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* trolololololol. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_one(*a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (*a)->d[0] = i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * \brief Square Root for bignums. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int BN_sqrtmod(BIGNUM* dv, BIGNUM* rem, BIGNUM* a, BN_CTX* ctx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  char *abn2dec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int g[100]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  long al; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  long x = 0, r = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int i, j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int d; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  long y, yn; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  abn2dec = BN_bn2dec(a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sscanf(abn2dec, "%ld", &al); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  r = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  x = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0; al > 0; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    g[i] = al%100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    al /= 100; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (j=i-1; j>=0; j--) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    r = r*100 + g[j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    y = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (d=1; d!=10; d++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      yn = d*(20*x + d); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (yn <= r) y = yn; else break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    r -= y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    x = 10*x + d -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sprintf(abn2dec, "%ld", r); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_dec2bn(&rem, abn2dec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sprintf(abn2dec, "%ld", x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_dec2bn(&dv, abn2dec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  OPENSSL_free(abn2dec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return BN_is_zero(rem); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  Weiner Attack Implementation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int wiener_question_setup(void) { return 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int wiener_question_teardown(void) { return 0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int wiener_question_test(X509* cert) { return 1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int wiener_question_ask(X509* cert) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  RSA *rsa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* key data */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM *n, *e, *d, *phi; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM *p, *q; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* continued fractions coefficient, and mod */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cf_t* cf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bigfraction_t *it; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t  i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM *t, *tmp, *rem; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* equation coefficients */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BIGNUM *b2, *delta; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_CTX *ctx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rsa = X509_get_pubkey(cert)->pkey.rsa; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  phi = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tmp = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rem = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  n = rsa->n; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  e = rsa->e; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  b2 = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  delta = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * generate the continued fractions approximating e/N 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cf = cf_init(NULL, e, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ctx = cf->ctx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i=0, it = cf_next(cf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       // XXX. how many keys shall I test? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       i!=100 && it; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       i++, it = cf_next(cf)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    t = it->h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    d = it->k; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Recovering φ(N) = (ed - 1) / t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * TEST1: obviously the couple {t, d} is correct → (ed-1) | t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_mul(phi, e, d, cf->ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_usub(tmp, phi, BN_value_one()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_div(phi, rem, tmp, t, cf->ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!BN_is_zero(rem)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // XXX. check, is it possible to fall here, assuming N, e are valid? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (BN_is_odd(phi) && BN_cmp(n, phi) > 0)   continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Recovering p, q 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Solving the equation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  x² + [N-φ(N)+1]x + N = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * which, after a few passages, boils down to: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     *  x² + (p+q)x + (pq) = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * TEST2: φ(N) is correct → the two roots of x are integers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_usub(b2, n, phi); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_uadd(b2, b2, BN_value_one()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_rshift(b2, b2, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (BN_is_zero(b2)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* delta */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_sqr(tmp, b2, ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_usub(delta, tmp, n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!BN_sqrtmod(tmp, rem, delta, ctx)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* key found :) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    p = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    q = BN_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_usub(p, b2, tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BN_uadd(q, b2, tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //printf("Primes: %s %s", BN_bn2dec(p), BN_bn2dec(q)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  cf_free(cf); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(rem); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(b2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(delta); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BN_free(phi); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct qa_question WienerQuestion = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+qa_question_t WienerQuestion = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   .name = "Wiener", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   .setup = wiener_question_setup, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   .teardown = wiener_question_teardown, 
			 |