#!/usr/bin/env python3

import unittest
from Cryptotools.Numbers.primeNumber import isPrimeNumber
from math import sqrt, isqrt, ceil
from random import choice


class TestBreakingRSA(unittest.TestCase):
    def test_breaking_rsa(self):
        # primes = self._list_primes()
        #p = choice(primes)
        #q = choice(primes)
        self._breaking_rsa(7901, 7817)
        self._breaking_rsa(7907, 7919)
        self._breaking_rsa(7103, 7127) # Works
        # self._breaking_rsa(7103, 7121) # Doesn't works

    def _breaking_rsa(self, p, q):
        # print(f"p = {p}")
        # print(f"q = {q}")
        n = p * q
        # print(f"n = {n}")
        
        # a = isqrt(n) + 1
        a = ceil(sqrt(n))
        iteration = 1
        while True:
            b2 = (a ** 2) - n
            sqb2 = sqrt(b2)
            if b2 % 2 == 0.0:
                b = sqrt(b2)
                break
            a = a + 1
            iteration += 1
        # print(f"Iteration: {iteration}") 
        # print(f"a = {a}")
        # print(f"b2 = {b2}")
        # print(f"b = {b}")
        p = int((a + b))
        q = int((a - b))
        #N = (a + b) * (a - b)
        N = p * q
        # print(isPrimeNumber(p))
        # print(isPrimeNumber(q))
        # print(N)
        # print()
        self.assertTrue(N == n)

    def _list_primes(self):
        l = list()
        i = 100 # We start at 100
        while (len(l) < 1000):
            if isPrimeNumber(i):
                l.append(i)
            i = i + 1
        return l

unittest.main()
