Esempio n. 1
0
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
Esempio n. 2
0
def rho_pollard(n,verbose=False):
	"""Pollard's Rho algorithm applied to factoring.
	
	Args:
		- *n (int)*: a non-prime integer
		
	Optional Args:
		- *verbose (bool)*: set to True if you want a display.
		
	Returns:
		- *(int)*: a small factor of n
		
	Simple and efficient.
	"""
		
	x = random.randint(1,n)
	y = x
	g = 1
	while(g==1):
		x = (x*x + 1)%n
		y = (y*y + 1)%n
		y = (y*y + 1)%n
		g = itools.gcd(n,x-y)
	if(verbose): print("rho_pollard :\n",n,"=",g,"x",n//g)
	return g
Esempio n. 3
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
Esempio n. 4
0
def rho_pollard_brent(n,verbose=False):
	"""Brent's improved version of Pollard's Rho algorithm applied to factoring.
	*(source : http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf)*
	
	Args:
		- *n (int)*: a non-prime integer
		
	Optional Args:
		- *verbose (bool)*: set to True if you want a display.
		
	Returns:
		- *(int)*: a small factor of n
		
	Clearly more efficient than the standard Pollard's Rho algorithm.
	"""
	x = random.randint(1,n)
	c = random.randint(1,n)
	m = random.randint(1,n)
	y = x
	g = 1
	r = 1
	q = 1
	while(g==1):
		x = y
		for i in range(r):
			y = (y*y + c)%n
		k = 0
		while( k<r and g==1):
			ys = y
			for i in range(min(m,r-k)):
				y = (y*y + c)%n
				q = q*(x-y) % n
			g = itools.gcd(q,n)
			k += m
			
		r *= 2
	
	if(g==n):
		g = 1
		while(g==1):
			ys = (ys*ys + c)%n
			g = itools.gcd(x-ys,n)
	
	if(verbose): print("rho_pollard_brent :\n",n,"=",g,"x",n//g)
	return g
Esempio n. 5
0
def pp1_williams(n,B,nbRM=20,verbose=False):
	"""Williams' 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(3,B,nbRM)
	a = random.randint(1,n)
	v = a
	i=0
	for q in primes:
		e = lB//itools.ilog(q,2)
		#plus efficace que :  for i in range(e): v = lucal_mul(v,q,n)
		#évite de calculer e fois la décomposition binaire de q et d'appeler e fonctions, au prix d'une exponentiation entière
		v = lucas_mul(v,q**e,n) #q**e ~ B
		g = itools.gcd(v-2,n)
		if(g!=1 and g!=n): break
				
	if(g>1 and g<n):
		if(verbose): print("pp1_williams :\n",n,"=",g,"x",n//g)
		return g
	else:
		if(verbose): print("pp1_williams failed with", B, ":(")
		return 0
Esempio n. 6
0
def pp1_williams_auto(n,Bmax,verbose=False):
	"""Williams' 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.
	
	"""

	B = 1000
	nbRM = 10
	alternate = False
	g = 1
	while(g==1 and B<=Bmax):
		lB = itools.ilog(B,2)
		B2 = (10 ** (itools.ilog(B,10)//5))*B #tiré de resultats expérimentaux : http://www.loria.fr/~zimmerma/records/Pplus1.html
		primes = itools.get_primes(3,B,nbRM)
		g = n
		
		#Step 1
		while(g==n):
			a = random.randint(1,n)
			v = a
			for q in primes:
				e = lB//itools.ilog(q,2)
				#plus efficace que :  for i in range(e): v = lucal_mul(v,q,n)
				#évite de calculer e fois la décomposition binaire de q et d'appeler e fonctions, au prix d'une exponentiation entière
				v = lucas_mul(v,q**e,n) #q**e ~ B
			#les valeurs atteintes par g sont croissantes et stagent à n lorsqu'atteints
			#=> pas besoin de les évaluer à chaque multiplication de l'indice
			#si g == n -> on a dépassé les facteurs, il faut recommencer avec la même borne (voire plus petite ?)
			#le tirage de a sera déterminant
			#si g==1 la borne n'est pas suffisante, on passe au Step 2 puis on augmente
			g = itools.gcd(v-2,n)
			if(g==n and verbose):
				print("N reached, resuming...")
		
		#Step 2 TODO : optimal? L'idée des multiples de 6 peut-elle être reprise pour p-1 Pollard ?
		if(g==1):
			c = (B//6)*6
			v6 = lucas_mul(v,6,n)
			Vl = []
			Vl.append(lucas_mul(v,c,n))
			Vl.append(lucas_mul(v,c+6,n))
			i = 2
			c = c+12
			while(c<B2):
				Vl.append( (Vl[i-1]*v6 - Vl[i-2]) % n )
				c += 6
				i += 1
			produit = 1
			for vi in Vl:
				produit = ( produit * (vi-v) ) % n
			g = itools.gcd(produit,n)
			if(g==1):
				B *= 10
			else:
				alternate = True
			
	if(g!=1 and g!=n):
		if(verbose): 
			if(alternate): print("pp1_williams_auto ( B' =",B2,") :\n",n,"=",g,"x",n//g)
			else: print("pp1_williams_auto ( B =",B,") :\n",n,"=",g,"x",n//g)
		return g
	else:
		if(verbose): print("pp1_williams_auto failed with", Bmax, ":(")
		return 0