diff --git a/algo.py b/algo.py
index 1b76bd8ee5cf305339fdbe8d5907300fd61cf88b..ae2f72245045583d11c94a3586f3c9e3767d8034 100644
--- a/algo.py
+++ b/algo.py
@@ -1,4 +1,5 @@
 import math
+import random
 
 def bachet_bezout(a, b):
     """Does the Bachet-Bezout algorithm on a of b
@@ -34,6 +35,7 @@ def bachet_bezout(a, b):
     
     return a, u[i-2], v[i-2]
 
+
 def inverse_modulaire(a, n):
     """Does the inverse modular of a by n, using Bachet-Bezout
 
@@ -47,6 +49,7 @@ def inverse_modulaire(a, n):
     
     return bachet_bezout(a, n)[1]
 
+
 def exponentiation_rapide(a, exp, n):
     """Does the quick explanation of a pow x modulo n
 
@@ -74,8 +77,9 @@ def exponentiation_rapide(a, exp, n):
     
     return int(r)
 
-def is_square(a):
-    """Check if a number is a perfect square, based on the "Babylonian algorithm" for square root,
+
+def is_perfect_square(a):
+    """Check if a number is a perfect square, based on the "Babylonian algorithm" (Héron's method) for square root,
     from : https://stackoverflow.com/questions/2489435/check-if-a-number-is-a-perfect-square 
         
     Args:
@@ -89,7 +93,7 @@ def is_square(a):
     seen = set([x])
     
     while x * x != a:
-        x = (x + (a // x)) // 2
+        x = (x + (a // x)) // 2 # arithmetic average
         
         if x in seen: 
             return False
@@ -98,6 +102,7 @@ def is_square(a):
         
     return True
 
+
 def fermat_factorization(n):
     """Does the Fermat's factorization on n,
     n = a² - b² = (a + b) * (a - b) = p * q <=> b² = a² - n
@@ -116,7 +121,7 @@ def fermat_factorization(n):
     a = math.ceil(math.sqrt(n)) # a = 26262277040 (for the key given)
     b2 = a**2 - n
     
-    while (not is_square(b2)): 
+    while ((a + int(math.sqrt(b2))) * (a - int(math.sqrt(b2))) != n): # (not is_perfect_square(b2)):
         a += 1
         b2 = a**2 - n      
           
@@ -126,6 +131,7 @@ def fermat_factorization(n):
     b = int(math.sqrt(b2))
     return (a, b)
 
+
 def decode_msg(M):
     """Decode a code UTF-8 in characters
     from : Niklaus Eggenberg
@@ -138,3 +144,89 @@ def decode_msg(M):
     """
     
     return M.to_bytes((M.bit_length() + 7) // 8, "little").decode("utf-8")
+
+
+def miller_rabin_test(d, n):
+    """Make the test of Miller Rabin (called for all k trials)
+    from : https://www.geeksforgeeks.org/primality-test-set-3-miller-rabin/ 
+
+    Args:
+        d (uint): the exponent d is an odd number such that d*2^r = n-1 for some r >= 1
+        n (uint): the modulo
+
+    Returns:
+        bool: False if n is composite, True if n is probably prime.
+    """
+    
+    # Pick a random number in [2..n-2], corner cases make sure that n > 4
+    a = 2 + random.randint(1, n - 4)
+
+    # Compute a^d % n
+    x = exponentiation_rapide(a, d, n)
+
+    if (x == 1 or x == n - 1):
+        return True
+
+    # Keep squaring x while one of the following doesn't happen
+    #   1. d does not reach n-1
+    #   2. (x^2) % n is not 1
+    #   3. (x^2) % n is not n-1
+    while (d != n - 1):
+        x = (x * x) % n
+        d *= 2
+
+        if (x == 1):
+            return False
+        if (x == n - 1):
+            return True
+
+    return False # Return composite
+
+
+def is_prime(n, k):
+    """Check if a number is prime using the test ofMiller Rabin.
+    from : https://www.geeksforgeeks.org/primality-test-set-3-miller-rabin/ 
+
+    Args:
+        n (uint): the value checked (n must be greater than 4)
+        k (uint): an input parameter that determines accuracy level, higher value of k indicates more accuracy.
+
+    Returns:
+        bool: True if the number is probably prime, False if n is composite
+    """
+
+    # Corner cases
+    if (n <= 1 or n == 4):
+        return False
+    if (n <= 3):
+        return True
+
+    # Find r such that n = 2^d * r + 1 for some r >= 1
+    d = n - 1
+    while (d % 2 == 0):
+        d //= 2
+
+    # Iterate given number of 'k' times
+    for i in range(k):
+        if (miller_rabin_test(d, n) == False):
+            return False
+
+    return True
+    
+
+def get_prime_divider(n):
+    """Get the first prime divider of n, starting with the root of n going to 0
+
+    Args:
+        n (uint): number used
+
+    Returns:
+        uint: the prime divider of n
+    """
+    
+    for i in reversed(range(math.ceil(math.sqrt(n)))):
+        
+        if (n % i == 0 and is_prime(i, 4)):
+            return i
+        
+    return 1
\ No newline at end of file
diff --git a/main.py b/main.py
index a2927fb28f063bc12be37fe570348268b959fdd9..91f63a0b600bc7845921e96bec9caf4178d6463a 100644
--- a/main.py
+++ b/main.py
@@ -27,12 +27,16 @@ def main():
     q = 0       # second prime number
     d = 0       # private key
 
-    #--- crack RSA ---
+    # --- crack RSA ---
     a, b = fermat_factorization(n)
     
     p = a + b
     q = a - b
     
+    # - second methode (sqrt(n) -> 0) -
+    # p = get_prime_divider(n)
+    # q = n // p
+    
     fi = (p - 1) * (q - 1)
     d = inverse_modulaire(e, fi) # get private key
 
diff --git a/main.tex b/main.tex
index 78c85b8d5898d0251e45867b74c52f3ae43afcd8..3886ca4f9708e1bf245092fc62d7336c206e5d03 100644
--- a/main.tex
+++ b/main.tex
@@ -1,12 +1,12 @@
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-% Rapport de physique 
+% Rapport de mathématique
 % Document LaTeX
 % Version 1.0 (22.09.22)
 % 
-% Ceci est un rapport sur un TP de physique, ou nous devions
-% simuler un systeme planetaire.
-% Par : Adrian Spycher, Costantino Volta
+% Ceci est un rapport sur un TP de mathématique, ou nous devions
+% cracker une clefs RSA que nous avions intercepté.
+% Par : Adrian Spycher, Flavio Moronne, Jad Tayan
 % 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -244,7 +244,7 @@ bmargin=1.25in]{geometry}
 Pour pouvoir cracker cette clefs RSA, nous avons utilisé la méthode de la factorisation de Fermat.
 C'est un algorithme de décomposition en produit de facteurs premiers d'un entier naturel, autrement dit, il va nous aider à retrouver $p$ et $q$ qui composent $n$.
 
-Cette algorithme dit que tout entier naturel impair $n$ se décompose en la différence de deux carrés qui peuvent être ensuite factorisé, on obtient :
+Dans ca factorisation, Fermat nous dit que tout entier naturel impair $n$ se décompose en la différence de deux carrés qui peuvent être ensuite factorisé, on obtient :
 \[
     n = a^2 - b^2 = (a + b)(a - b) = p \cdot q
 \]
@@ -254,12 +254,12 @@ Dans notre cas, on assicie la valeur de $p$ à $a + b$ et la valeur de $q$ à $a
 Si $p$ et $q$ sont tout deux différents de 1, alors ce sont des facteurs non triviaux de $n$.
 Autrement, on se retrouverait avec $n = n \cdot 1$, qui signifirait que $n$ est premier.
 
-Algébriquement, on voit que
+Algébriquement, on voit que :
 \[
     b^2 = a^2 - n
 \]
 
-Sachant que $a$ et $b$ sont deux nombre entier, on cherche une valeur de $a$ qui vérifie que $b^2$ ait une racine entière.
+Sachant que $a$ et $b$ sont deux nombre entier, on cherche une valeur de $a$ qui vérifie bien que $b^2$ ait une racine entière.
 Le point de départ de $a$ serra $\ \sqrt[]{n} \ $ arrondis au supérieur, car en-dessous, $b^2$ serait inférieur ou égale à 0, ce qui est impossible.
 
 \newpage % prettier
@@ -297,11 +297,12 @@ L'algorithme que nous avons fait se présente alors sous cette forme :
 \end{figure*}
 
 % TODO : add bibliogrpahy
-Pour savoir si $b^2$ avait une racine entière, nous avons utilisé une méthode que nous avons retrouver sur \textit{StackOverflow} qui est basé sur l'algorithme Babyloniens.
-Qui, en passant les détails, parcours différentes valeurs possibles calculé par rapport au nombre donnée.
-Si les valeurs testé ne sont pas la racine, c'est que la racine n'est pas entière.
+Pour savoir si $b^2$ avait une racine entière, nous avons utilisé une méthode que nous avons retrouver sur \textit{StackOverflow} qui est basé sur l'algorithme Babyloniens aussi appelé l'algorithme de Héron.
 
-Après avoir récupérer $p$ et $q$, nous pouvons retrouver la clef privée $d$, notamment, en calculant la valeur de $\phi$ :
+Cette algorithme cherche la racine en calculant, à chaque itération, la moyenne arithmétique de $b^2$, en partant de la moitier de $b$.
+Si une valeurs testé est répété, c'est que la racine n'est pas entière.
+
+Après avoir récupérer $p$ et $q$, nous pouvons retrouver la clef privée $d$, notamment en calculant la valeur de $\phi$ :
 \[
     \phi = (p - 1) \cdot (q - 1)
 \]\[
@@ -327,6 +328,55 @@ Et c'est comme ça que nous avons déchiffré le message.
 % astuces d'implémentation non triviales ou les bugs rencontrés, qui assureront aux prochains agents
 % de ne pas reproduire les mêmes erreurs !
 
+\subsubsection{Le problème du C}
+
+Pour implémenter ces algorithmes, nous avions d'abord choisis de le faire en C.
+Car le C étant compile et très proche de la machine, il est extrêmement rapide par rapport au Python qui était proposé.
+Malheureusement, après avoir implémenter la factorisation de Fermat, nous avons remarqué que le C n'était pas capable de gérer des nombres supérieurs à 64 bits.
+Nous avons essayer d'utilisé les \textit{uint128} pour pallier se problème, mais ce n'était pas suffisant.
+En plus de ne pas être pris en charge par des fonctions triviales comme \textit{printf} ou \textit{sqrt}, une force mystérieuse agissait sur lui de façons à ce qu'il fasse des erreurs de calcule.
+
+Nous avons alors décidé de traduire notre code C en Python de façon à ne plus avoir ces problèmes.
+
+\begin{remark}
+    Nous avons appris que le standard C 23, qui sort en 2023, prendra beaucoup plus en charge le \textit{uint128}.
+\end{remark}
+
+\subsubsection{L'optimisation}
+
+En Python, nous n'avons pas eu de problème, tout à été simple à implémenter.
+Ce qui nous a demandé le plus de réfléxion était l'optimisation du code, afin d'attendre le moins longtemps pour cracker la clef RSA.
+Nous avons remarqué assez vite qu'un problème se trouvait dans la condition de sortie de la boucle \textit{while} de la factorisation de Fermat.
+En effet, nous pensions que trouver une racine entière à l'aide de l'algorithme de Héron était la façon la plus rapide de calculer notre résultat.
+Car pour nous, la fonction \textit{sqrt} de Python était très lente comparé à l'algorithme de Héron, mais en réalité non.
+Nous avons alors choisis de changer la condition en utilisant directement :
+
+\begin{figure*}[!h]
+    \centering
+
+    \begin{subfigure}{.5\linewidth}
+
+        \begin{algorithmic}
+            \setstretch{1.3}
+
+            \While {$(a + sqrt(\text{b2}))(a - sqrt(\text{b2})) \myprogneq n$}
+
+            \State \dots
+
+            \EndWhile
+
+        \end{algorithmic}
+
+    \end{subfigure}
+\end{figure*}
+
+Après avoir changer cette ligne, notre code à été nettement plus rapide, avec une résolution de plus ou moins 45 minutes.
+
+\begin{remark}
+    La factorisation de Fermat fonctionne très rapidement si $p$ et $q$ sont proche, ce qui n'était forcément pas notre cas.
+    Sur une autre clef, nous avons pris 5 minutes.
+\end{remark}
+
 
 \newpage