Commit e26ab76a authored by Almouhannad Hafez's avatar Almouhannad Hafez

Refactor code

parent a7752fb6
...@@ -32,15 +32,15 @@ ...@@ -32,15 +32,15 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"key:\n", "key:\n",
" 00011100000101001110011110000000100100001000101011\n", "10101000000011011100011100110001010011101011010011\n",
"original text:\n", "original text:\n",
" Almouhannad.Hafez\n", "Almouhannad.Hafez\n",
"original text in binary:\n", "original text in binary:\n",
" 010000010110110001101101011011110111010101101000011000010110111001101110011000010110010000101110010010000110000101100110011001010111101000000000\n", "010000010110110001101101011011110111010101101000011000010110111001101110011000010110010000101110010010000110000101100110011001010111101000000000\n",
"encrypted:\n", "encrypted:\n",
" 000100001010000110100001100010010000111110100100111001011101001101010000111001011101111110001010110011010100101001110000110101001111100100110011\n", "001010101011011010111010111001011101000010111000101010000110110000111100101010000110010001000111100001001100000011100001001000101100111000110111\n",
"decrypted:\n", "decrypted:\n",
" Almouhannad.Hafez\n" "Almouhannad.Hafez\n"
] ]
} }
], ],
...@@ -50,14 +50,14 @@ ...@@ -50,14 +50,14 @@
" rounds_count = 100\n", " rounds_count = 100\n",
")\n", ")\n",
"key = sdes.generate_random_key()\n", "key = sdes.generate_random_key()\n",
"print(f\"key:\\n {key}\")\n", "print(f\"key:\\n{key}\")\n",
"text = \"Almouhannad.Hafez\"\n", "text = \"Almouhannad.Hafez\"\n",
"print(f\"original text:\\n {text}\")\n", "print(f\"original text:\\n{text}\")\n",
"print(f\"original text in binary:\\n {sdes.text_to_binary(text)}\")\n", "print(f\"original text in binary:\\n{sdes.text_to_binary(text)}\")\n",
"enc = sdes.encrypt(text, key)\n", "enc = sdes.encrypt(text, key)\n",
"print(f\"encrypted:\\n {enc}\")\n", "print(f\"encrypted:\\n{enc}\")\n",
"dec = sdes.decrypt(enc, key)\n", "dec = sdes.decrypt(enc, key)\n",
"print(f\"decrypted:\\n {dec}\")\n" "print(f\"decrypted:\\n{dec}\")\n"
] ]
} }
], ],
......
...@@ -2,6 +2,10 @@ import random ...@@ -2,6 +2,10 @@ import random
class SDES: class SDES:
###############################################################################################
# Constructor
###############################################################################################
def __init__(self, rounds_count: int = 2, key_length: int = 9): def __init__(self, rounds_count: int = 2, key_length: int = 9):
""" """
Initialize the SDES algorithm with pre-defined parameters Initialize the SDES algorithm with pre-defined parameters
...@@ -17,7 +21,6 @@ class SDES: ...@@ -17,7 +21,6 @@ class SDES:
self.round_key_length = 8 self.round_key_length = 8
# S1, S2 boxes: # S1, S2 boxes:
self.S1 = [["101", "010", "001", "110", "011", "100", "111", "000"], self.S1 = [["101", "010", "001", "110", "011", "100", "111", "000"],
["001", "100", "110", "010", "000", "111", "101", "011"]] ["001", "100", "110", "010", "000", "111", "101", "011"]]
...@@ -38,6 +41,84 @@ class SDES: ...@@ -38,6 +41,84 @@ class SDES:
self.rounds_count = rounds_count self.rounds_count = rounds_count
self.key_length = key_length self.key_length = key_length
###############################################################################################
# Main algorithm functions
###############################################################################################
def encrypt(self, plain_text: str, key: str) -> str:
binary_text = self.text_to_binary(plain_text)
output = binary_text
for i in range(self.rounds_count):
output = self.perform_round(i, key, output, 'enc')
return output
def decrypt(self, binary_encrypted_input: str, key: str) -> str:
output = binary_encrypted_input
for i in range(self.rounds_count):
output = self.perform_round(i, key, output, 'dec')
decrypted_plain_text = self.binary_to_text(output)
return decrypted_plain_text
def perform_round (self, round_number: int, key: int, input: str, mode: str) -> str:
blocks = self.get_blocks(input)
if mode == 'enc':
round_key = self.get_round_key(key, round_number)
elif mode == 'dec':
# Do the same process of encryption, but using keys in reverse order
round_number_inv = (self.rounds_count - round_number - 1) % self.rounds_count
round_key = self.get_round_key(key, round_number_inv)
output = ''
for i in range(len(blocks)):
blocks[i] = self.process_block(round_key, blocks[i])
# Flip LR in the last round
if round_number == self.rounds_count -1:
block = blocks[i]
blocks[i] = ''
blocks[i] += block[self.block_size//2 : self.block_size]
blocks[i] += block[0:self.block_size//2]
output += blocks[i]
return output
def process_block(self, round_key: str, old_block: str) -> str:
L_old, R_old = old_block[0:self.block_size//2] , old_block[self.block_size//2 : self.block_size]
L_new = R_old
R_new = self.f(round_key, R_old)
R_new = self.binary_strings_xor(R_new, L_old)
new_block = ''
new_block += L_new
new_block += R_new
return new_block
def f(self, key: str, R: str) -> str:
new_R = self.E(R)
new_R = self.binary_strings_xor(new_R, key)
new_R_L, new_R_R = new_R[0:4], new_R[4:8]
new_R_L = self.apply_S(new_R_L, 1)
new_R_R = self.apply_S(new_R_R, 2)
new_R = ''
new_R += new_R_L
new_R += new_R_R
return new_R
def E(self, R: str) -> str:
extended_R = ''
extended_R += (R[0] + R[1])
extended_R += R[3]
extended_R += (R[2] + R[3])
extended_R += R[2]
extended_R += (R[4] + R[5])
return extended_R
def apply_S(self, R: str, S_number: int) -> str:
row_index = int(R[0], 2)
col_index = int(R[1:4], 2)
if (S_number == 1):
return self.S1[row_index][col_index]
else:
return self.S2[row_index][col_index]
def get_round_key(self, key: str, round_number: int) -> str: def get_round_key(self, key: str, round_number: int) -> str:
""" """
...@@ -72,6 +153,10 @@ class SDES: ...@@ -72,6 +153,10 @@ class SDES:
return round_key return round_key
###############################################################################################
# Other helper functions
###############################################################################################
def generate_random_key(self) -> str: def generate_random_key(self) -> str:
""" """
Generate a random binary key of length = self.key_length Generate a random binary key of length = self.key_length
...@@ -172,86 +257,10 @@ class SDES: ...@@ -172,86 +257,10 @@ class SDES:
blocks = [input[i:i+self.block_size] for i in range(0, len(input), self.block_size)] blocks = [input[i:i+self.block_size] for i in range(0, len(input), self.block_size)]
return blocks return blocks
###############################################################################################
def encrypt(self, plain_text: str, key: str) -> str:
binary_text = self.text_to_binary(plain_text)
output = binary_text
for i in range(self.rounds_count):
output = self.perform_round(i, key, output, 'enc')
return output
def decrypt(self, binary_encrypted_input: str, key: str) -> str:
output = binary_encrypted_input
for i in range(self.rounds_count):
output = self.perform_round(i, key, output, 'dec')
decrypted_plain_text = self.binary_to_text(output)
return decrypted_plain_text
def perform_round (self, round_number: int, key: int, input: str, mode: str) -> str:
blocks = self.get_blocks(input)
if mode == 'dec':
round_number_inv = (self.rounds_count - round_number - 1) % self.rounds_count
round_key = self.get_round_key(key, round_number_inv)
else:
round_key = self.get_round_key(key, round_number)
output = ''
for i in range(len(blocks)):
blocks[i] = self.process_block(round_key, blocks[i])
if round_number == self.rounds_count -1:
block = blocks[i]
blocks[i] = ''
blocks[i] += block[self.block_size//2 : self.block_size]
blocks[i] += block[0:self.block_size//2]
output += blocks[i]
return output
def process_block(self, round_key: str, old_block: str) -> str:
L_old, R_old = old_block[0:self.block_size//2] , old_block[self.block_size//2 : self.block_size]
L_new = R_old
R_new = self.f(round_key, R_old)
R_new = self.binary_strings_xor(R_new, L_old)
new_block = ''
new_block += L_new
new_block += R_new
return new_block
def f(self, key: str, R: str) -> str:
new_R = self.E(R)
new_R = self.binary_strings_xor(new_R, key)
new_R_L, new_R_R = new_R[0:4], new_R[4:8]
new_R_L = self.apply_S(new_R_L, 1)
new_R_R = self.apply_S(new_R_R, 2)
new_R = ''
new_R += new_R_L
new_R += new_R_R
return new_R
def E(self, R: str) -> str:
extended_R = ''
extended_R += (R[0] + R[1])
extended_R += R[3]
extended_R += (R[2] + R[3])
extended_R += R[2]
extended_R += (R[4] + R[5])
return extended_R
def apply_S(self, R: str, S_number: int) -> str:
row_index = int(R[0], 2)
col_index = int(R[1:4], 2)
if (S_number == 1):
return self.S1[row_index][col_index]
else:
return self.S2[row_index][col_index]
def binary_strings_xor(self, binary_string_1: str, binary_string_2: str) -> str: def binary_strings_xor(self, binary_string_1: str, binary_string_2: str) -> str:
num1 = int(binary_string_1, 2) num1 = int(binary_string_1, 2)
num2 = int(binary_string_2, 2) num2 = int(binary_string_2, 2)
xor_result = num1 ^ num2 xor_result = num1 ^ num2
xor_result_str = bin(xor_result)[2:] xor_result_str = bin(xor_result)[2:]
xor_result_str = xor_result_str.zfill(len(binary_string_1)) xor_result_str = xor_result_str.zfill(len(binary_string_1))
return xor_result_str return xor_result_str
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment