Skip to content
Snippets Groups Projects
Commit 44649844 authored by Viken's avatar Viken
Browse files

Update of the 6th of July

parent 15cde895
No related branches found
No related tags found
No related merge requests found
Showing
with 31593 additions and 743 deletions
This diff is collapsed.
File added
METRICS = {
# [encryption, decryption]
"integrity": False,
"implementation_size": [0,0],
"ram_consumption": [0,0],
"throughput": [0,0],
"execution_time": [0,0],
"memory_usage": [0,0],
"cpu_cycles": [0,0],
}
CIPHER =["AES", "SIMON", "SPECK"]
# Retreiving the measurments already made and saved in .json files
import json
MEASUREMENTS = {
f'{cipher}' : dict(METRICS) for cipher in CIPHER
}
for cipher in CIPHER :
with open(f"./src/block_cipher/metrics/{cipher}_metrics.json", 'r') as file:
MEASUREMENTS[cipher] = json.load(file)
'''
ANALYSIS
We plot the following informations :
'''
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import Crypto.Cipher.AES as AES
import os
import json
from measurement_functions.functions import measure_software_performance
'''
AES :
works with 16, 24, or 32-byte long key and block
for lightweight application we take the lowest
'''
KEY = os.urandom(16) # Generate a random 16-byte long key
MODE = AES.MODE_ECB
PLAINTEXT = os.urandom(16) # Generate a random 16-byte long block
DICT_PATH = './src/block_cipher/metrics/AES_metrics.json'
def encryption_measurement(plaintext, key, mode):
perf = measure_software_performance(AES.new, key=key, mode=mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
metrics = [b''] + metrics
perf = measure_software_performance(cipher.encrypt, plaintext)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
def decryption_measurement(encryptedtext, key, mode):
perf = measure_software_performance(AES.new, key=key, mode=mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
metrics = [b''] + metrics
perf = measure_software_performance(cipher.decrypt, encryptedtext)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
if __name__ == '__main__':
encryption = encryption_measurement(PLAINTEXT, KEY, MODE)
decryption = decryption_measurement(encryption[0], KEY, MODE)
METRICS = {
# [encryption, decryption]
"integrity": decryption[0] == PLAINTEXT,
"implementation_size": [encryption[1], decryption[1]],
"ram_consumption": [encryption[2], decryption[2]],
"throughput": [encryption[3], decryption[3]],
"execution_time": [encryption[4], decryption[4]],
"memory_usage": [encryption[5], decryption[5]],
"cpu_cycles": [encryption[6], decryption[6]],
}
with open(DICT_PATH, 'w') as file:
json.dump(METRICS, file)
from simon import SimonCipher
import os
import json
from measurement_functions.functions import measure_software_performance
'''
SPECK :
works with
key : Block :
64 (8 Bytes) 32 (4 Bytes)
72 or 96 48
96 or 128 64
96 or 144 96
128 or 192 or 256 128
for lightweight application we take the lowest
'''
KEY = int.from_bytes(os.urandom(8)) # Generate a random 8-byte long key
KEY_SIZE = 8*8
BLOCK_SIZE = 4*8
MODE = 'ECB'
PLAINTEXT = os.urandom(4) # Generate a random 4-byte long block
DICT_PATH = './src/block_cipher/metrics/SIMON_metrics.json'
def encryption_measurement(plaintext, key, key_size, block_size, mode):
perf = measure_software_performance(SimonCipher, key, key_size, block_size, mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
plaintext = int.from_bytes(plaintext, byteorder='big', signed=False)
metrics = [b''] + metrics
perf = list(measure_software_performance(cipher.encrypt, plaintext))
perf[0] = perf[0].to_bytes(block_size//8, byteorder='big', signed=False)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
def decryption_measurement(encryptedtext, key, key_size, block_size, mode):
perf = measure_software_performance(SimonCipher, key, key_size, block_size, mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
encryptedtext = int.from_bytes(encryptedtext, byteorder='big', signed=False)
metrics = [b''] + metrics
perf = list(measure_software_performance(cipher.decrypt, encryptedtext))
perf[0] = perf[0].to_bytes(block_size//8, byteorder='big', signed=False)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
if __name__ == '__main__':
encryption = encryption_measurement(PLAINTEXT, KEY, KEY_SIZE, BLOCK_SIZE, MODE)
decryption = decryption_measurement(encryption[0], KEY, KEY_SIZE, BLOCK_SIZE, MODE)
METRICS = {
# [encryption, decryption]
"integrity": decryption[0] == PLAINTEXT,
"implementation_size": [encryption[1], decryption[1]],
"ram_consumption": [encryption[2], decryption[2]],
"throughput": [encryption[3], decryption[3]],
"execution_time": [encryption[4], decryption[4]],
"memory_usage": [encryption[5], decryption[5]],
"cpu_cycles": [encryption[6], decryption[6]],
}
with open(DICT_PATH, 'w') as file:
json.dump(METRICS, file)
from speck import SpeckCipher
import os
import json
from measurement_functions.functions import measure_software_performance
'''
SPECK :
works with
key : Block :
64 32 (4 Bytes)
72 or 96 48
96 or 128 64
96 or 144 96
128 or 192 or 256 128
for lightweight application we take the lowest
'''
KEY = int.from_bytes(os.urandom(8)) # Generate a random 8-byte long key
KEY_SIZE = 8*8
BLOCK_SIZE = 4*8
MODE = 'ECB'
PLAINTEXT = os.urandom(4) # Generate a random 4-byte long block
DICT_PATH = './src/block_cipher/metrics/SPECK_metrics.json'
def encryption_measurement(plaintext, key, key_size, block_size, mode):
perf = measure_software_performance(SpeckCipher, key, key_size, block_size, mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
plaintext = int.from_bytes(plaintext, byteorder='big', signed=False)
metrics = [b''] + metrics
perf = list(measure_software_performance(cipher.encrypt, plaintext))
perf[0] = perf[0].to_bytes(block_size//8, byteorder='big', signed=False)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
def decryption_measurement(encryptedtext, key, key_size, block_size, mode):
perf = measure_software_performance(SpeckCipher, key, key_size, block_size, mode)
cipher = perf[0]
metrics = [object for object in perf[1:]]
encryptedtext = int.from_bytes(encryptedtext, byteorder='big', signed=False)
metrics = [b''] + metrics
perf = list(measure_software_performance(cipher.decrypt, encryptedtext))
perf[0] = perf[0].to_bytes(block_size//8, byteorder='big', signed=False)
metrics = [metrics[i] + perf[i] for i in range(len(perf))]
return metrics
if __name__ == '__main__':
encryption = encryption_measurement(PLAINTEXT, KEY, KEY_SIZE, BLOCK_SIZE, MODE)
decryption = decryption_measurement(encryption[0], KEY, KEY_SIZE, BLOCK_SIZE, MODE)
METRICS = {
# [encryption, decryption]
"integrity": decryption[0] == PLAINTEXT,
"implementation_size": [encryption[1], decryption[1]],
"ram_consumption": [encryption[2], decryption[2]],
"throughput": [encryption[3], decryption[3]],
"execution_time": [encryption[4], decryption[4]],
"memory_usage": [encryption[5], decryption[5]],
"cpu_cycles": [encryption[6], decryption[6]],
}
with open(DICT_PATH, 'w') as file:
json.dump(METRICS, file)
import sys
import time
import timeit
import tracemalloc
def measure_software_performance(func, *args, **kwargs):
"""
Measures the performance metrics of a function.
Parameters:
func (function): The function to be measured.
*args: Variable-length argument list for the function.
**kwargs: Arbitrary keyword arguments for the function.
Returns:
tuple: A tuple containing the result of the function and the performance metrics:
(result, implementation_size, ram_consumption, throughput, execution_time, memory_usage, cpu_cycles)
"""
# Measure implementation size
implementation_size = sys.getsizeof(func)
# Start tracemalloc to measure memory usage
tracemalloc.start()
# Measure time and CPU cycles
num_cycles = 100000
start_cycles = time.perf_counter()
execution_time = timeit.timeit(lambda: func(*args, **kwargs), number=num_cycles)
result = func(*args, **kwargs)
end_cycles = time.perf_counter()
cpu_cycles = end_cycles - start_cycles
# Stop tracemalloc and get memory usage statistics
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
# Calculate throughput (byte/cycle)
throughput = implementation_size / cpu_cycles
# Calculate RAM consumption
ram_consumption = peak - current
return (
result,
implementation_size,
ram_consumption,
throughput,
execution_time,
current,
cpu_cycles,
)
\ No newline at end of file
{"integrity": true, "implementation_size": [216, 216], "ram_consumption": [21562, 52523], "throughput": [119.07806804348952, 118.71078931084953], "execution_time": [4.758196124996175, 4.773563184004161], "memory_usage": [32186, 833], "cpu_cycles": [4.7597706240048865, 4.775073979981244]}
\ No newline at end of file
{"integrity": true, "implementation_size": [1752, 1752], "ram_consumption": [51220, 51764], "throughput": [9.11745907618993, 9.173547093840302], "execution_time": [265.238612236004, 262.9877221630013], "memory_usage": [216051, 1656], "cpu_cycles": [265.2456477149972, 262.9915106590197]}
\ No newline at end of file
{"integrity": true, "implementation_size": [1752, 1752], "ram_consumption": [51544, 52088], "throughput": [51.64470404690014, 54.60125773546804], "execution_time": [61.079046960992855, 62.4007616880117], "memory_usage": [215727, 1332], "cpu_cycles": [61.08791659898998, 62.40270626099664]}
\ No newline at end of file
import Crypto.Cipher.AES as AES
import function.padding.Padding as pad
CHUNK_SIZE = 16 * 1024
PADDING_MODE = 'zero'
PADDING = {
'zero': pad.zero_padding,
'pkcs7': pad.pkcs7_padding
}
UNPADDING = {
'zero': pad.zero_unpadding,
'pkcs7': pad.pkcs7_unpadding
}
def encryption_from_bin_data(key, data, mode=AES.MODE_ECB, padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Encrypts binary data using AES encryption.
Parameters:
- key (bytes): The encryption key. It must be 16 (AES-128), 24 (AES-192), or 32 (AES-256) bytes.
- data (bytes): Binary data to be encrypted.
- mode (int): Encryption mode (default: AES.MODE_ECB).
- padding (str): Padding mode (default: 'pkcs7').
- chunk_size (int): Chunk size in bytes for processing large files (default: 16 * 1024).
Returns:
- encrypted_data (bytes): Binary data of the encrypted file.
"""
cipher = AES.new(key=key, mode=mode)
block_size = cipher.block_size
padding_indicator = (len(data)+1) % block_size # =0 if don't need padding, >0 otherwise
padding_size = block_size - ((len(data)+1) % block_size)
data = bytes([padding_size]) + data
# If needed pad the data
if padding_indicator > 0:
data = PADDING[padding](data, block_size)
encrypted_data = b""
# Encrypt the data in chunks
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
# Encrypt the chunk and append to the encrypted data
ciphertext = cipher.encrypt(chunk)
encrypted_data += ciphertext
return encrypted_data
def decryption_from_bin_data(key, encrypted_data, mode=AES.MODE_ECB, padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Decrypts binary data using AES decryption.
Parameters:
- key (bytes): The decryption key. It must be 16 (AES-128), 24 (AES-192), or 32 (AES-256) bytes.
- encrypted_data (bytes): Binary data to be decrypted.
- mode (int): Encryption mode (default: AES.MODE_ECB).
- padding (str): Padding mode (default: 'pkcs7').
- chunk_size (int): Chunk size in bytes for processing large files (default: 16 * 1024).
Returns:
- decrypted_data (bytes): Binary data of the decrypted file.
"""
cipher = AES.new(key=key, mode=mode)
padding_indicator = None
decrypted_data = b""
# Decrypt the data in chunks
for i in range(0, len(encrypted_data), chunk_size):
chunk = encrypted_data[i:i + chunk_size]
# Decrypt the chunk and append to the decrypted data
decrypted_text = cipher.decrypt(chunk)
decrypted_data += decrypted_text
# Store the padding indicator from the first chunk
if padding_indicator is None :
padding_indicator = decrypted_data[0]
# Remove padding
decrypted_data = UNPADDING[padding](decrypted_data, padding_indicator)
return decrypted_data[1:]
'''
import os
# Generate a random key with 32-byte size
key = os.urandom(32)
# Example data to be encrypted
data = b'This is some example data to be encrypted'*1
# Encrypt the data
encrypted_data = encryption_from_bin_data(key, data)
# Decrypt the data
decrypted_data = decryption_from_bin_data(key, encrypted_data)
# Check if the decryption was successful
#print(data)
#print(decrypted_data)
print(data == decrypted_data)
'''
from Crypto.Cipher.ChaCha20 import new
CHUNK_SIZE = 16 * 1024
def encryption_from_bin_data(key, data, nonce_size = 12, chunk_size=CHUNK_SIZE):
'''
Encrypts binary data using ChaCha20 encryption.
Parameters:
- key (bytes): The secret key is 256 bits long, 32 bytes to which we have added the nonce.
The last byte indicate the size of the nonce
For ChaCha20, it must be 8 or 12 bytes long.
For XChaCha20, it must be 24 bytes long.
If not provided, 8 bytes will be randomly generated.
- data (bytes): Binary data to be encrypted.
Returns:
- encrypted_data (bytes): Binary data of the encrypted file.
'''
nonce_size = key[-1]
key = key[:-1]
key, nonce = key[:-nonce_size], key[-nonce_size:]
cipher = new(key=key, nonce=nonce)
encrypted_data = b""
for i in range(0, len(data), chunk_size):
chunk = data[i:i+chunk_size]
# Encrypt the chunk and append to the encrypted data
ciphertext = cipher.encrypt(chunk)
encrypted_data += ciphertext
return encrypted_data
def decryption_from_bin_data(key, encrypted_data, nonce_size = 12, chunk_size=CHUNK_SIZE):
'''
Decrypts binary data using ChaCha20 decryption.
Parameters:
- key (bytes): The decryption key. It must be 32 bytes long.
- encrypted_data (bytes): Binary data to be decrypted.
Returns:
- decrypted_data (bytes): Binary data of the decrypted file.
'''
nonce_size = key[-1]
key = key[:-1]
key, nonce = key[:-nonce_size], key[-nonce_size:]
cipher = new(key=key, nonce=nonce)
decrypted_data = b""
# Decrypt the data in chunks
for i in range(0, len(encrypted_data), chunk_size):
chunk = encrypted_data[i:i+chunk_size]
# Decrypt the chunk and append to the decrypted data
decrypted_text = cipher.decrypt(chunk)
decrypted_data += decrypted_text
return decrypted_data
'''
import os
# Generate a random key with 32-byte size with a nonce of 12
key = os.urandom(32)
nonce = os.urandom(12)
key += nonce
key += int.to_bytes(12)
# Example data to be encrypted
data = b'This is some example data to be encrypted'*10049
# Encrypt the data
encrypted_data = encryption_from_bin_data(key, data)
# Decrypt the data
decrypted_data = decryption_from_bin_data(key, encrypted_data)
# Print the results
#print("Original data:", data)
#print("Decrypted data:", decrypted_data)
print(data == decrypted_data)
'''
\ No newline at end of file
from simon import SimonCipher
import function.padding.Padding as pad
CHUNK_SIZE = 16 * 1024
PADDING_MODE = "pkcs7"
PADDING = {
'zero': pad.zero_padding,
'pkcs7': pad.pkcs7_padding
}
UNPADDING = {
'zero': pad.zero_unpadding,
'pkcs7': pad.pkcs7_unpadding
}
def encryption_from_bin_data(key, data, mode='ECB', padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Encrypts binary data using the Simon cipher with PKCS#7 padding.
Parameters:
- key (bytes): The encryption key in binary format.
- mode (str): The mode of operation for the cipher. Default: 'ECB'
- padding (str): Padding mode. Default: 'pkcs7'
- chunk_size (int): Chunk size in bytes for processing large files. Default: 16 * 1024
Returns:
- encrypted_data (bytes): Encrypted binary data.
"""
key_size = len(key) * 8
key = int.from_bytes(key, byteorder='big', signed=False)
cipher = SimonCipher(key, key_size=key_size, mode=mode)
block_size = cipher.block_size // 8
padding_indicator = (len(data)+1) % block_size # =0 if don't need padding, >0 otherwise
padding_size = block_size - ((len(data)+1) % block_size)
data = bytes([padding_size]) + data
# If needed pad the data
if padding_indicator > 0:
data = PADDING[padding](data, block_size)
if chunk_size > block_size :
chunk_size = block_size
encrypted_data = b""
# Encrypt the data in chunks
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
chunk = int.from_bytes(chunk, byteorder='big', signed=False)
# Encrypt the block and append to the encrypted data
ciphertext = cipher.encrypt(chunk)
ciphertext = ciphertext.to_bytes(block_size, byteorder='big', signed=False)
encrypted_data += ciphertext
return encrypted_data
def decryption_from_bin_data(key, data, mode='ECB', padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Decrypts binary data encrypted using the Speck cipher with PKCS#7 padding.
Parameters:
- key (bytes): The decryption key in binary format.
- mode (str): The mode of operation for the cipher. Default: 'ECB'
- padding (str): Padding mode. Default: 'pkcs7'
- chunk_size (int): Chunk size in bytes for processing large files. Default: 16 * 1024
Returns:
- decrypted_data (bytes): Decrypted binary data.
"""
key_size = len(key) * 8
key = int.from_bytes(key, byteorder='big', signed=False)
cipher = SimonCipher(key, key_size=key_size, mode=mode)
block_size = cipher.block_size // 8
padding_indicator = None
if chunk_size > block_size :
chunk_size = block_size
decrypted_data = b""
# Decrypt the data in chunks
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
chunk = int.from_bytes(chunk, byteorder='big', signed=False)
# Decrypt the block and append to the decrypted data
chunk = cipher.decrypt(chunk)
chunk = chunk.to_bytes(block_size, byteorder='big', signed=False)
decrypted_data += chunk
# Store the padding indicator from the first chunk
if padding_indicator is None and len(decrypted_data) > 0:
padding_indicator = decrypted_data[0]
# Remove padding
decrypted_data = UNPADDING[padding](decrypted_data, padding_indicator)
return decrypted_data[1:]
'''
import os
# Generate a random key with 32-byte size
key = os.urandom(32)
# Example data to be encrypted
data = b'This is some example data to be encrypted'*1
# Encrypt the data
encrypted_data = encryption_from_bin_data(key, data)
# Decrypt the data
decrypted_data = decryption_from_bin_data(key, encrypted_data)
# Print the results
#print("Original data:", data)
#print("Decrypted data:", decrypted_data)
print(data == decrypted_data)
'''
\ No newline at end of file
from speck import SpeckCipher
import function.padding.Padding as pad
CHUNK_SIZE = 16 * 1024
PADDING_MODE = "pkcs7"
PADDING = {
'zero': pad.zero_padding,
'pkcs7': pad.pkcs7_padding
}
UNPADDING = {
'zero': pad.zero_unpadding,
'pkcs7': pad.pkcs7_unpadding
}
def encryption_from_bin_data(key, data, mode='ECB', padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Encrypts binary data using the Speck cipher with PKCS#7 padding.
Parameters:
- key (bytes): The encryption key in binary format.
- mode (str): The mode of operation for the cipher. Default: 'ECB'
- padding (str): Padding mode. Default: 'pkcs7'
- chunk_size (int): Chunk size in bytes for processing large files. Default: 16 * 1024
Returns:
- encrypted_data (bytes): Encrypted binary data.
"""
key_size = len(key) * 8
key = int.from_bytes(key, byteorder='big', signed=False)
cipher = SpeckCipher(key, key_size=key_size, mode=mode)
block_size = cipher.block_size // 8
padding_indicator = (len(data)+1) % block_size # =0 if don't need padding, >0 otherwise
padding_size = block_size - ((len(data)+1) % block_size)
data = bytes([padding_size]) + data
# If needed pad the data
if padding_indicator > 0:
data = PADDING[padding](data, block_size)
if chunk_size > block_size :
chunk_size = block_size
encrypted_data = b""
# Encrypt the data in chunks
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
chunk = int.from_bytes(chunk, byteorder='big', signed=False)
# Encrypt the block and append to the encrypted data
ciphertext = cipher.encrypt(chunk)
ciphertext = ciphertext.to_bytes(block_size, byteorder='big', signed=False)
encrypted_data += ciphertext
return encrypted_data
def decryption_from_bin_data(key, data, mode='ECB', padding=PADDING_MODE, chunk_size=CHUNK_SIZE):
"""
Decrypts binary data encrypted using the Speck cipher with PKCS#7 padding.
Parameters:
- key (bytes): The decryption key in binary format.
- mode (str): The mode of operation for the cipher. Default: 'ECB'
- padding (str): Padding mode. Default: 'pkcs7'
- chunk_size (int): Chunk size in bytes for processing large files. Default: 16 * 1024
Returns:
- decrypted_data (bytes): Decrypted binary data.
"""
key_size = len(key) * 8
key = int.from_bytes(key, byteorder='big', signed=False)
cipher = SpeckCipher(key, key_size=key_size, mode=mode)
block_size = cipher.block_size // 8
padding_indicator = None
if chunk_size > block_size :
chunk_size = block_size
decrypted_data = b""
# Decrypt the data in chunks
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
chunk = int.from_bytes(chunk, byteorder='big', signed=False)
# Decrypt the block and append to the decrypted data
chunk = cipher.decrypt(chunk)
chunk = chunk.to_bytes(block_size, byteorder='big', signed=False)
decrypted_data += chunk
# Store the padding indicator from the first chunk
if padding_indicator is None and len(decrypted_data) > 0:
padding_indicator = decrypted_data[0]
# Remove padding
decrypted_data = UNPADDING[padding](decrypted_data, padding_indicator)
return decrypted_data[1:]
'''
import os
# Generate a random key with 32-byte size
key = os.urandom(32)
# Example data to be encrypted
data = b'This is some example data to be encrypted'*1
# Encrypt the data
encrypted_data = encryption_from_bin_data(key, data)
# Decrypt the data
decrypted_data = decryption_from_bin_data(key, encrypted_data)
# Print the results
#print("Original data:", data)
#print("Decrypted data:", decrypted_data)
print(data == decrypted_data)
'''
\ No newline at end of file
def zero_padding(data, block_size):
"""
Applies zero padding to the given data to make its length a multiple of the block size.
Parameters:
- data (bytes): The data to be padded.
- block_size (int): The block size in bytes.
Returns:
- Padded data (bytes).
"""
padding_size = block_size - (len(data) % block_size)
padding = b'\x00' * padding_size
return data + padding
def zero_unpadding(data, padding_indicator):
"""
Removes zero padding from the given data.
Parameters:
- data (bytes): The padded data.
Returns:
- Unpadded data (bytes).
"""
if padding_indicator > 0 :
return data[:-padding_indicator] # Trim the data up to the last non-zero byte
return data # If the data doesn't contain any padding, return it as is
def pkcs7_padding(data, block_size):
"""
Applies PKCS7 padding to the given data to make its length a multiple of the block size.
Parameters:
- data (bytes): The data to be padded.
- block_size (int): The block size in bytes.
Returns:
- Padded data (bytes).
"""
padding_size = block_size - (len(data) % block_size)
padding = bytes([padding_size] * padding_size)
return data + padding
def pkcs7_unpadding(data, padding_indicator):
"""
Removes PKCS7 padding from the given data.
Parameters:
- data (bytes): The padded data.
- padding_indicator (int): The padding indicator value.
Returns:
- Unpadded data (bytes).
"""
if padding_indicator > 0 :
padding_size = data[-1]
if padding_size == padding_indicator:
return data[:-padding_size]
else:
raise ValueError("Invalid padding")
return data
from function import Aes, Simon, Speck, Chacha20
import key_generation
from handle_bin import convert_to_bin_file, compare_binary_data
from handle_dict import average_dictionary, save_dictionary
import time
import sys
CIPHERS = {
"AES" : Aes,
"ChaCha20" : Chacha20,
#"Simon" : Simon,
#"Speck" : Speck
}
TEST = {
"jpg" : './src/test_plaintext/test.jpg',
"txt" : './src/test_plaintext/test.txt',
"pdf" : './src/test_plaintext/test.pdf'
}
METRICS = {
"integrity": False,
"space_complexity": 0,
"encryption_time_complexity": 0,
"decryption_time_complexity":0,
"encryption_memory_usage":0,
"decryption_memory_usage":0
}
KEY_SIZES = [16, 24, 32]
AVERAGING_PARAMETER = 1000
def metrics_by_key_size(plaintext_bin_data, loop=AVERAGING_PARAMETER):
METRICS_BY_KEY_SIZE = {
f'{key_size}': {
cipher: dict(METRICS) for cipher in CIPHERS.keys()
} for key_size in KEY_SIZES
}
LIST_DICTIONNARY = []
for iteration in range(loop): # To average a bit the value
LIST_DICTIONNARY.append(METRICS_BY_KEY_SIZE)
for key_size in KEY_SIZES:
for cipher in CIPHERS.keys():
if not (cipher == "ChaCha20" and key_size in [16, 24]): # To indicate that ChaCha20 only works with key_size of 32
key = key_generation.load_key(cipher=cipher, key_size=key_size)
T = time.time()
encrypted_bin_data = CIPHERS[cipher].encryption_from_bin_data(key, plaintext_bin_data)
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["encryption_time_complexity"] = time.time() - T # Time in seconds
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["space_complexity"] = len(encrypted_bin_data) / 1000 # Length in kB
T = time.time()
decrypted_bin_data = CIPHERS[cipher].decryption_from_bin_data(key, encrypted_bin_data)
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["decryption_time_complexity"] = time.time() - T # Time in seconds
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["integrity"] = compare_binary_data(plaintext_bin_data,
decrypted_bin_data) # Check if decrypted correctly
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["encryption_memory_usage"] = get_memory_usage(CIPHERS[cipher].encryption_from_bin_data)
METRICS_BY_KEY_SIZE[f'{key_size}'][cipher]["decryption_memory_usage"] = get_memory_usage(CIPHERS[cipher].decryption_from_bin_data)
return average_dictionary(LIST_DICTIONNARY, loop)
def get_memory_usage(obj):
size = sys.getsizeof(obj)
if hasattr(obj, '__iter__'):
if hasattr(obj, 'items'):
for key, value in obj.items():
size += get_memory_usage(key)
size += get_memory_usage(value)
elif not isinstance(obj, str):
for item in obj:
size += get_memory_usage(item)
return size
# Data to be processed
plaintext_path = TEST["txt"]
plaintext_bin_data = convert_to_bin_file(plaintext_path)
# creation of the metrics dictionnary (averaged) and save in .json file
save_dictionary(metrics_by_key_size(plaintext_bin_data), "./src/metrics_by_key_size_dictionary.json")
def convert_to_bin_file(input_file_path):
'''
Converts the contents of a file to binary data.
Parameters:
- input_file_path (str): The path of the input file.
Returns:
- file_contents (bytes): The binary data read from the input file.
'''
with open(input_file_path, 'rb') as input_file:
file_contents = input_file.read()
return file_contents
def write_bin_file(bin_data, output_file_path):
'''
Writes binary data to an output file.
Parameters:
- bin_data (bytes): The binary data to be written.
- output_file_path (str): The path of the output file.
Returns:
None
'''
with open(output_file_path, 'wb') as output_file:
output_file.write(bin_data)
def compare_binary_data(data1, data2):
'''
Compares two binary data to check if they are equal.
Parameters:
- data1 (bytes): The first binary data to compare.
- data2 (bytes): The second binary data to compare.
Returns:
- result (bool): True if the binary data is equal, False otherwise.
'''
return data1 == data2
import json
# Serialization of dictionary
def save_dictionary(my_dictionary, dictionary_path):
with open(dictionary_path, 'w') as file:
json.dump(my_dictionary, file)
# load dictionnary
def load_dictionary(dictionary_path):
with open(dictionary_path, 'r') as file:
my_dictionary = json.load(file)
return my_dictionary
# Basic manipulation functions on dictionnary
def add_dictionary_values(dict1, dict2):
"""
Adds the values inside two dictionaries.
Parameters:
dict1 (dict): The first dictionary.
dict2 (dict): The second dictionary.
Returns:
dict: A new dictionary with the summed values.
"""
result_dict = {}
all_keys = set(dict1.keys()) | set(dict2.keys())
for key in all_keys:
if key in dict1 and key in dict2:
if isinstance(dict1[key], dict) and isinstance(dict2[key], dict):
result_dict[key] = add_dictionary_values(dict1[key], dict2[key])
else:
result_dict[key] = dict1[key] + dict2[key]
elif key in dict1:
result_dict[key] = dict1[key]
else:
result_dict[key] = dict2[key]
return result_dict
def divise_dictionary_values(dictionary, number):
"""
Divides the values in a dictionary by a specified number.
Parameters:
dictionary (dict): The dictionary containing values to be divided.
number (float): The number to divide the values by.
Returns:
dict: A new dictionary with the divided values.
"""
result_dict = {}
for key in dictionary.keys():
if isinstance(dictionary[key], dict):
result_dict[key] = divise_dictionary_values(dictionary[key], number)
else:
result_dict[key] = dictionary[key] / number
return result_dict
def average_dictionary(dictionnaries, loop):
"""
Computes the average of a list of dictionaries.
Parameters:
dictionnaries (list): A list of dictionaries.
loop (int): The number of dictionaries to consider for averaging.
Returns:
dict: A new dictionary with the average values.
"""
result_dict = {}
for i in range(loop):
result_dict = add_dictionary_values(result_dict, dictionnaries[i])
return divise_dictionary_values(result_dict, loop)
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