Telethon/telethon/crypto/factorization.py
2017-09-04 17:10:04 +02:00

72 lines
1.8 KiB
Python

from random import randint
try:
import sympy.ntheory
except ImportError:
sympy = None
class Factorization:
@staticmethod
def find_small_multiplier_lopatin(what):
"""Finds the small multiplier by using Lopatin's method"""
g = 0
for i in range(3):
q = (randint(0, 127) & 15) + 17
x = randint(0, 1000000000) + 1
y = x
lim = 1 << (i + 18)
for j in range(1, lim):
a, b, c = x, x, q
while b != 0:
if (b & 1) != 0:
c += a
if c >= what:
c -= what
a += a
if a >= what:
a -= what
b >>= 1
x = c
z = y - x if x < y else x - y
g = Factorization.gcd(z, what)
if g != 1:
break
if (j & (j - 1)) == 0:
y = x
if g > 1:
break
p = what // g
return min(p, g)
@staticmethod
def gcd(a, b):
"""Calculates the greatest common divisor"""
while a != 0 and b != 0:
while b & 1 == 0:
b >>= 1
while a & 1 == 0:
a >>= 1
if a > b:
a -= b
else:
b -= a
return a if b == 0 else b
@staticmethod
def factorize(pq):
"""Factorizes the given number and returns both
the divisor and the number divided by the divisor
"""
if sympy:
return tuple(sympy.ntheory.factorint(pq).keys())
else:
divisor = Factorization.find_small_multiplier_lopatin(pq)
return divisor, pq // divisor