def main2(): a = continued_fraction(Integer(17) / Integer(23)) print(a) b = continued_fraction(Integer(6) / Integer(23)) print(b) A = CFF(a) B = CFF(b) print(A + B) print(A.value()) print(a.value())
def main5(): c = continued_fraction( [Integer(1), Integer(2), Integer(3), Integer(4), Integer(5)]) print(c) print(c.convergents()) print([c.p(n) for n in range(c.length())]) print([c.q(n) for n in range(c.length())])
def main6(): c = continued_fraction([Integer(1)] * (8)) v = [(i, c.p(i) / c.q(i)) for i in range(c.length())] P = point(v, rgbcolor=(0, 0, 1), pointsize=40) L = line(v, rgbcolor=(0.5, 0.5, 0.5)) L2 = line([(Integer(0), c.value()), (c.length() - Integer(1), c.value())], thickness=0.5, rgbcolor=(0.7, 0, 0)) (L + L2 + P).save(filename="continued_fraction.png") print("Graph is saved as continued_fraction.png")
def main4(): c = continued_fraction(pi) for n in range(-1, 13): print(c.p(n) * c.q(n - Integer(1)) - c.q(n) * c.p(n - Integer(1)), end=' ') print() for n in range(Integer(13)): print(c.p(n) * c.q(n - Integer(2)) - c.q(n) * c.p(n - Integer(2)), end=' ') print()
def wiener(e, n): m = 12345 c = pow(m, e, n) list1 = continued_fraction(Integer(e) / Integer(n)) conv = list1.convergents() for i in conv: d = int(i.denominator()) m1 = pow(c, d, n) if m1 == m: return d
def wiener(e, n): m = 12345 c = pow(m, e, n) q0 = 1 list1 = continued_fraction(Integer(e) / Integer(n)) conv = list1.convergents() for i in conv: k = i.numerator() q1 = i.denominator() for r in range(20): for s in range(20): d = r * q1 + s * q0 m1 = pow(c, d, n) if m1 == m: return d q0 = q1
def attack(n, e): """ Recovers the prime factors of a modulus and the private exponent if the private exponent is too small. :param n: the modulus :param e: the public exponent :return: a tuple containing the prime factors of the modulus and the private exponent, or None if the private exponent was not found """ convergents = continued_fraction(Integer(e) / Integer(n)).convergents() for c in convergents: k = c.numerator() d = c.denominator() if k == 0 or (e * d - 1) % k != 0: continue phi = (e * d - 1) // k factors = known_phi.factorize(n, phi) if factors: return *factors, d
def attack(n, e, max_s=20000, max_r=100, max_t=100): """ Recovers the prime factors of a modulus and the private exponent if the private exponent is too small. More information: Dujella A., "Continued fractions and RSA with small secret exponent" :param n: the modulus :param e: the public exponent :param max_s: the amount of s values to try (default: 20000) :param max_r: the amount of r values to try for each s value (default: 100) :param max_t: the amount of t values to try for each s value (default: 100) :return: a tuple containing the prime factors of the modulus and the private exponent, or None if the private exponent was not found """ i_n = Integer(n) i_e = Integer(e) threshold = i_e / i_n + (RealNumber(2.122) * i_e) / (i_n * i_n.sqrt()) convergents = continued_fraction(i_e / i_n).convergents() for i in range(1, len(convergents) - 2, 2): if convergents[i + 2] < threshold < convergents[i]: m = i break for s in range(max_s): for r in range(max_r): k = r * convergents[m + 1].numerator() + s * convergents[m + 1].numerator() d = r * convergents[m + 1].denominator() + s * convergents[m + 1].denominator() if k == 0 or (e * d - 1) % k != 0: continue phi = (e * d - 1) // k factors = known_phi.factorize(n, phi) if factors: return *factors, d for t in range(max_t): k = s * convergents[m + 2].numerator() - t * convergents[m + 1].numerator() d = s * convergents[m + 2].denominator() - t * convergents[m + 1].denominator() if k == 0 or (e * d - 1) % k != 0: continue phi = (e * d - 1) // k factors = known_phi.factorize(n, phi) if factors: return *factors, d
def main1(): print(continued_fraction(Integer(17) / Integer(23))) print(continued_fraction(e)) print(continued_fraction_list(e, bits=21)) print(continued_fraction_list(e, bits=30))
def main3(): c = continued_fraction(pi) print(c.convergents()[:6].list())