Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
D
DS-Project
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
almohanad.hafez
DS-Project
Commits
b87b231b
Commit
b87b231b
authored
Nov 15, 2024
by
Almouhannad Hafez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor code
parent
e26ab76a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
473 additions
and
41 deletions
+473
-41
project.ipynb
project.ipynb
+232
-19
s_des.py
s_des.py
+241
-22
No files found.
project.ipynb
View file @
b87b231b
...
...
@@ -4,7 +4,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup"
"**Simplified Data Encryption Standard (SDES)** \n",
"***By: Almouhannad Hafez***\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setup"
]
},
{
...
...
@@ -22,6 +30,13 @@
"%reload_ext autoreload"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Define new instance of SDES class"
]
},
{
"cell_type": "code",
"execution_count": 2,
...
...
@@ -31,16 +46,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"key:\n",
"10101000000011011100011100110001010011101011010011\n",
"original text:\n",
"Almouhannad.Hafez\n",
"original text in binary:\n",
"010000010110110001101101011011110111010101101000011000010110111001101110011000010110010000101110010010000110000101100110011001010111101000000000\n",
"encrypted:\n",
"001010101011011010111010111001011101000010111000101010000110110000111100101010000110010001000111100001001100000011100001001000101100111000110111\n",
"decrypted:\n",
"Almouhannad.Hafez\n"
"A new instance of SDES was initilized with parameters\n",
"key_length: 50\n",
"rounds_count: 100\n"
]
}
],
...
...
@@ -49,15 +57,220 @@
" key_length = 50,\n",
" rounds_count = 100\n",
")\n",
"\n",
"print(f\"A new instance of SDES was initilized with parameters\\nkey_length: {sdes.key_length}\\nrounds_count: {sdes.rounds_count}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Get a random key"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Radnomly generated key of length 50:\n",
"11100001010100011000010000010000001001111111100001\n"
]
}
],
"source": [
"key = sdes.generate_random_key()\n",
"print(f\"Radnomly generated key of length {sdes.key_length}:\\n{key}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Apply encryption"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Text 'Hello, I'm Almouhannad Hafez' after encryption using sdes:\n",
"010001110101010100101001111001100011001010011110110010000111000010111111011001111001101110110101111001100011111000010000000100010100110010100110111101111000110001001100110110010010110101100100000110101010111000011100001110001011\n"
]
}
],
"source": [
"text = \"Hello, I'm Almouhannad Hafez\"\n",
"encrypted_binary_string = sdes.encrypt(plain_text = text,\n",
" key = key)\n",
"\n",
"print(f\"Text '{text}' after encryption using sdes:\\n{encrypted_binary_string}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Apply decryption\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Decrypted text:\n",
"Hello, I'm Almouhannad Hafez\u0000\n"
]
}
],
"source": [
"decrypted_plain_text = sdes.decrypt(binary_encrypted_input=encrypted_binary_string,\n",
" key = key)\n",
"print(f\"Decrypted text:\\n{decrypted_plain_text}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Let's try other parameters"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A new instance of SDES was initilized with parameters\n",
"key_length: 9\n",
"rounds_count: 2\n",
"Radnomly generated key of length 9:\n",
"110010000\n",
"Text 'Hello, I'm Almouhannad Hafez' after encryption using sdes:\n",
"111000111100010010010010000101110101110110111011110001100100100110011001101111010011100111000010000101110101101000110111111100101011111010111010010101100101110111100010000011011001110100111111011111101110110101100001000101000011\n",
"Decrypted text:\n",
"Hello, I'm Almouhannad Hafez\u0000\n"
]
}
],
"source": [
"sdes = SDES() # Default params\n",
"print(f\"A new instance of SDES was initilized with parameters\\nkey_length: {sdes.key_length}\\nrounds_count: {sdes.rounds_count}\")\n",
"\n",
"key = sdes.generate_random_key()\n",
"print(f\"key:\\n{key}\")\n",
"text = \"Almouhannad.Hafez\"\n",
"print(f\"original text:\\n{text}\")\n",
"print(f\"original text in binary:\\n{sdes.text_to_binary(text)}\")\n",
"enc = sdes.encrypt(text, key)\n",
"print(f\"encrypted:\\n{enc}\")\n",
"dec = sdes.decrypt(enc, key)\n",
"print(f\"decrypted:\\n{dec}\")\n"
"print(f\"Radnomly generated key of length {sdes.key_length}:\\n{key}\")\n",
"\n",
"text = \"Hello, I'm Almouhannad Hafez\"\n",
"encrypted_binary_string = sdes.encrypt(plain_text = text,\n",
" key = key)\n",
"print(f\"Text '{text}' after encryption using sdes:\\n{encrypted_binary_string}\")\n",
"\n",
"decrypted_plain_text = sdes.decrypt(binary_encrypted_input=encrypted_binary_string,\n",
" key = key)\n",
"print(f\"Decrypted text:\\n{decrypted_plain_text}\")"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A new instance of SDES was initilized with parameters\n",
"key_length: 10000000\n",
"rounds_count: 2\n",
"Text 'Hello, I'm Almouhannad Hafez' after encryption using sdes:\n",
"100011000111000000011100011100001110001100110101001110011000100111000010111110011100100110110100011100001110100101111110100100111000000110110100101100111110100101101100000000101110110111001011011111111101101100111101111001001101\n",
"Decrypted text:\n",
"Hello, I'm Almouhannad Hafez\u0000\n"
]
}
],
"source": [
"sdes = SDES(key_length=10000000) # Large key\n",
"print(f\"A new instance of SDES was initilized with parameters\\nkey_length: {sdes.key_length}\\nrounds_count: {sdes.rounds_count}\")\n",
"\n",
"key = sdes.generate_random_key()\n",
"# print(f\"Radnomly generated key of length {sdes.key_length}:\\n{key}\")\n",
"\n",
"text = \"Hello, I'm Almouhannad Hafez\"\n",
"encrypted_binary_string = sdes.encrypt(plain_text = text,\n",
" key = key)\n",
"print(f\"Text '{text}' after encryption using sdes:\\n{encrypted_binary_string}\")\n",
"\n",
"decrypted_plain_text = sdes.decrypt(binary_encrypted_input=encrypted_binary_string,\n",
" key = key)\n",
"print(f\"Decrypted text:\\n{decrypted_plain_text}\")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A new instance of SDES was initilized with parameters\n",
"key_length: 9\n",
"rounds_count: 10000\n",
"Radnomly generated key of length 9:\n",
"110011101\n",
"Text 'Hello, I'm Almouhannad Hafez' after encryption using sdes:\n",
"000011110100111010111100111000111111101011000001110001111101000001101011011111000101001110010111111000111111010110010000100001111011011001101101101010100001100011000110111000001010011101001110101101101000100100101000000100111111\n",
"Decrypted text:\n",
"Hello, I'm Almouhannad Hafez\u0000\n",
"====================\n",
"Encrpytion time: 1.8319964408874512s\n",
"Decrpytion time: 2.1560163497924805s\n"
]
}
],
"source": [
"import time\n",
"\n",
"sdes = SDES(rounds_count=10000) # Large number of rounds\n",
"key = sdes.generate_random_key()\n",
"text = \"Hello, I'm Almouhannad Hafez\"\n",
"start_encryption_time = time.time()\n",
"encrypted_binary_string = sdes.encrypt(plain_text = text,\n",
" key = key)\n",
"end_encryption_time = time.time()\n",
"decrypted_plain_text = sdes.decrypt(binary_encrypted_input=encrypted_binary_string,\n",
" key = key)\n",
"end_decryption_time = time.time()\n",
"\n",
"print(f\"A new instance of SDES was initilized with parameters\\nkey_length: {sdes.key_length}\\nrounds_count: {sdes.rounds_count}\")\n",
"print(f\"Radnomly generated key of length {sdes.key_length}:\\n{key}\")\n",
"print(f\"Text '{text}' after encryption using sdes:\\n{encrypted_binary_string}\")\n",
"print(f\"Decrypted text:\\n{decrypted_plain_text}\")\n",
"\n",
"# Print exection times:\n",
"print(\"==\"*10)\n",
"print(f\"Encrpytion time: {end_encryption_time-start_encryption_time}s\")\n",
"print(f\"Decrpytion time: {end_decryption_time-end_encryption_time}s\")"
]
}
],
...
...
s_des.py
View file @
b87b231b
...
...
@@ -17,11 +17,10 @@ class SDES:
# SDES is a block-cipher algorithm, uses blocks of size 12 bits
self
.
block_size
=
12
# SDED uses a fixed-length key (8bits
-
key) for each iteration
# SDED uses a fixed-length key (8bits key) for each iteration
self
.
round_key_length
=
8
# S1, S2 boxes:
self
.
S1
=
[[
"101"
,
"010"
,
"001"
,
"110"
,
"011"
,
"100"
,
"111"
,
"000"
],
[
"001"
,
"100"
,
"110"
,
"010"
,
"000"
,
"111"
,
"101"
,
"011"
]]
...
...
@@ -46,63 +45,226 @@ class SDES:
###############################################################################################
def
encrypt
(
self
,
plain_text
:
str
,
key
:
str
)
->
str
:
"""
Encrypts the given text using SDES with the given key
Parameters:
plain_text (str): The plain text to be encrypted
key (str): The key to be used for encryption
Returns:
encrypted_text (str): encrypted binary text resulting from the encryption
"""
# Type checking
if
not
isinstance
(
plain_text
,
str
):
raise
TypeError
(
f
"'plain_text' must be str, got {type(plain_text).__name__}"
)
if
not
isinstance
(
key
,
str
):
raise
TypeError
(
f
"'key' must be str, got {type(key).__name__}"
)
# Validation rules
if
len
(
plain_text
)
==
0
:
raise
ValueError
(
f
"Input text must not be empty"
)
if
len
(
key
)
!=
self
.
key_length
:
raise
ValueError
(
f
"The length of the key must be {self.key_length} bits, got {len(key)} bits"
)
# Convert the plain text to binary
binary_text
=
self
.
text_to_binary
(
plain_text
)
output
=
binary_text
# Initialize the output with the binary text
encrypted_text
=
binary_text
# Perform the rounds of encryption
for
i
in
range
(
self
.
rounds_count
):
output
=
self
.
perform_round
(
i
,
key
,
output
,
'enc'
)
return
output
encrypted_text
=
self
.
perform_round
(
i
,
key
,
encrypted_text
,
'enc'
)
return
encrypted_text
def
decrypt
(
self
,
binary_encrypted_input
:
str
,
key
:
str
)
->
str
:
"""
Decrypts the given binary text using SDES with the given key
Parameters:
binary_encrypted_input (str): binary text to be decrypted
key (str): key to be used for decryption
Returns:
decrypted_plain_text (str): plain text resulting from the decryption
"""
# Type checking
if
not
isinstance
(
binary_encrypted_input
,
str
):
raise
TypeError
(
f
"'binary_encrypted_input' must be str, got {type(binary_encrypted_input).__name__}"
)
if
not
isinstance
(
key
,
str
):
raise
TypeError
(
f
"'key' must be str, got {type(key).__name__}"
)
# Validation rules
if
len
(
binary_encrypted_input
)
==
0
:
raise
ValueError
(
f
"Input binary text must not be empty"
)
if
len
(
key
)
!=
self
.
key_length
:
raise
ValueError
(
f
"The length of the key must be {self.key_length} bits, got {len(key)} bits"
)
# Initialize the output
output
=
binary_encrypted_input
# Perform the rounds of decryption
for
i
in
range
(
self
.
rounds_count
):
output
=
self
.
perform_round
(
i
,
key
,
output
,
'dec'
)
# Convert the binary output to plain text
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
:
return
decrypted_plain_text
def
perform_round
(
self
,
round_number
:
int
,
key
:
str
,
input
:
str
,
mode
:
str
)
->
str
:
"""
Performs a single round of encryption or decryption
Parameters:
round_number (int): round number for the operation
key (str): key to be used for the operation
input (str): binary input to be processed
mode (str): Mode of operation ('enc' for encryption, 'dec' for decryption)
Returns:
output (str): The processed binary output after the round
"""
# Type checking
if
not
isinstance
(
round_number
,
int
):
raise
TypeError
(
f
"'round_number' must be int, got {type(round_number).__name__}"
)
if
not
isinstance
(
key
,
str
):
raise
TypeError
(
f
"'key' must be str, got {type(key).__name__}"
)
if
not
isinstance
(
input
,
str
):
raise
TypeError
(
f
"'input' must be str, got {type(input).__name__}"
)
if
not
isinstance
(
mode
,
str
):
raise
TypeError
(
f
"'mode' must be str, got {type(mode).__name__}"
)
# Validation rules
if
round_number
<
0
or
round_number
>=
self
.
rounds_count
:
raise
ValueError
(
f
"'round_number' must be between 0 and {self.rounds_count - 1}, got {round_number}"
)
if
mode
not
in
[
'enc'
,
'dec'
]:
raise
ValueError
(
f
"Invalid mode '{mode}'. Expected 'enc' or 'dec'."
)
# Get the blocks from the input
blocks
=
self
.
get_blocks
(
input
)
# Determine the round key based on the mode
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
#
Use keys in reverse order for decryption
round_number_inv
=
(
self
.
rounds_count
-
round_number
-
1
)
%
self
.
rounds_count
round_key
=
self
.
get_round_key
(
key
,
round_number_inv
)
round_key
=
self
.
get_round_key
(
key
,
round_number_inv
)
# Initialize output
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
:
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
]
blocks
[
i
]
=
block
[
self
.
block_size
//
2
:]
+
block
[:
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
]
"""
Processes a block of data using round key
Parameters:
round_key (str): The key to be used for this round
old_block (str): The block of data to be processed
Returns:
new_block (str): The processed block after applying the round function
"""
# Type checking
if
not
isinstance
(
round_key
,
str
):
raise
TypeError
(
f
"'round_key' must be str, got {type(round_key).__name__}"
)
if
not
isinstance
(
old_block
,
str
):
raise
TypeError
(
f
"'old_block' must be str, got {type(old_block).__name__}"
)
# Validation rules
if
len
(
round_key
)
!=
self
.
round_key_length
:
raise
ValueError
(
f
"The length of 'round_key' must be {self.round_key_length} bits, got {len(round_key)} bits"
)
if
len
(
old_block
)
!=
self
.
block_size
:
raise
ValueError
(
f
"The length of 'old_block' must be {self.block_size} bits, got {len(old_block)} bits"
)
# Split the old block into left and right parts
L_old
,
R_old
=
old_block
[
0
:
self
.
block_size
//
2
],
old_block
[
self
.
block_size
//
2
:]
# Perform the processing
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
# Combine the new left and right parts into a new block
new_block
=
L_new
+
R_new
return
new_block
def
f
(
self
,
key
:
str
,
R
:
str
)
->
str
:
"""
Applies the round function on the right half of the block using round key
Parameters:
key (str): The key to be used for this round
R (str): The right half of the block to be processed
Returns:
new_R (str): The processed right half after applying the round function
"""
# Type checking
if
not
isinstance
(
key
,
str
):
raise
TypeError
(
f
"'key' must be str, got {type(key).__name__}"
)
if
not
isinstance
(
R
,
str
):
raise
TypeError
(
f
"'R' must be str, got {type(R).__name__}"
)
# Validation rules
if
len
(
key
)
!=
self
.
round_key_length
:
raise
ValueError
(
f
"The length of 'key' must be {self.round_key_length} bits, got {len(key)} bits"
)
if
len
(
R
)
!=
self
.
block_size
//
2
:
raise
ValueError
(
f
"The length of 'R' must be {self.block_size // 2} bits, got {len(R)} bits"
)
# Perform the processing
# Extension
new_R
=
self
.
E
(
R
)
# XOR with key
new_R
=
self
.
binary_strings_xor
(
new_R
,
key
)
# Apply S boxes
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
new_R
=
new_R_L
+
new_R_R
return
new_R
def
E
(
self
,
R
:
str
)
->
str
:
"""
Extends the right half of the block
Parameters:
R (str): The right half of the block to be extended
Returns:
extended_R (str): The extended version of the right half
"""
# Type checking
if
not
isinstance
(
R
,
str
):
raise
TypeError
(
f
"'R' must be str, got {type(R).__name__}"
)
# Validation rules
if
len
(
R
)
!=
self
.
block_size
//
2
:
raise
ValueError
(
f
"The length of 'R' must be {self.block_size // 2} bits, got {len(R)} bits"
)
# Perform the extension
extended_R
=
''
extended_R
+=
(
R
[
0
]
+
R
[
1
])
extended_R
+=
R
[
3
]
...
...
@@ -113,9 +275,35 @@ class SDES:
return
extended_R
def
apply_S
(
self
,
R
:
str
,
S_number
:
int
)
->
str
:
"""
Applies the S-box transformation to the input
Parameters:
R (str): The input to be transformed (must be 4 bits)
S_number (int): The S-box number to use (1 or 2)
Returns:
str: The transformed output after applying the S-box
"""
# Type checking
if
not
isinstance
(
R
,
str
):
raise
TypeError
(
f
"'R' must be str, got {type(R).__name__}"
)
if
not
isinstance
(
S_number
,
int
):
raise
TypeError
(
f
"'S_number' must be int, got {type(S_number).__name__}"
)
# Validation rules
if
len
(
R
)
!=
4
:
raise
ValueError
(
f
"The length of 'R' must be 4 bits, got {len(R)} bits"
)
if
S_number
not
in
[
1
,
2
]:
raise
ValueError
(
"S_number must be either 1 or 2"
)
# Calculate row and column indices for the S-box lookup
row_index
=
int
(
R
[
0
],
2
)
col_index
=
int
(
R
[
1
:
4
],
2
)
if
(
S_number
==
1
):
# Apply the appropriate S-box
if
S_number
==
1
:
return
self
.
S1
[
row_index
][
col_index
]
else
:
return
self
.
S2
[
row_index
][
col_index
]
...
...
@@ -258,9 +446,40 @@ class SDES:
return
blocks
def
binary_strings_xor
(
self
,
binary_string_1
:
str
,
binary_string_2
:
str
)
->
str
:
"""
Performs the XOR operation on two binary strings
Parameters:
binary_string_1 (str): The first binary string
binary_string_2 (str): The second binary string
Returns:
xor_result_str (str): The result of the XOR operation as a binary string
"""
# Type checking
if
not
isinstance
(
binary_string_1
,
str
):
raise
TypeError
(
f
"'binary_string_1' must be str, got {type(binary_string_1).__name__}"
)
if
not
isinstance
(
binary_string_2
,
str
):
raise
TypeError
(
f
"'binary_string_2' must be str, got {type(binary_string_2).__name__}"
)
# Validation rules
if
len
(
binary_string_1
)
!=
len
(
binary_string_2
):
raise
ValueError
(
"Both binary strings must have the same length"
)
for
char
in
binary_string_1
:
if
char
not
in
'01'
:
raise
ValueError
(
f
"'binary_string_1' contains non-binary characters: {binary_string_1}"
)
for
char
in
binary_string_2
:
if
char
not
in
'01'
:
raise
ValueError
(
f
"'binary_string_2' contains non-binary characters: {binary_string_2}"
)
# Perform XOR operation after converting to int
num1
=
int
(
binary_string_1
,
2
)
num2
=
int
(
binary_string_2
,
2
)
xor_result
=
num1
^
num2
xor_result_str
=
bin
(
xor_result
)[
2
:]
# Ensure the result is zero-padded to the same length
xor_result_str
=
xor_result_str
.
zfill
(
len
(
binary_string_1
))
return
xor_result_str
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment