diff --git a/main.py b/main.py
index 462dc75ee11e52a20a1c728c712ae2868f47ffe7..ac6268daa7e0f4aa0a9d11039def542261e2af99 100644
--- a/main.py
+++ b/main.py
@@ -4,27 +4,56 @@ Authors : Rayyan BELHI, Dario GENGA
 Date : 2022
 """
 
-def modulo(a, b): # a mod b = res
+
+# Return a mod b
+def modulo(a, b):
     res = 0
     tmp = 0
-    if (a < b):
+    if a < b:
         res = a
-    elif (a > b):
+    elif a > b:
         tmp = a // b
         res = a - (b*tmp)
     else:
         res = 0
     return res
 
-def add_mod(a,b): # (a+b) mod 16 (=2^4) // p.3
+
+# Return (a+b) mod 16
+def add_mod(a, b):
+    if type(a) == str:
+        a = int(a, 2)
+
+    if type(b) == str:
+        b = int(b, 2)
+
     tmp = a + b
-    res = modulo(tmp, 16)
-    return res
+    res = modulo(tmp, 2**4)
+    return format(res, '04b')
+
+
+# Return (a*b) mod 17
+def mul_mod(a, b):
+    if type(a) == str:
+        a = int(a, 2)
+
+    if type(b) == str:
+        b = int(b, 2)
+
+    # If we have a nibble of 0000, then this corresponds to 16 (base 10) that is congruent to -1 modulo 17
+    if a == 0:
+        a = 16
+    if b == 0:
+        b = 16
 
-def mul_mod(a,b): # (a*b) mod 17 // p.3
     tmp = a * b
-    res = modulo(tmp, 17)
-    return res
+    res = modulo(tmp, 2**4 + 1)
+    # Because we work with nibbles and  2^4 + 1 = 17, if we obtain 16 as result this will correspond to 10000 in binary.
+    # This value can't be stored in a nibble, so we must exclude it
+    if res == 2**4:
+        res = 0
+
+    return format(res, '04b')
 
 
 def xor(a,b):#a XOR b = str(binaire)
@@ -62,38 +91,99 @@ def xor(a,b):#a XOR b = str(binaire)
         i += 1
     return res
 
-def create_key_tables():
-    pass
-
 
-def round():
-    # 1. Multiply X1 and the first subkey Z1
-    # 2. Add X2 and the second subkey Z2
-    # 3. Add X3 and the third subkey Z3
-    # 4. Multiply X4 and the fourth subkey Z4
+# Shift the 6 first bit of the key to the end
+def shift_key(key):
+    bit_to_shift = key[0:6]
+    new_key = key[6:] + bit_to_shift
+    return new_key
+
+
+# Create the table of the 28 subkeys used for the IDEA encryption
+def create_subkeys_table(key):
+    subkeys = []
+    nibble = ''
+
+    while len(subkeys) < 28:
+        # Decompose the key into 8 nibbles
+        for bit in key:
+            nibble += bit
+            if len(nibble) >= 4 and len(subkeys) < 28:
+                subkeys.append(nibble)
+                nibble = ''
+
+        # Shift the key for the next round
+        key = shift_key(key)
+
+    return subkeys
+
+
+# Encrypt the text with the key by using the IDEA algorithm
+def encrypt(plaintext, key):
+    input_block = plaintext
+    subkeys = create_subkeys_table(key)
+
+    current_round = 0
+    total_rounds = 4
+
+    while current_round <= total_rounds:
+        # 1. Multiply X1 and the first subkey Z1
+        res_1 = mul_mod(input_block[0:4], subkeys[0])
+        # 2. Add X2 and the second subkey Z2
+        res_2 = add_mod(input_block[4:8], subkeys[1])
+        # 3. Add X3 and the third subkey Z3
+        res_3 = add_mod(input_block[8:12], subkeys[2])
+        # 4. Multiply X4 and the fourth subkey Z4
+        res_4 = mul_mod(input_block[12:16], subkeys[3])
+
+        # Don't do the next steps if this is the final round
+        if current_round < total_rounds:
+            # 5. Bitwise XOR the results of steps 1 and 3
+            res_5 = xor(res_1, res_3)
+            # 6. Bitwise XOR the results of steps 2 and 4
+            res_6 = xor(res_2, res_4)
+            # 7. Multiply the result of step 5 and the fifth subkey Z5
+            res_7 = mul_mod(res_5, subkeys[4])
+            # 8. Add the results of step 6 and 7
+            res_8 = add_mod(res_6, res_7)
+            # 9. Multiply the result of step 8 and the sixth subkey Z6
+            res_9 = mul_mod(res_8, subkeys[5])
+            # 10. Add the results of steps 7 and 9
+            res_10 = add_mod(res_7, res_9)
+            # 11. Bitwise XOR the results of steps 1 and 9
+            res_11 = xor(res_1, res_9)
+            # 12. Bitwise XOR the results of steps 3 and 9
+            res_12 = xor(res_3, res_9)
+            # 13. Bitwise XOR the results of steps 2 and 10
+            res_13 = xor(res_2, res_10)
+            # 14. Bitwise XOR the results of steps 4 and 10
+            res_14 = xor(res_4, res_10)
+            # Create the input for the next round with the final results
+            # The results of the steps 12 and 13 are swapped
+            input_block = res_11 + res_13 + res_12 + res_14
+
+        current_round += 1
+        subkeys = subkeys[6:]
+
+    ciphertext = res_1 + res_2 + res_3 + res_4
+    return ciphertext
 
-    # Don't do the next steps if this is the final round
 
-    # 5. Bitwise XOR the results of steps 1 and 3
-    # 6. Bitwise XOR the results of steps 2 and 4
-    # 7. Multiply the result of step 5 and the fifth subkey Z5
-    # 8. Add the results of step 6 and 7
-    # 9. Multiply the result of step 8 and the sisth subkey Z6
-    # 10. Add the results of steps 7 and 9
-    # 11. Bitwise XOR the results of steps 1 and 9
-    # 12. Bitwise XOR the results of steps 3 and 9
-    # 13. Bitwise XOR the results of steps 2 and 10
-    # 14. Bitwise XOR the results of steps 4 and 10
-
-    pass
+def main():
+    plaintext = '1001110010101100'
+    key = '11011100011011110011111101011001'
+    expected_ciphertext = '1011101101001011'
 
+    ciphertext = encrypt(plaintext, key)
 
-def main():
-    plaintext = 1001110010101100
-    key = 11011100011011110011111101011001
-    expected_ciphertext = 1011101101001011
+    print("The original message is : " + plaintext)
+    print("The key is : " + key)
+    print("The ciphertext obtained is : " + ciphertext)
 
-    print("hello world")
+    if ciphertext == expected_ciphertext:
+        print("The encryption has been successful !")
+    else:
+        print("An error has occurred during the encryption...")
 
 
 if __name__ == "__main__":