def pm1_pollard_auto(n,Bmax,verbose=False): """Pollard's p-1 factoring algorithm with automatic Boundary adjustment. Args: - *n (int)*: an integer - *Bmax (int)*: Maximum smooth boundary Optional Args: - *verbose (bool)*: set to True if you want a display. Returns: - *(int)*: a subfactor p of n such that p-1 is B-smooth if it exists. 0 if attack failed. """ #optimized parameters B = 16000 nbRM = 10 alternate = False g = 1 while(g==1 and B<=Bmax): lB = itools.ilog(B,2) primes = itools.get_primes(1,B,nbRM) g = n while(g==n): a = random.randint(1,n) for q in primes: e = lB//itools.ilog(q,2) a = itools.exp_mod(a,q**e,n) #q**e ~ B g = itools.gcd(a-1,n) if(g==n and verbose): print("N reached, resuming...") if(g==1): c = a primes = itools.get_primes(B,2*B,nbRM) d = primes[0] a = itools.exp_mod(c,d,n) for i in range(1,len(primes)): g = itools.gcd(a-1,n) if(g!=1): alternate=True break d = primes[i]-primes[i-1] a *= itools.exp_mod(c,d,n) #peut être amélioré en mémorisant les c**(2k) dans une table if(g==1): B *= 4 if(g!=1 and g!=n): if(verbose): if(alternate): print("pm1_pollard_auto ( B' =",2*B,") :\n",n,"=",g,"x",n//g) else: print("pm1_pollard_auto ( B =",B,") :\n",n,"=",g,"x",n//g) return g else: if(verbose): print("pm1_pollard_auto failed with", Bmax, ":(") return 0
def pm1_pollard(n,B,nbRM=20,verbose=False): """Pollard's p-1 factoring algorithm. Args: - *n (int)*: an integer - *B (int)*: smooth boundary Optional Args: - *nbRM (int)*: number of repeats of Rabin-Miller primality test. - *verbose (bool)*: set to True if you want a display. Returns: - *(int)*: a subfactor p of n such that p-1 is B-smooth if it exists. 0 if attack failed. """ lB = itools.ilog(B,2) primes = itools.get_primes(1,B,nbRM) a = random.randint(1,n) for q in primes: e = lB//itools.ilog(q,2) a = itools.exp_mod(a,q**e,n) #q**e ~ B g = itools.gcd(a-1,n) if g>1 and g<n: if(verbose): print("pm1_pollard :\n",n,"=",g,"x",n//g) return g else: if(verbose): print("pm1_pollard failed with", B, ":(") return 0
def weger1(n,e,m,c,verbose=False): """Trivial implementation of Weger's attack on RSA that uses a plain and a cipher to test potential private exponents. Args: - *n (int)*: the modulo - *e (int)*: public exponent - *m (int)*: plain - *c (int)*: cypher (m^e % n) Optional Args: - *verbose (bool)*: set to True to get a display. Returns: - *(int)*: the private exponent if the attack succeeded 0 if attack failed For this attack to work, the private exponent d must be such that : d < (n^(3/4))/abs(p-q) p and q must close to each other. d is then the denominator of a reduced fraction of e/(n+1-2*sqrt(n)) : In this attack we assume Phi(n) ~ (n+1-2*sqrt(n)) (since we assume p ~ q ~ sqrt(n)) """ conv = gen_convergents(n+1-2*itools.isqrt(n), e) for d in conv: if(verbose): print("d prob =",d) p = itools.exp_mod(c,d,n) if(verbose): print("pow =",p) if p == m%n: if(verbose): print("\nweger : success!!!\nSecret exponent :", d, "\n") return d if(verbose): print("\nweger failed :(\n") return 0