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

auj

parent 03f27bcc
Branches master
No related tags found
No related merge requests found
...@@ -12,54 +12,31 @@ This has been written in Python3 in the context of Viken KARABOGHOSSIAN's projec ...@@ -12,54 +12,31 @@ This has been written in Python3 in the context of Viken KARABOGHOSSIAN's projec
The project contains the following files: The project contains the following files:
* `requirements.txt`: the list of all required Python3 packages. * `requirements.txt`: the list of all required Python3 packages.
* `instruction.md`: this file, which contains the instructions to better understand and use the scripts. * `instruction.md`: this file, which contains the instructions to better understand and use the scripts.
* ```interative_plots.py``` : command line tool to interactively decide which algorithms, operations and metrics to visualize. * ```main.py```: command line tool to interactively do the comparative study.
* ```automated_plots.py```: an automated script to generate and save automatically the required plots.
* ```scenarios.py```: command line tool to interactively create scenario, where a scenario is defined by two end users, a bandwidth and a latency. An end user is defined by its : memory/RAM capacity, plaintext size (size of the transmitted package), and a processor frequency.
* ```main.py```: command line tool to study a scenario and save the result in csv file
* `/plots`: a folder in which the plots will be saved. * `/plots`: a folder in which the plots will be saved.
* `/ciphers_src`: a folder that contains the python implementation of the ciphers we study. * `/src`: a folder that contains both the python implementation of the ciphers we study and utils fonction for the orrect execution of the main script.
* `/doc`: a folder that contains the documentation generated by sphinx. * `/doc`: a folder that contains the documentation generated by sphinx.
* `/Litterature`: a folder that contains litterature for the internship.
## Usage (interactive ploting) ## Usage
1. Open the root folder of your project in a terminal. This folder should contain: 1. Open the root folder of your project in a terminal. This folder should contain:
* The ```interactive_plots.py``` script * The ```main.py``` script
* The csv file containing the results you want to plot (delimiter = ',')
* This file (`instructions.md`) * This file (`instructions.md`)
2. You will be prompted questions. Answer them and click `enter`. 2. Execute the ```main.py``` script by typing ```python3 main.py```. You will be prompted questions. Answer them and click `enter`.
3. If you decided to save the plot, check them in `/plots`
## Usage (automated ploting)
1. Open the root folder of your project in a terminal. This folder should contain:
* The ```automated_plots.py``` script
* The csv file containing the results you want to plot (delimiter = ',')
* This file (`instructions.md`)
2. Before executing the script, check the following parameters:
* filepath
* metrics_choices
* operation_choices
* algo_choices
3. Then type: ```python3 automated_plots.py```
4. Check your results in `/results`
## Usage (main)
## Content ## Content
The tool was designed to take as input a csv file containing information about the performance evaluation of encryption schemes. As the project studied block cipher and stream cipher, the tool can handle the two following lists of headers: The tool was designed to make a comparative study between a set of symmetric encryption cipher.
* Block cipher: It is based on the comparisons of the costs of each cipher in a given scenario (a scebario is a set of two node), where ciher's cost is a weighted summation of the cipher's performances.
|algo|key_length|block_length|operation|integrity|implementation_size|ram_consumption|throughput|execution_time|memory_usage|encrypted_file_size|
* Stream cipher:
|algo|key_length|nonce_length|operation|integrity|implementation_size|ram_consumption|throughput|execution_time|memory_usage|encrypted_file_size|
------------ ------------
## Improvement and future work: ## Improvement and future work:
* Render the program more flexible.
* Render the program more flexible. E.g., take csv for which the headers are not known. * Improve the measurments of ciphers' perfomance.
* Add autocompletion for paremeter selection (rich.prompt Completion)
## More to come: ## More to come:
...
# PROGRAM STARTS # PROGRAM STARTS
\ No newline at end of file
...@@ -10,8 +10,6 @@ from rich.prompt import Prompt ...@@ -10,8 +10,6 @@ from rich.prompt import Prompt
from rich.console import Console from rich.console import Console
from rich.markdown import Markdown from rich.markdown import Markdown
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import datetime
class Transmission: class Transmission:
...@@ -29,21 +27,25 @@ class Transmission: ...@@ -29,21 +27,25 @@ class Transmission:
self.plaintext_size = len(self.plaintext) self.plaintext_size = len(self.plaintext)
###### Set up the scenario ###### Set up the scenario
choice = Prompt.ask("\nChoose between the following scenarios:\n1: end_to_end\n2: ground_to_satellite\n3: satellite_to_satellite\n", choice = Prompt.ask("\nChoose between the following scenarios:\n0: default \n1: end_to_end\n2: ground_to_satellite\n3: satellite_to_satellite\n",
choices=['1', '2', '3'], default='1') choices=['0', '1', '2', '3'], default='0')
if choice == '0':
self.scene = 'default'
default = node(1, 1, 1/self.plaintext_size, self.plaintext)
self.scenarii = scenario(default, default, 1, 1, 1, self.plaintext)
if choice == '1': if choice == '1':
self.scene = 'end_to_end' self.scene = 'end_to_end'
end_user = node(16e9, 8e9, 3.5e9, self.plaintext) end_user = node(16e9, 8e9, 3.5e9, self.plaintext)
self.scenarii = scenario(end_user, end_user, 13e9, 1600e3, self.plaintext) self.scenarii = scenario(end_user, end_user, 13e9, 1600e3, 3 * 10 ** 8, self.plaintext)
elif choice == '2': elif choice == '2':
self.scene = 'ground_to_satellite' self.scene = 'ground_to_satellite'
satellite = node(2e9, 512e6, 100e6, self.plaintext) satellite = node(2e9, 512e6, 100e6, self.plaintext)
ground_station = node(1e12, 32e9, 4e9, self.plaintext) ground_station = node(1e12, 32e9, 4e9, self.plaintext)
self.scenarii = scenario(ground_station, satellite, 13e9, 500e3, self.plaintext) self.scenarii = scenario(ground_station, satellite, 13e9, 500e3, 3 * 10 ** 8, self.plaintext)
elif choice == '3': elif choice == '3':
self.scene = 'satellite_to_satellite' self.scene = 'satellite_to_satellite'
satellite = node(2e9, 512e6, 100e6, self.plaintext) satellite = node(2e9, 512e6, 100e6, self.plaintext)
self.scenarii = scenario(satellite, satellite, 281.7e12, 7371e3, self.plaintext) self.scenarii = scenario(satellite, satellite, 281.7e12, 7371e3, 3 * 10 ** 8, self.plaintext)
def run_analysis(self): def run_analysis(self):
...@@ -57,45 +59,37 @@ class Transmission: ...@@ -57,45 +59,37 @@ class Transmission:
for cipher in self.scenarii.costs[mode].keys(): for cipher in self.scenarii.costs[mode].keys():
for combination in self.scenarii.costs[mode][cipher].keys(): for combination in self.scenarii.costs[mode][cipher].keys():
plt.barh(combination, self.scenarii.costs[mode][cipher][combination]) plt.barh(combination, self.scenarii.costs[mode][cipher][combination])
plt.ylabel("Algorithm-key_size/nonce_block_size")
plt.xlabel("Cost")
plt.yticks(fontsize=9)
plt.title(f"Comparative anaysis for a {self.plaintext_size}byte long message")
plt.tight_layout() # Ensures labels don't overlap
plt.show() plt.show()
# Automatic saving
if Prompt.ask("Do you want to save the plot?", choices=['y', 'n'], default='n') == "y":
date = datetime.datetime.now()
for mode in self.scenarii.costs.keys():
for cipher in self.scenarii.costs[mode].keys():
for combination in self.scenarii.costs[mode][cipher].keys():
plt.barh(combination, self.scenarii.costs[mode][cipher][combination])
plt.savefig('plots/' + 'cost_' + self.scene + '-' + str(date.year) + str(date.month) +
str(date.day) + '-' + str(date.hour) + str(date.minute) + '.png')
# Clear after saving
plt.clf()
plt.cla()
# Keep only the best combinations # Keep only the best combinations
self.scenarii.choose_the_better() self.scenarii.choose_the_better()
plt.figure('Now only the best combination for each cipher in a ' + self.scene + ' scenario') plt.figure('Now only the best combination for each cipher in a ' + self.scene + ' scenario')
for mode in self.scenarii.costs.keys():
for cipher in self.scenarii.costs[mode].keys():
for combination in self.scenarii.costs[mode][cipher].keys():
plt.barh(combination, self.scenarii.costs[mode][cipher][combination])
plt.show()
# Automatic saving
if Prompt.ask("Do you want to save the plot?", choices=['y', 'n'], default='n') == "y":
date = datetime.datetime.now()
for mode in self.scenarii.costs.keys(): for mode in self.scenarii.costs.keys():
for cipher in self.scenarii.costs[mode].keys(): for cipher in self.scenarii.costs[mode].keys():
for combination in self.scenarii.costs[mode][cipher].keys(): combinations = list(self.scenarii.costs[mode][cipher].keys())
plt.barh(combination, self.scenarii.costs[mode][cipher][combination]) costs = list(self.scenarii.costs[mode][cipher].values())
plt.savefig('plots/' + 'cost_' + self.scene + '-' + str(date.year) + str(date.month) +
str(date.day) + '-' + str(date.hour) + str(date.minute) + '.png') bars = plt.barh(combinations, costs)
# Clear after saving # Adding text labels for each bar
plt.clf() for bar, cost in zip(bars, costs):
plt.cla() label = f'{cost:.6f}' if cost > 0.000001 else f'{cost:.2e}'
plt.text(bar.get_width(), bar.get_y() + bar.get_height()/2, label,
va='center', fontsize=8, color='black', fontweight='bold')
plt.ylabel("Algorithm-key_size/nonce_block_size")
plt.xlabel("Cost")
plt.yticks(fontsize=9)
plt.title(f"Comparative analysis for a {self.plaintext_size} byte long message")
plt.tight_layout() # Ensures labels don't overlap
plt.show()
......
...@@ -14,7 +14,8 @@ from src.ciphers_src.util import measure_software_performance ...@@ -14,7 +14,8 @@ from src.ciphers_src.util import measure_software_performance
MODE = AES.MODE_CTR MODE = AES.MODE_CTR
LENGTHS = [[16,nonce] for nonce in range(16)] + [[24 , nonce] for nonce in range(16)] + [[32,nonce] for nonce in range(16)] #LENGTHS = [[16,nonce] for nonce in range(16)] + [[24 , nonce] for nonce in range(16)] + [[32,nonce] for nonce in range(16)]
LENGTHS = [[16,nonce] for nonce in [8,12]] + [[24 , nonce] for nonce in [8,12]] + [[32,nonce] for nonce in [8,12]]
KEY_SIZES = [length[0] for length in LENGTHS] KEY_SIZES = [length[0] for length in LENGTHS]
NONCE_SIZES = [length[1] for length in LENGTHS] NONCE_SIZES = [length[1] for length in LENGTHS]
KEYS = [os.urandom(key_size) for key_size in KEY_SIZES] # Generate a random N-byte long key KEYS = [os.urandom(key_size) for key_size in KEY_SIZES] # Generate a random N-byte long key
......
...@@ -28,14 +28,12 @@ CIPHER = { ...@@ -28,14 +28,12 @@ CIPHER = {
} }
} }
SIGNAL_CELERITY = 3 * 10 ** 8 # OEM signal celerity
class node : class node :
def __init__(self,storage_capacity, RAM_capacity, processor_frequency, plaintext) -> None: def __init__(self,storage_capacity, RAM_capacity, processor_frequency, plaintext) -> None:
self.storage_capacity = storage_capacity self.storage_capacity = storage_capacity
self.RAM_capacity = RAM_capacity self.RAM_capacity = RAM_capacity
self.processor_frequency = processor_frequency self.processor_frequency = processor_frequency
stream = self._cipher_analysis('stream', plaintext) stream = self._cipher_analysis('stream', plaintext)
block = self._cipher_analysis('block', plaintext) block = self._cipher_analysis('block', plaintext)
integrity = (stream[1]==block[1]) == True integrity = (stream[1]==block[1]) == True
...@@ -44,6 +42,7 @@ class node : ...@@ -44,6 +42,7 @@ class node :
"stream" : stream[0], "stream" : stream[0],
"block" : block[0] "block" : block[0]
} }
self.normalization()
def _cipher_analysis(self, mode, plaintext): def _cipher_analysis(self, mode, plaintext):
...@@ -140,12 +139,12 @@ class node : ...@@ -140,12 +139,12 @@ class node :
for mode in ['stream','block']: for mode in ['stream','block']:
min_max_metrics = { min_max_metrics = {
'encrytion' : { 'encryption' : {
"implementation_size": [], "implementation_size": [],
"ram_consumption": [], "ram_consumption": [],
"throughput": [], "throughput": [],
"execution_time": [], "execution_time": [],
"memory_usage": [], #"memory_usage": [],
"encrypted_file_size": [], "encrypted_file_size": [],
#"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]], #"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]],
}, },
...@@ -154,7 +153,7 @@ class node : ...@@ -154,7 +153,7 @@ class node :
"ram_consumption": [], "ram_consumption": [],
"throughput": [], "throughput": [],
"execution_time": [], "execution_time": [],
"memory_usage": [], #"memory_usage": [],
"encrypted_file_size": [], "encrypted_file_size": [],
#"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]], #"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]],
}, },
...@@ -163,7 +162,7 @@ class node : ...@@ -163,7 +162,7 @@ class node :
"ram_consumption": [], "ram_consumption": [],
"throughput": [], "throughput": [],
"execution_time": [], "execution_time": [],
"memory_usage": [], #"memory_usage": [],
"encrypted_file_size": [], "encrypted_file_size": [],
#"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]], #"cpu_cycles": [encryption[6], decryption[6], encryption[6]+ decryption[6]],
}, },
...@@ -171,32 +170,36 @@ class node : ...@@ -171,32 +170,36 @@ class node :
# add them all in a min_max_metrics dictionnary # add them all in a min_max_metrics dictionnary
for cipher in self.ciphers_data[mode].keys() : for cipher in self.ciphers_data[mode].keys() :
for operation in self.ciphers_data[mode][cipher].keys(): for combinaison in self.ciphers_data[mode][cipher].keys():
for metric in self.ciphers_data[mode][cipher][operation].keys(): for operation in self.ciphers_data[mode][cipher][combinaison].keys():
min_max_metrics[operation][metric].append(self.ciphers_data[mode][cipher][operation][metric]) if operation != "integrity":
for metric in self.ciphers_data[mode][cipher][combinaison][operation].keys():
min_max_metrics[operation][metric].append(self.ciphers_data[mode][cipher][combinaison][operation][metric])
# just keep the max and min value # just keep the max and min value
for operation in min_max_metrics.keys(): for operation in min_max_metrics.keys():
for metric in min_max_metrics[operation].keys(): for metric in min_max_metrics[operation].keys():
max = max(min_max_metrics[operation][metric]) maxim = max(min_max_metrics[operation][metric])
min = min(min_max_metrics[operation][metric]) minim = min(min_max_metrics[operation][metric])
min_max_metrics[operation][metric] = [min, max] min_max_metrics[operation][metric] = [minim, maxim]
# now normalize # now normalize
for cipher in self.ciphers_data[mode].keys() : for cipher in self.ciphers_data[mode].keys() :
for operation in self.ciphers_data[mode][cipher].keys(): for combinaison in self.ciphers_data[mode][cipher].keys():
for metric in self.ciphers_data[mode][cipher][operation].keys(): for operation in self.ciphers_data[mode][cipher][combinaison].keys():
if operation != "integrity":
for metric in self.ciphers_data[mode][cipher][combinaison][operation].keys():
maxim = min_max_metrics[operation][metric][1] maxim = min_max_metrics[operation][metric][1]
minim = min_max_metrics[operation][metric][0] minim = min_max_metrics[operation][metric][0]
if [max, min] == [0,0]: if [maxim, minim] != [0,0]:
pass if maxim == minim :
minim=0
if not (metric == "throughput") : if not (metric == "throughput") :
self.ciphers_data[mode][cipher][operation][metric] -= minim self.ciphers_data[mode][cipher][combinaison][operation][metric] -= minim
else : else :
self.ciphers_data[mode][cipher][operation][metric] = \ self.ciphers_data[mode][cipher][combinaison][operation][metric] = \
maxim - self.ciphers_data[mode][cipher][operation][metric] maxim - self.ciphers_data[mode][cipher][combinaison][operation][metric]
self.ciphers_data[mode][cipher][combinaison][operation][metric] /= (maxim-minim)
self.ciphers_data[mode][cipher][operation][metric] /= (maxim-minim)
...@@ -204,12 +207,12 @@ class node : ...@@ -204,12 +207,12 @@ class node :
class scenario : class scenario :
def __init__(self, node1, node2, bandwidth, distance, plaintext) -> None: def __init__(self, node1, node2, bandwidth, distance, signal_celerity, plaintext) -> None:
self.node1 = node1 self.node1 = node1
self.node2 = node2 self.node2 = node2
self.bandwidth = bandwidth self.bandwidth = bandwidth
self.distance = distance self.distance = distance
self.latency = distance/SIGNAL_CELERITY self.latency = distance/signal_celerity
self.weights = self._weights(plaintext) self.weights = self._weights(plaintext)
self.costs = { self.costs = {
...@@ -218,8 +221,6 @@ class scenario : ...@@ -218,8 +221,6 @@ class scenario :
} }
def _weights(self, message): def _weights(self, message):
weights = {} weights = {}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment