Merge remote-tracking branch 'origin/main'
# Conflicts: # IS/Lab/Lab2/des_vs_aes256.py
This commit is contained in:
commit
4ca2829e4e
13 changed files with 1201 additions and 87 deletions
28
ES/Lab/Lab2/array_reversal.asm
Normal file
28
ES/Lab/Lab2/array_reversal.asm
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
AREA RESET, DATA, READONLY
|
||||||
|
EXPORT __Vectors
|
||||||
|
__Vectors
|
||||||
|
DCD 0x10001000
|
||||||
|
DCD Reset_Handler
|
||||||
|
ALIGN
|
||||||
|
AREA mycode,CODE,READONLY
|
||||||
|
ENTRY
|
||||||
|
EXPORT Reset_Handler
|
||||||
|
|
||||||
|
Reset_Handler
|
||||||
|
MOV R2, #5
|
||||||
|
LDR R0, =SRC
|
||||||
|
LDR R1, =SRC + 36
|
||||||
|
Loop
|
||||||
|
LDR R3, [R0]
|
||||||
|
LDR R4, [R1]
|
||||||
|
STR R3, [R1], #-4
|
||||||
|
STR R4, [R0], #4
|
||||||
|
SUBS R2, #1
|
||||||
|
|
||||||
|
BNE Loop
|
||||||
|
|
||||||
|
STOP
|
||||||
|
B STOP
|
||||||
|
AREA mydate, DATA, READWRITE
|
||||||
|
SRC DCD 0x00000032, 0x12345644, 0x00000005, 0x00000098, 0x000000AB, 0x000000CD, 0x00000055, 0x00000032, 0x000000CA, 0x00000045
|
||||||
|
END
|
34
ES/Lab/Lab3/ADDER.asm
Normal file
34
ES/Lab/Lab3/ADDER.asm
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
AREA RESET, DATA, READONLY
|
||||||
|
EXPORT __Vectors
|
||||||
|
|
||||||
|
__Vectors
|
||||||
|
DCD 0x10001000
|
||||||
|
DCD Reset_Handler
|
||||||
|
ALIGN
|
||||||
|
AREA MYCODE, CODE, READONLY
|
||||||
|
ENTRY
|
||||||
|
EXPORT Reset_Handler
|
||||||
|
|
||||||
|
Reset_Handler
|
||||||
|
LDR R0, =SRC
|
||||||
|
MOV R3, #10
|
||||||
|
|
||||||
|
UP
|
||||||
|
LDR R1, [R0], #4
|
||||||
|
ADDS R2, R1
|
||||||
|
ADC R5, #0
|
||||||
|
SUBS R3, #1
|
||||||
|
BNE UP;
|
||||||
|
|
||||||
|
LDR R4, =Result
|
||||||
|
STR R2, [R4]
|
||||||
|
STR R5, [R4]
|
||||||
|
|
||||||
|
SRC DCD 0x12345678, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, 0x00000008, 0x00000009
|
||||||
|
|
||||||
|
AREA mydata, DATA, READWRITE
|
||||||
|
|
||||||
|
Result
|
||||||
|
DCD 0
|
||||||
|
|
||||||
|
END
|
44
ES/Lab/Lab3/add128bit.asm
Normal file
44
ES/Lab/Lab3/add128bit.asm
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
AREA RESET, DATA, READONLY
|
||||||
|
EXPORT __Vectors
|
||||||
|
|
||||||
|
__Vectors
|
||||||
|
DCD 0x10001000
|
||||||
|
DCD Reset_Handler
|
||||||
|
|
||||||
|
ALIGN
|
||||||
|
|
||||||
|
AREA MYCODE, CODE, READONLY
|
||||||
|
ENTRY
|
||||||
|
|
||||||
|
EXPORT Reset_Handler
|
||||||
|
|
||||||
|
Reset_Handler
|
||||||
|
LDR R1, =N1
|
||||||
|
LDR R2, =N2
|
||||||
|
MOV R3, #4
|
||||||
|
|
||||||
|
UP
|
||||||
|
LDR R4, [R1], #4
|
||||||
|
LDR R5, [R2], #4
|
||||||
|
ADCS R6, R5, R4
|
||||||
|
SUB R3, #1
|
||||||
|
TEQ R3, #0
|
||||||
|
BNE UP;
|
||||||
|
|
||||||
|
LDR R8, =Result
|
||||||
|
STR R2, [R8], #4
|
||||||
|
STR R5, [R8]
|
||||||
|
|
||||||
|
STOP
|
||||||
|
B STOP
|
||||||
|
ALIGN
|
||||||
|
|
||||||
|
N1 DCD 0x10002000, 0x30004000, 0x50006000, 0x70008000
|
||||||
|
N2 DCD 0x10002000, 0x30004000, 0x50006000, 0x70008000
|
||||||
|
|
||||||
|
AREA mydata, DATA, READWRITE
|
||||||
|
|
||||||
|
|
||||||
|
Result DCD 0
|
||||||
|
|
||||||
|
END
|
|
@ -1,33 +1,196 @@
|
||||||
from crypto.Cipher import DES3
|
from Crypto.Cipher import DES, DES3, AES
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
|
import time
|
||||||
|
from bokeh.plotting import figure, show, output_file
|
||||||
|
from bokeh.models import HoverTool, ColumnDataSource
|
||||||
|
from bokeh.layouts import column, row
|
||||||
|
import bokeh.palettes as bp
|
||||||
|
|
||||||
def des_pad(text):
|
def pad_key(key, length):
|
||||||
n = len(text) % 8
|
return key.ljust(length)[:length].encode('utf-8')
|
||||||
return text + (b' ' * n)
|
|
||||||
|
|
||||||
def des_128(ptext, key):
|
def encrypt_with_timing(cipher_func, ptext, key, *args):
|
||||||
cipher=DES.new(key, DES.MODE_ECB)
|
# Use more precise timing for microsecond measurements
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
result = cipher_func(ptext, key, *args)
|
||||||
|
end_time = time.perf_counter()
|
||||||
|
return result, end_time - start_time
|
||||||
|
|
||||||
|
def des_encrypt(ptext, key, mode):
|
||||||
|
key = pad_key(key, 8)
|
||||||
|
cipher = DES.new(key, mode)
|
||||||
|
padded_text = pad(ptext.encode('utf-8'), DES.block_size)
|
||||||
|
return cipher.encrypt(padded_text)
|
||||||
|
|
||||||
def des_192(ptext, key):
|
def des3_encrypt(ptext, key, key_size, mode):
|
||||||
|
if key_size == 128:
|
||||||
|
key = pad_key(key, 16)
|
||||||
|
elif key_size == 192:
|
||||||
|
key = pad_key(key, 24)
|
||||||
|
else: # 256 bit uses 192 bit key (DES3 limitation)
|
||||||
|
key = pad_key(key, 24)
|
||||||
|
|
||||||
def des_256(ptext, key):
|
cipher = DES3.new(key, mode)
|
||||||
|
padded_text = pad(ptext.encode('utf-8'), DES3.block_size)
|
||||||
|
return cipher.encrypt(padded_text)
|
||||||
|
|
||||||
def aes_128(ptext, key):
|
def aes_encrypt(ptext, key, key_size, mode):
|
||||||
def aes_192(ptext, key):
|
if key_size == 128:
|
||||||
def aes_256(ptext, key):
|
key = pad_key(key, 16)
|
||||||
|
elif key_size == 192:
|
||||||
|
key = pad_key(key, 24)
|
||||||
|
else: # 256
|
||||||
|
key = pad_key(key, 32)
|
||||||
|
|
||||||
def bokeh_graph():
|
cipher = AES.new(key, mode)
|
||||||
|
padded_text = pad(ptext.encode('utf-8'), AES.block_size)
|
||||||
|
return cipher.encrypt(padded_text)
|
||||||
|
|
||||||
|
def des_128(ptext, key, mode=DES.MODE_ECB):
|
||||||
|
return des_encrypt(ptext, key, mode)
|
||||||
|
|
||||||
|
def des_192(ptext, key, mode=DES3.MODE_ECB):
|
||||||
|
return des3_encrypt(ptext, key, 192, mode)
|
||||||
|
|
||||||
|
def des_256(ptext, key, mode=DES3.MODE_ECB):
|
||||||
|
return des3_encrypt(ptext, key, 256, mode)
|
||||||
|
|
||||||
|
def aes_128(ptext, key, mode=AES.MODE_ECB):
|
||||||
|
return aes_encrypt(ptext, key, 128, mode)
|
||||||
|
|
||||||
|
def aes_192(ptext, key, mode=AES.MODE_ECB):
|
||||||
|
return aes_encrypt(ptext, key, 192, mode)
|
||||||
|
|
||||||
|
def aes_256(ptext, key, mode=AES.MODE_ECB):
|
||||||
|
return aes_encrypt(ptext, key, 256, mode)
|
||||||
|
|
||||||
|
def bokeh_graph(timing_data):
|
||||||
|
output_file("encryption_performance.html")
|
||||||
|
|
||||||
|
from bokeh.models import LinearColorMapper, ColorBar, BasicTicker, PrintfTickFormatter
|
||||||
|
from bokeh.transform import transform
|
||||||
|
import math
|
||||||
|
|
||||||
|
algorithms = list(timing_data.keys())
|
||||||
|
messages = [f"Msg {i+1}" for i in range(len(next(iter(timing_data.values()))))]
|
||||||
|
|
||||||
|
# Convert all times to microseconds for better visibility
|
||||||
|
def to_microseconds(seconds):
|
||||||
|
return seconds * 1_000_000
|
||||||
|
|
||||||
|
# Chart 2: Performance variability - Box plot style using circles and lines
|
||||||
|
p2 = figure(x_range=algorithms, title="Performance Distribution Across Messages",
|
||||||
|
toolbar_location=None, tools="", width=800, height=400)
|
||||||
|
|
||||||
|
for i, algo_name in enumerate(algorithms):
|
||||||
|
times_us = [to_microseconds(t) for t in timing_data[algo_name]]
|
||||||
|
|
||||||
|
# Calculate statistics
|
||||||
|
mean_time = sum(times_us) / len(times_us)
|
||||||
|
min_time = min(times_us)
|
||||||
|
max_time = max(times_us)
|
||||||
|
|
||||||
|
# Plot range line
|
||||||
|
p2.line([i, i], [min_time, max_time], line_width=2, color=colors[i], alpha=0.6)
|
||||||
|
|
||||||
|
# Plot individual points
|
||||||
|
y_positions = times_us
|
||||||
|
x_positions = [i + (j - 2) * 0.1 for j in range(len(times_us))] # Spread points horizontally
|
||||||
|
p2.circle(x_positions, y_positions, size=8, color=colors[i], alpha=0.8)
|
||||||
|
|
||||||
|
# Plot mean as a diamond
|
||||||
|
p2.diamond([i], [mean_time], size=12, color=colors[i], line_color="black", line_width=1)
|
||||||
|
|
||||||
|
p2.xaxis.major_label_orientation = 45
|
||||||
|
p2.yaxis.axis_label = "Execution Time (microseconds)"
|
||||||
|
p2.xaxis.axis_label = "Encryption Algorithm"
|
||||||
|
p2.xaxis.ticker = BasicTicker()
|
||||||
|
p2.xaxis.formatter = PrintfTickFormatter(format="%s")
|
||||||
|
|
||||||
|
hover2 = HoverTool(tooltips=[("Time (μs)", "@y{0.00}")], mode='vline')
|
||||||
|
p2.add_tools(hover2)
|
||||||
|
|
||||||
|
# Chart 4: Relative performance comparison (normalized to fastest)
|
||||||
|
p4 = figure(x_range=algorithms, title="Relative Performance (Normalized to Fastest Algorithm)",
|
||||||
|
toolbar_location=None, tools="", width=800, height=400)
|
||||||
|
|
||||||
|
# Find the fastest average time
|
||||||
|
fastest_avg = min(avg_times)
|
||||||
|
relative_times = [avg / fastest_avg for avg in avg_times]
|
||||||
|
|
||||||
|
bars4 = p4.vbar(x=algorithms, top=relative_times, width=0.6, color=colors, alpha=0.8)
|
||||||
|
|
||||||
|
# Add reference line at 1.0
|
||||||
|
p4.line([-0.5, len(algorithms)-0.5], [1, 1], line_dash="dashed", line_width=2, color="red", alpha=0.7)
|
||||||
|
|
||||||
|
p4.xaxis.major_label_orientation = 45
|
||||||
|
p4.yaxis.axis_label = "Relative Performance (1.0 = fastest)"
|
||||||
|
p4.xaxis.axis_label = "Encryption Algorithm"
|
||||||
|
|
||||||
|
hover4 = HoverTool(tooltips=[("Algorithm", "@x"), ("Relative Speed", "@top{0.00}x")], renderers=[bars4])
|
||||||
|
p4.add_tools(hover4)
|
||||||
|
|
||||||
|
# Layout all charts
|
||||||
|
layout = column(
|
||||||
|
row(p2),
|
||||||
|
row(p4)
|
||||||
|
)
|
||||||
|
|
||||||
|
show(layout)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print("The AES/DES Encryptor")
|
print("The AES/DES Encryptor with Performance Analysis")
|
||||||
ptext = input("Enter plaintext: ")
|
|
||||||
key = b'input("Enter key: ")'
|
# Get exactly 5 messages from user
|
||||||
print("DES 128 Bit Cyphertext: ", des_128(ptext, key))
|
messages = []
|
||||||
print("DES 192 Bit Cyphertext: ", des_192(ptext, key))
|
print("\nEnter exactly 5 messages to encrypt:")
|
||||||
print("DES 256 Bit Cyphertext: ", des_256(ptext, key))
|
for i in range(5):
|
||||||
print("AES 128 Bit Cyphertext: ", aes_128(ptext, key))
|
while True:
|
||||||
print("AES 192 Bit Cyphertext: ", aes_192(ptext, key))
|
message = input(f"Message {i+1}: ")
|
||||||
print("AES 256 Bit Cyphertext: ", aes_256(ptext, key))
|
if message.strip(): # Only accept non-empty messages
|
||||||
|
messages.append(message)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Please enter a non-empty message.")
|
||||||
|
|
||||||
|
key = input("\nEnter key: ")
|
||||||
|
|
||||||
|
# Define algorithms to test (using ECB mode only)
|
||||||
|
algorithms = [
|
||||||
|
('DES', des_128, DES.MODE_ECB),
|
||||||
|
('DES3-192', des_192, DES3.MODE_ECB),
|
||||||
|
('AES-128', aes_128, AES.MODE_ECB),
|
||||||
|
('AES-192', aes_192, AES.MODE_ECB),
|
||||||
|
('AES-256', aes_256, AES.MODE_ECB)
|
||||||
|
]
|
||||||
|
|
||||||
|
timing_data = {}
|
||||||
|
|
||||||
|
print("\nEncrypting messages and measuring performance...\n")
|
||||||
|
|
||||||
|
# Run each message through each algorithm multiple times for better precision
|
||||||
|
for algo_name, algo_func, mode in algorithms:
|
||||||
|
timing_data[algo_name] = []
|
||||||
|
print(f"=== {algo_name} ===")
|
||||||
|
|
||||||
|
for i, message in enumerate(messages):
|
||||||
|
print(f"Message {i+1}: {message[:30]}...")
|
||||||
|
|
||||||
|
# Run multiple times and take the best time to reduce noise
|
||||||
|
best_time = float('inf')
|
||||||
|
for _ in range(10): # 10 runs for better precision
|
||||||
|
ctext, exec_time = encrypt_with_timing(algo_func, message, key, mode)
|
||||||
|
best_time = min(best_time, exec_time)
|
||||||
|
|
||||||
|
print(f"{algo_name}: {best_time:.8f}s ({best_time*1000000:.2f}μs)")
|
||||||
|
timing_data[algo_name].append(best_time)
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Generate performance graphs
|
||||||
|
print("Generating performance visualization...")
|
||||||
|
bokeh_graph(timing_data)
|
||||||
|
print("Performance graphs saved to 'encryption_performance.html'")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
61
IS/Lab/Lab2/des_vs_aes256.html
Normal file
61
IS/Lab/Lab2/des_vs_aes256.html
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,87 +1,176 @@
|
||||||
from Crypto.Cipher import DES, AES
|
|
||||||
from Crypto.Util.Padding import pad, unpad
|
|
||||||
import time
|
import time
|
||||||
|
import numpy as np
|
||||||
|
from Crypto.Cipher import AES, DES
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
from bokeh.plotting import figure, show
|
from bokeh.plotting import figure, show
|
||||||
from bokeh.models import ColumnDataSource
|
from bokeh.models import HoverTool
|
||||||
from bokeh.io import output_file
|
from bokeh.layouts import column
|
||||||
|
from bokeh.palettes import Category10
|
||||||
|
|
||||||
|
def aes_cipher(key):
|
||||||
|
return AES.new(key.encode('utf-8'), AES.MODE_ECB)
|
||||||
|
|
||||||
def benchmark_encryption_decryption(cipher_func, data, key):
|
def aes_en(ptext, key):
|
||||||
# Measure encryption time
|
cipher = aes_cipher(key)
|
||||||
start_time = time.time()
|
ptext = pad(ptext.encode('utf-8'), AES.block_size)
|
||||||
encrypted = cipher_func(data, key)
|
return cipher.encrypt(ptext)
|
||||||
encrypt_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Measure decryption time
|
def aes_de(ctext, key):
|
||||||
start_time = time.time()
|
cipher = aes_cipher(key)
|
||||||
decrypted = cipher_func(encrypted, key, decrypt=True)
|
decrypted = cipher.decrypt(ctext)
|
||||||
decrypt_time = time.time() - start_time
|
return unpad(decrypted, AES.block_size).decode('utf-8')
|
||||||
|
|
||||||
return encrypt_time, decrypt_time
|
def aes256_pad_key(key):
|
||||||
|
return key.ljust(32)[:32]
|
||||||
|
|
||||||
|
def des_cipher(key):
|
||||||
|
return DES.new(key.encode('utf-8'), DES.MODE_ECB)
|
||||||
|
|
||||||
def des_cipher(data, key, decrypt=False):
|
def des_en(ptext, key):
|
||||||
cipher = DES.new(key.encode('utf-8'), DES.MODE_ECB)
|
cipher = des_cipher(key)
|
||||||
if decrypt:
|
ptext = pad(ptext.encode('utf-8'), DES.block_size)
|
||||||
return unpad(cipher.decrypt(data), DES.block_size).decode('utf-8')
|
return cipher.encrypt(ptext)
|
||||||
else:
|
|
||||||
padded_data = pad(data.encode('utf-8'), DES.block_size)
|
|
||||||
return cipher.encrypt(padded_data)
|
|
||||||
|
|
||||||
|
def des_de(ctext, key):
|
||||||
|
cipher = des_cipher(key)
|
||||||
|
decrypted = cipher.decrypt(ctext)
|
||||||
|
return unpad(decrypted, DES.block_size).decode('utf-8')
|
||||||
|
|
||||||
def aes_cipher(data, key, decrypt=False):
|
def des_pad_key(key):
|
||||||
cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB)
|
return key.ljust(8)[:8]
|
||||||
if decrypt:
|
|
||||||
return unpad(cipher.decrypt(data), AES.block_size).decode('utf-8')
|
|
||||||
else:
|
|
||||||
padded_data = pad(data.encode('utf-8'), AES.block_size)
|
|
||||||
return cipher.encrypt(padded_data)
|
|
||||||
|
|
||||||
|
def time_encryption_progressive(encrypt_func, plaintext, key, max_iterations=1000):
|
||||||
|
"""Time encryption across different iteration counts"""
|
||||||
|
iteration_counts = np.logspace(1, np.log10(max_iterations), 10, dtype=int)
|
||||||
|
times_per_iteration = []
|
||||||
|
|
||||||
|
for iterations in iteration_counts:
|
||||||
|
start_time = time.time()
|
||||||
|
for _ in range(iterations):
|
||||||
|
encrypt_func(plaintext, key)
|
||||||
|
end_time = time.time()
|
||||||
|
total_time = end_time - start_time
|
||||||
|
times_per_iteration.append(total_time / iterations)
|
||||||
|
|
||||||
|
return iteration_counts, times_per_iteration
|
||||||
|
|
||||||
|
def time_decryption_progressive(decrypt_func, ciphertext, key, max_iterations=1000):
|
||||||
|
"""Time decryption across different iteration counts"""
|
||||||
|
iteration_counts = np.logspace(1, np.log10(max_iterations), 10, dtype=int)
|
||||||
|
times_per_iteration = []
|
||||||
|
|
||||||
|
for iterations in iteration_counts:
|
||||||
|
start_time = time.time()
|
||||||
|
for _ in range(iterations):
|
||||||
|
decrypt_func(ciphertext, key)
|
||||||
|
end_time = time.time()
|
||||||
|
total_time = end_time - start_time
|
||||||
|
times_per_iteration.append(total_time / iterations)
|
||||||
|
|
||||||
|
return iteration_counts, times_per_iteration
|
||||||
|
|
||||||
|
def benchmark_ciphers(plaintext, raw_key, max_iterations=1000):
|
||||||
|
# Prepare keys
|
||||||
|
aes_key = aes256_pad_key(raw_key)
|
||||||
|
des_key = des_pad_key(raw_key)
|
||||||
|
|
||||||
|
# Get ciphertexts for decryption timing
|
||||||
|
aes_ciphertext = aes_en(plaintext, aes_key)
|
||||||
|
des_ciphertext = des_en(plaintext, des_key)
|
||||||
|
|
||||||
|
# Time encryption progressively
|
||||||
|
aes_enc_iterations, aes_enc_times = time_encryption_progressive(aes_en, plaintext, aes_key, max_iterations)
|
||||||
|
des_enc_iterations, des_enc_times = time_encryption_progressive(des_en, plaintext, des_key, max_iterations)
|
||||||
|
|
||||||
|
# Time decryption progressively
|
||||||
|
aes_dec_iterations, aes_dec_times = time_decryption_progressive(aes_de, aes_ciphertext, aes_key, max_iterations)
|
||||||
|
des_dec_iterations, des_dec_times = time_decryption_progressive(des_de, des_ciphertext, des_key, max_iterations)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'aes_enc_iterations': aes_enc_iterations,
|
||||||
|
'aes_enc_times': aes_enc_times,
|
||||||
|
'des_enc_iterations': des_enc_iterations,
|
||||||
|
'des_enc_times': des_enc_times,
|
||||||
|
'aes_dec_iterations': aes_dec_iterations,
|
||||||
|
'aes_dec_times': aes_dec_times,
|
||||||
|
'des_dec_iterations': des_dec_iterations,
|
||||||
|
'des_dec_times': des_dec_times
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_plot(title, plaintext_length):
|
||||||
|
return figure(
|
||||||
|
title=f"{title}\nPlaintext length: {plaintext_length} chars",
|
||||||
|
x_axis_label="Number of Iterations",
|
||||||
|
y_axis_label="Time per Operation (seconds)",
|
||||||
|
x_axis_type="log",
|
||||||
|
y_axis_type="log",
|
||||||
|
width=800,
|
||||||
|
height=400,
|
||||||
|
background_fill_color="#fafafa",
|
||||||
|
border_fill_color="whitesmoke"
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_line_and_markers(plot, x_data, y_data, color, label):
|
||||||
|
plot.line(x_data, y_data, line_width=3, color=color, alpha=0.8, legend_label=label)
|
||||||
|
plot.scatter(x_data, y_data, size=8, color=color, alpha=0.8)
|
||||||
|
|
||||||
|
def plot_results(results, plaintext_length):
|
||||||
|
colors = Category10[4]
|
||||||
|
|
||||||
|
# Create plots
|
||||||
|
p1 = create_plot("Encryption Performance: Time per Operation", plaintext_length)
|
||||||
|
p2 = create_plot("Decryption Performance: Time per Operation", plaintext_length)
|
||||||
|
|
||||||
|
# Add data to plots
|
||||||
|
add_line_and_markers(p1, results['aes_enc_iterations'], results['aes_enc_times'], colors[0], "AES-256 Encryption")
|
||||||
|
add_line_and_markers(p1, results['des_enc_iterations'], results['des_enc_times'], colors[1], "DES Encryption")
|
||||||
|
add_line_and_markers(p2, results['aes_dec_iterations'], results['aes_dec_times'], colors[2], "AES-256 Decryption")
|
||||||
|
add_line_and_markers(p2, results['des_dec_iterations'], results['des_dec_times'], colors[3], "DES Decryption")
|
||||||
|
|
||||||
|
# Add hover tools and styling
|
||||||
|
hover = HoverTool(tooltips=[("Algorithm", "@legend_label"), ("Iterations", "@x"), ("Time per Op", "@y{0.0000000} sec")])
|
||||||
|
|
||||||
|
for p in [p1, p2]:
|
||||||
|
p.add_tools(hover)
|
||||||
|
p.legend.location = "top_right"
|
||||||
|
p.legend.click_policy = "hide"
|
||||||
|
p.legend.background_fill_alpha = 0.8
|
||||||
|
p.grid.grid_line_alpha = 0.3
|
||||||
|
|
||||||
|
show(column(p1, p2))
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
message = "Performance Testing of Encryption Algorithms"
|
print("AES-256 vs DES Performance Comparison")
|
||||||
|
print("=====================================")
|
||||||
|
|
||||||
# Test with different key sizes
|
plaintext = input("Enter plaintext: ")
|
||||||
des_key = "12345678" # 8 bytes for DES
|
key = input("Enter key: ")
|
||||||
aes_key = "12345678901234567890123456789012" # 32 bytes for AES-256
|
max_iterations = int(input("Enter maximum number of iterations (default 1000): ") or "1000")
|
||||||
|
|
||||||
# Benchmark DES
|
print(f"\nBenchmarking across iteration ranges up to {max_iterations}...")
|
||||||
des_encrypt_time, des_decrypt_time = benchmark_encryption_decryption(des_cipher, message, des_key)
|
results = benchmark_ciphers(plaintext, key, max_iterations)
|
||||||
|
|
||||||
# Benchmark AES-256
|
# Calculate average times for comparison
|
||||||
aes_encrypt_time, aes_decrypt_time = benchmark_encryption_decryption(aes_cipher, message, aes_key)
|
avg_aes_enc = np.mean(results['aes_enc_times'])
|
||||||
|
avg_des_enc = np.mean(results['des_enc_times'])
|
||||||
|
avg_aes_dec = np.mean(results['aes_dec_times'])
|
||||||
|
avg_des_dec = np.mean(results['des_dec_times'])
|
||||||
|
|
||||||
# Print results
|
print("\nAverage Results (time per operation):")
|
||||||
print("Performance Results:")
|
print(f"AES-256 Encryption: {avg_aes_enc:.8f} seconds")
|
||||||
print("-" * 40)
|
print(f"DES Encryption: {avg_des_enc:.8f} seconds")
|
||||||
print(f"DES Encryption: {des_encrypt_time:.9f} seconds")
|
print(f"AES-256 Decryption: {avg_aes_dec:.8f} seconds")
|
||||||
print(f"DES Decryption: {des_decrypt_time:.9f} seconds")
|
print(f"DES Decryption: {avg_des_dec:.8f} seconds")
|
||||||
print(f"AES-256 Encryption: {aes_encrypt_time:.9f} seconds")
|
|
||||||
print(f"AES-256 Decryption: {aes_decrypt_time:.9f} seconds")
|
|
||||||
|
|
||||||
# Create Bokeh visualization
|
print("\nSpeed comparison:")
|
||||||
algorithms = ['DES', 'AES-256']
|
if avg_aes_enc < avg_des_enc:
|
||||||
encrypt_times = [des_encrypt_time, aes_encrypt_time]
|
ratio = avg_des_enc / avg_aes_enc
|
||||||
decrypt_times = [des_decrypt_time, aes_decrypt_time]
|
print(f"AES-256 encryption is {ratio:.2f}x faster than DES")
|
||||||
|
else:
|
||||||
# Create the plot
|
ratio = avg_aes_enc / avg_des_enc
|
||||||
p = figure(x_range=algorithms, height=400, title="Encryption/Decryption Performance Comparison",
|
print(f"DES encryption is {ratio:.2f}x faster than AES-256")
|
||||||
toolbar_location=None, responsive=True)
|
|
||||||
|
|
||||||
p.vbar(x='algorithm', top='encrypt_time', width=0.4, color='blue', alpha=0.7, legend_label="Encryption",
|
|
||||||
source=ColumnDataSource(data=dict(algorithm=algorithms, encrypt_time=encrypt_times)))
|
|
||||||
p.vbar(x='algorithm', top='decrypt_time', width=0.4, color='red', alpha=0.7, legend_label="Decryption",
|
|
||||||
source=ColumnDataSource(data=dict(algorithm=algorithms, decrypt_time=decrypt_times)))
|
|
||||||
|
|
||||||
p.legend.location = "top_right"
|
|
||||||
p.xaxis.axis_label = "Algorithm"
|
|
||||||
p.yaxis.axis_label = "Time (seconds)"
|
|
||||||
p.title.text_font_size = "14px"
|
|
||||||
|
|
||||||
# Save and show the plot
|
|
||||||
output_file("encryption_performance.html")
|
|
||||||
show(p)
|
|
||||||
|
|
||||||
|
plot_results(results, len(plaintext))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
61
IS/Lab/Lab2/encryption_performance.html
Normal file
61
IS/Lab/Lab2/encryption_performance.html
Normal file
File diff suppressed because one or more lines are too long
61
IS/Lab/Lab2/multiround_aes_192
Normal file
61
IS/Lab/Lab2/multiround_aes_192
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
|
|
||||||
|
def aes_cipher(key):
|
||||||
|
return AES.new(key.encode('utf-8'), AES.MODE_ECB)
|
||||||
|
|
||||||
|
def aes_en(ptext, key):
|
||||||
|
cipher = aes_cipher(key)
|
||||||
|
ptext = pad(ptext.encode('utf-8'), AES.block_size)
|
||||||
|
return cipher.encrypt(ptext)
|
||||||
|
|
||||||
|
def aes_de(ctext, key):
|
||||||
|
cipher = aes_cipher(key)
|
||||||
|
decrypted = cipher.decrypt(ctext)
|
||||||
|
return unpad(decrypted, AES.block_size).decode('utf-8')
|
||||||
|
|
||||||
|
def aespad_key(key):
|
||||||
|
return key.ljust(24)[:24]
|
||||||
|
|
||||||
|
def aes_en_trace(ptext, key):
|
||||||
|
key = aespad_key(key)
|
||||||
|
key_bytes = key.encode('utf-8')
|
||||||
|
cipher = AES.new(key_bytes, AES.MODE_ECB)
|
||||||
|
blocks = pad(ptext.encode('utf-8'), AES.block_size)
|
||||||
|
|
||||||
|
print("AES-192 (ECB) concise steps:")
|
||||||
|
print(" • Key expansion: Nk=6, Nb=4, Nr=12 → 13 round keys")
|
||||||
|
print(" • Initial round: AddRoundKey")
|
||||||
|
print(" • Main rounds (1..11): SubBytes → ShiftRows → MixColumns → AddRoundKey")
|
||||||
|
print(" • Final round (12): SubBytes → ShiftRows → AddRoundKey\n")
|
||||||
|
|
||||||
|
out = bytearray()
|
||||||
|
for i in range(0, len(blocks), 16):
|
||||||
|
block = blocks[i:i+16]
|
||||||
|
print(f"Block {i//16} plaintext: {block.hex()}")
|
||||||
|
print(" Round 0: AddRoundKey")
|
||||||
|
for r in range(1, 12):
|
||||||
|
print(f" Round {r}: SubBytes → ShiftRows → MixColumns → AddRoundKey")
|
||||||
|
print(" Round 12: SubBytes → ShiftRows → AddRoundKey")
|
||||||
|
cblock = cipher.encrypt(block)
|
||||||
|
print(f" Ciphertext block: {cblock.hex()}\n")
|
||||||
|
out.extend(cblock)
|
||||||
|
return bytes(out)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
default_pt = "MIT AES DEMO"
|
||||||
|
default_key = "MIT-AES-192-DEMO-KEY-24!"
|
||||||
|
|
||||||
|
ptext = input(f"Enter plaintext (blank={default_pt}): ").strip()
|
||||||
|
key = input(f"Enter key (blank={default_key}): ").strip()
|
||||||
|
if not ptext:
|
||||||
|
ptext = default_pt
|
||||||
|
if not key:
|
||||||
|
key = default_key
|
||||||
|
|
||||||
|
ctext = aes_en_trace(ptext, key)
|
||||||
|
print("Ciphertext:", ctext.hex())
|
||||||
|
print("Decrypted:", aes_de(ctext, aespad_key(key)))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
120
IS/Lab/Lab3/DiffieHellman.py
Normal file
120
IS/Lab/Lab3/DiffieHellman.py
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import time
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
from Crypto.Protocol.KDF import HKDF
|
||||||
|
from Crypto.Util import number
|
||||||
|
|
||||||
|
|
||||||
|
def rfc3526_group14() -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Return the 2048-bit MODP Group (Group 14) parameters from RFC 3526.
|
||||||
|
|
||||||
|
g = 2
|
||||||
|
p is the safe prime specified in RFC 3526, section 3.
|
||||||
|
"""
|
||||||
|
# RFC 3526 Group 14 (2048-bit MODP) prime (hex, concatenated)
|
||||||
|
p_hex = (
|
||||||
|
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||||
|
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||||
|
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||||
|
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||||
|
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||||
|
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||||
|
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||||
|
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||||
|
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||||
|
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||||
|
"15728E5A8AACAA68FFFFFFFFFFFFFFFF"
|
||||||
|
)
|
||||||
|
p = int(p_hex, 16)
|
||||||
|
g = 2
|
||||||
|
return p, g
|
||||||
|
|
||||||
|
|
||||||
|
def int_to_fixed_length_bytes(value: int, length_bits: int) -> bytes:
|
||||||
|
length_bytes = (length_bits + 7) // 8
|
||||||
|
return value.to_bytes(length_bytes, byteorder="big")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_keypair(p: int, g: int, private_bits: int = 256) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
Generate a Diffie-Hellman private/public key pair.
|
||||||
|
|
||||||
|
- private_bits controls the size of the secret exponent for performance and security.
|
||||||
|
256 bits is a common choice for Group 14.
|
||||||
|
"""
|
||||||
|
a = 0
|
||||||
|
while a < 2:
|
||||||
|
a = number.getRandomNBitInteger(private_bits)
|
||||||
|
A = pow(g, a, p)
|
||||||
|
return a, A
|
||||||
|
|
||||||
|
|
||||||
|
def derive_shared_key(peer_public: int, private: int, p: int, key_len: int = 32) -> bytes:
|
||||||
|
"""
|
||||||
|
Compute the shared secret and derive a symmetric key using HKDF-SHA256.
|
||||||
|
Returns key_len bytes (default 32 bytes = 256-bit key).
|
||||||
|
"""
|
||||||
|
shared_secret = pow(peer_public, private, p)
|
||||||
|
# Use fixed-length big-endian encoding of the shared secret for KDF input
|
||||||
|
shared_bytes = int_to_fixed_length_bytes(shared_secret, p.bit_length())
|
||||||
|
key = HKDF(shared_bytes, key_len, salt=None, hashmod=SHA256, context=b"DH key")
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TimingResult:
|
||||||
|
alice_keygen_s: float
|
||||||
|
bob_keygen_s: float
|
||||||
|
alice_exchange_s: float
|
||||||
|
bob_exchange_s: float
|
||||||
|
|
||||||
|
|
||||||
|
def measure_timings(p: int, g: int, private_bits: int = 256) -> TimingResult:
|
||||||
|
start = time.perf_counter()
|
||||||
|
a_priv, a_pub = generate_keypair(p, g, private_bits)
|
||||||
|
alice_keygen_s = time.perf_counter() - start
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
b_priv, b_pub = generate_keypair(p, g, private_bits)
|
||||||
|
bob_keygen_s = time.perf_counter() - start
|
||||||
|
|
||||||
|
# Exchange
|
||||||
|
start = time.perf_counter()
|
||||||
|
a_key = derive_shared_key(b_pub, a_priv, p)
|
||||||
|
alice_exchange_s = time.perf_counter() - start
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
b_key = derive_shared_key(a_pub, b_priv, p)
|
||||||
|
bob_exchange_s = time.perf_counter() - start
|
||||||
|
|
||||||
|
# Sanity check
|
||||||
|
if a_key != b_key:
|
||||||
|
raise RuntimeError("Derived keys do not match. Check parameters.")
|
||||||
|
|
||||||
|
return TimingResult(
|
||||||
|
alice_keygen_s=alice_keygen_s,
|
||||||
|
bob_keygen_s=bob_keygen_s,
|
||||||
|
alice_exchange_s=alice_exchange_s,
|
||||||
|
bob_exchange_s=bob_exchange_s,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
p, g = rfc3526_group14()
|
||||||
|
|
||||||
|
timings = measure_timings(p, g, private_bits=256)
|
||||||
|
|
||||||
|
print("Diffie-Hellman (RFC3526 Group 14, g=2)")
|
||||||
|
print(f"Prime bits: {p.bit_length()}\n")
|
||||||
|
|
||||||
|
print("Timings (seconds):")
|
||||||
|
print(f"- Alice key generation: {timings.alice_keygen_s:.6f}")
|
||||||
|
print(f"- Bob key generation: {timings.bob_keygen_s:.6f}")
|
||||||
|
print(f"- Alice key exchange: {timings.alice_exchange_s:.6f}")
|
||||||
|
print(f"- Bob key exchange: {timings.bob_exchange_s:.6f}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
58
IS/Lab/Lab3/ECC.py
Normal file
58
IS/Lab/Lab3/ECC.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
from Crypto.PublicKey import ECC
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_keygen(curve: str = 'P-256') -> ECC.EccKey:
|
||||||
|
return ECC.generate(curve=curve)
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_encrypt(plaintext: str, recipient_public_key: ECC.EccKey):
|
||||||
|
eph_private = ECC.generate(curve=recipient_public_key.curve)
|
||||||
|
shared_point = recipient_public_key.pointQ * eph_private.d
|
||||||
|
shared_x = int(shared_point.x)
|
||||||
|
aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
|
||||||
|
|
||||||
|
cipher = AES.new(aes_key, AES.MODE_GCM)
|
||||||
|
ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode('utf-8'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
'ephemeral_pub_der': eph_private.public_key().export_key(format='DER'),
|
||||||
|
'nonce': cipher.nonce,
|
||||||
|
'tag': tag,
|
||||||
|
'ciphertext': ciphertext,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_decrypt(enc: dict, recipient_private_key: ECC.EccKey) -> str:
|
||||||
|
eph_public = ECC.import_key(enc['ephemeral_pub_der'])
|
||||||
|
shared_point = eph_public.pointQ * recipient_private_key.d
|
||||||
|
shared_x = int(shared_point.x)
|
||||||
|
aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
|
||||||
|
|
||||||
|
cipher = AES.new(aes_key, AES.MODE_GCM, nonce=enc['nonce'])
|
||||||
|
plaintext = cipher.decrypt_and_verify(enc['ciphertext'], enc['tag'])
|
||||||
|
return plaintext.decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print('Welcome to ECC (ECIES-style)')
|
||||||
|
ptext = input('Enter plaintext: ')
|
||||||
|
|
||||||
|
priv_key = ecc_keygen()
|
||||||
|
pub_key = priv_key.public_key()
|
||||||
|
|
||||||
|
print('\nPublic Key (Qx, Qy):')
|
||||||
|
print('Qx =', hex(int(pub_key.pointQ.x)))
|
||||||
|
print('Qy =', hex(int(pub_key.pointQ.y)))
|
||||||
|
|
||||||
|
enc = ecc_encrypt(ptext, pub_key)
|
||||||
|
print("\nYour ciphertext (hex):", binascii.hexlify(enc['ciphertext']).decode())
|
||||||
|
|
||||||
|
decrypted = ecc_decrypt(enc, priv_key)
|
||||||
|
print('Your decrypted plaintext:', decrypted)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
57
IS/Lab/Lab3/ElGamal.py
Normal file
57
IS/Lab/Lab3/ElGamal.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import random
|
||||||
|
from Crypto.Util.number import getPrime
|
||||||
|
|
||||||
|
def elgamal_keygen(bits=512):
|
||||||
|
p = getPrime(bits)
|
||||||
|
g = random.randint(2, p-1)
|
||||||
|
x = random.randint(1, p-2) # private key
|
||||||
|
h = pow(g, x, p) # public key component
|
||||||
|
return (p, g, h), x
|
||||||
|
|
||||||
|
def elgamal_encrypt(message, pub_key):
|
||||||
|
p, g, h = pub_key
|
||||||
|
m = int.from_bytes(message.encode('utf-8'), 'big')
|
||||||
|
if m >= p:
|
||||||
|
raise ValueError("Message too large for key size")
|
||||||
|
|
||||||
|
k = random.randint(1, p-2)
|
||||||
|
c1 = pow(g, k, p)
|
||||||
|
c2 = (m * pow(h, k, p)) % p
|
||||||
|
return (c1, c2)
|
||||||
|
|
||||||
|
def elgamal_decrypt(ciphertext, priv_key, pub_key):
|
||||||
|
c1, c2 = ciphertext
|
||||||
|
p, g, h = pub_key
|
||||||
|
x = priv_key
|
||||||
|
|
||||||
|
s = pow(c1, x, p)
|
||||||
|
s_inv = pow(s, p-2, p) # modular inverse
|
||||||
|
m = (c2 * s_inv) % p
|
||||||
|
|
||||||
|
return m.to_bytes((m.bit_length() + 7) // 8, 'big').decode('utf-8')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to ElGamal")
|
||||||
|
ptext = input("Enter plaintext: ")
|
||||||
|
|
||||||
|
# Generate keys
|
||||||
|
pub_key, priv_key = elgamal_keygen()
|
||||||
|
p, g, h = pub_key
|
||||||
|
|
||||||
|
print(f"\nPublic Key (p, g, h):")
|
||||||
|
print(f"p = {hex(p)}")
|
||||||
|
print(f"g = {g}")
|
||||||
|
print(f"h = {hex(h)}")
|
||||||
|
|
||||||
|
# Encrypt
|
||||||
|
ctext = elgamal_encrypt(ptext, pub_key)
|
||||||
|
print(f"\nCiphertext (c1, c2):")
|
||||||
|
print(f"c1 = {hex(ctext[0])}")
|
||||||
|
print(f"c2 = {hex(ctext[1])}")
|
||||||
|
|
||||||
|
# Decrypt
|
||||||
|
decrypted = elgamal_decrypt(ctext, priv_key, pub_key)
|
||||||
|
print(f"Decrypted: {decrypted}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
299
IS/Lab/Lab3/FileTransfer.py
Normal file
299
IS/Lab/Lab3/FileTransfer.py
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import binascii
|
||||||
|
from Crypto.PublicKey import RSA, ECC
|
||||||
|
from Crypto.Cipher import PKCS1_OAEP, AES
|
||||||
|
from Crypto.Hash import SHA256
|
||||||
|
from Crypto.Util.Padding import pad, unpad
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from bokeh.plotting import figure, show, output_file
|
||||||
|
from bokeh.layouts import gridplot
|
||||||
|
from bokeh.models import HoverTool
|
||||||
|
|
||||||
|
|
||||||
|
def generate_test_file(size_mb):
|
||||||
|
"""Generate test file of specified size in MB"""
|
||||||
|
filename = f"test_file_{size_mb}MB.txt"
|
||||||
|
with open(filename, 'wb') as f:
|
||||||
|
# Write random data
|
||||||
|
for _ in range(size_mb * 1024): # 1MB = 1024KB
|
||||||
|
f.write(get_random_bytes(1024))
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
def rsa_keygen_timed():
|
||||||
|
"""Generate RSA key pair and measure time"""
|
||||||
|
start = time.time()
|
||||||
|
key = RSA.generate(2048)
|
||||||
|
gen_time = time.time() - start
|
||||||
|
return key, gen_time
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_keygen_timed():
|
||||||
|
"""Generate ECC key pair and measure time"""
|
||||||
|
start = time.time()
|
||||||
|
key = ECC.generate(curve='secp256r1')
|
||||||
|
gen_time = time.time() - start
|
||||||
|
return key, gen_time
|
||||||
|
|
||||||
|
|
||||||
|
def rsa_encrypt_file(filename, pub_key):
|
||||||
|
"""Encrypt file using RSA with AES hybrid encryption"""
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
# Generate AES key
|
||||||
|
aes_key = get_random_bytes(32) # 256-bit AES key
|
||||||
|
|
||||||
|
# Encrypt AES key with RSA
|
||||||
|
rsa_cipher = PKCS1_OAEP.new(pub_key)
|
||||||
|
encrypted_aes_key = rsa_cipher.encrypt(aes_key)
|
||||||
|
|
||||||
|
# Encrypt file with AES
|
||||||
|
aes_cipher = AES.new(aes_key, AES.MODE_CBC)
|
||||||
|
iv = aes_cipher.iv
|
||||||
|
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
plaintext = f.read()
|
||||||
|
|
||||||
|
padded_plaintext = pad(plaintext, AES.block_size)
|
||||||
|
ciphertext = aes_cipher.encrypt(padded_plaintext)
|
||||||
|
|
||||||
|
enc_time = time.time() - start
|
||||||
|
|
||||||
|
encrypted_data = {
|
||||||
|
'encrypted_aes_key': encrypted_aes_key,
|
||||||
|
'iv': iv,
|
||||||
|
'ciphertext': ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
return encrypted_data, enc_time
|
||||||
|
|
||||||
|
|
||||||
|
def rsa_decrypt_file(encrypted_data, priv_key):
|
||||||
|
"""Decrypt file using RSA with AES hybrid decryption"""
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
# Decrypt AES key with RSA
|
||||||
|
rsa_cipher = PKCS1_OAEP.new(priv_key)
|
||||||
|
aes_key = rsa_cipher.decrypt(encrypted_data['encrypted_aes_key'])
|
||||||
|
|
||||||
|
# Decrypt file with AES
|
||||||
|
aes_cipher = AES.new(aes_key, AES.MODE_CBC, encrypted_data['iv'])
|
||||||
|
padded_plaintext = aes_cipher.decrypt(encrypted_data['ciphertext'])
|
||||||
|
plaintext = unpad(padded_plaintext, AES.block_size)
|
||||||
|
|
||||||
|
dec_time = time.time() - start
|
||||||
|
return plaintext, dec_time
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_encrypt_file(filename, pub_key):
|
||||||
|
"""Encrypt file using ECC with AES hybrid encryption"""
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
# Generate ephemeral key pair
|
||||||
|
eph_private = ECC.generate(curve='secp256r1')
|
||||||
|
|
||||||
|
# Compute shared secret
|
||||||
|
shared_point = pub_key.pointQ * eph_private.d
|
||||||
|
shared_x = int(shared_point.x)
|
||||||
|
aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
|
||||||
|
|
||||||
|
# Encrypt file with AES
|
||||||
|
aes_cipher = AES.new(aes_key, AES.MODE_GCM)
|
||||||
|
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
plaintext = f.read()
|
||||||
|
|
||||||
|
ciphertext, tag = aes_cipher.encrypt_and_digest(plaintext)
|
||||||
|
|
||||||
|
enc_time = time.time() - start
|
||||||
|
|
||||||
|
encrypted_data = {
|
||||||
|
'ephemeral_pub_der': eph_private.public_key().export_key(format='DER'),
|
||||||
|
'nonce': aes_cipher.nonce,
|
||||||
|
'tag': tag,
|
||||||
|
'ciphertext': ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
return encrypted_data, enc_time
|
||||||
|
|
||||||
|
|
||||||
|
def ecc_decrypt_file(encrypted_data, priv_key):
|
||||||
|
"""Decrypt file using ECC with AES hybrid decryption"""
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
# Import ephemeral public key
|
||||||
|
eph_public = ECC.import_key(encrypted_data['ephemeral_pub_der'])
|
||||||
|
|
||||||
|
# Compute shared secret
|
||||||
|
shared_point = eph_public.pointQ * priv_key.d
|
||||||
|
shared_x = int(shared_point.x)
|
||||||
|
aes_key = SHA256.new(shared_x.to_bytes(32, 'big')).digest()
|
||||||
|
|
||||||
|
# Decrypt file with AES
|
||||||
|
aes_cipher = AES.new(aes_key, AES.MODE_GCM, nonce=encrypted_data['nonce'])
|
||||||
|
plaintext = aes_cipher.decrypt_and_verify(encrypted_data['ciphertext'], encrypted_data['tag'])
|
||||||
|
|
||||||
|
dec_time = time.time() - start
|
||||||
|
return plaintext, dec_time
|
||||||
|
|
||||||
|
|
||||||
|
def measure_performance(file_sizes):
|
||||||
|
"""Measure performance for both RSA and ECC"""
|
||||||
|
results = {
|
||||||
|
'file_sizes': file_sizes,
|
||||||
|
'rsa_keygen': [],
|
||||||
|
'ecc_keygen': [],
|
||||||
|
'rsa_encrypt': [],
|
||||||
|
'rsa_decrypt': [],
|
||||||
|
'ecc_encrypt': [],
|
||||||
|
'ecc_decrypt': [],
|
||||||
|
'rsa_key_size': 0,
|
||||||
|
'ecc_key_size': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Performance Testing - RSA vs ECC File Transfer")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Generate keys once
|
||||||
|
rsa_key, rsa_keygen_time = rsa_keygen_timed()
|
||||||
|
ecc_key, ecc_keygen_time = ecc_keygen_timed()
|
||||||
|
|
||||||
|
# Calculate key sizes
|
||||||
|
results['rsa_key_size'] = len(rsa_key.export_key('DER'))
|
||||||
|
results['ecc_key_size'] = len(ecc_key.export_key(format='DER'))
|
||||||
|
|
||||||
|
print(f"RSA Key Generation Time: {rsa_keygen_time:.4f} seconds")
|
||||||
|
print(f"ECC Key Generation Time: {ecc_keygen_time:.4f} seconds")
|
||||||
|
print(f"RSA Key Size: {results['rsa_key_size']} bytes")
|
||||||
|
print(f"ECC Key Size: {results['ecc_key_size']} bytes")
|
||||||
|
print()
|
||||||
|
|
||||||
|
for size in file_sizes:
|
||||||
|
print(f"Testing {size}MB file...")
|
||||||
|
|
||||||
|
# Generate test file
|
||||||
|
filename = generate_test_file(size)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# RSA performance
|
||||||
|
rsa_pub = rsa_key.publickey()
|
||||||
|
encrypted_rsa, rsa_enc_time = rsa_encrypt_file(filename, rsa_pub)
|
||||||
|
decrypted_rsa, rsa_dec_time = rsa_decrypt_file(encrypted_rsa, rsa_key)
|
||||||
|
|
||||||
|
# ECC performance
|
||||||
|
ecc_pub = ecc_key.public_key()
|
||||||
|
encrypted_ecc, ecc_enc_time = ecc_encrypt_file(filename, ecc_pub)
|
||||||
|
decrypted_ecc, ecc_dec_time = ecc_decrypt_file(encrypted_ecc, ecc_key)
|
||||||
|
|
||||||
|
# Store results
|
||||||
|
results['rsa_keygen'].append(rsa_keygen_time)
|
||||||
|
results['ecc_keygen'].append(ecc_keygen_time)
|
||||||
|
results['rsa_encrypt'].append(rsa_enc_time)
|
||||||
|
results['rsa_decrypt'].append(rsa_dec_time)
|
||||||
|
results['ecc_encrypt'].append(ecc_enc_time)
|
||||||
|
results['ecc_decrypt'].append(ecc_dec_time)
|
||||||
|
|
||||||
|
print(f" RSA - Encrypt: {rsa_enc_time:.4f}s, Decrypt: {rsa_dec_time:.4f}s")
|
||||||
|
print(f" ECC - Encrypt: {ecc_enc_time:.4f}s, Decrypt: {ecc_dec_time:.4f}s")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Clean up test file
|
||||||
|
if os.path.exists(filename):
|
||||||
|
os.remove(filename)
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def create_performance_graphs(results):
|
||||||
|
"""Create performance comparison graphs using Bokeh"""
|
||||||
|
output_file("file_transfer_performance.html")
|
||||||
|
|
||||||
|
file_sizes = results['file_sizes']
|
||||||
|
|
||||||
|
# Encryption time comparison
|
||||||
|
p1 = figure(title="Encryption Time Comparison", x_axis_label="File Size (MB)",
|
||||||
|
y_axis_label="Time (seconds)", width=400, height=300)
|
||||||
|
p1.line(file_sizes, results['rsa_encrypt'], legend_label="RSA", line_color="red", line_width=2)
|
||||||
|
p1.circle(file_sizes, results['rsa_encrypt'], color="red", size=6)
|
||||||
|
p1.line(file_sizes, results['ecc_encrypt'], legend_label="ECC", line_color="blue", line_width=2)
|
||||||
|
p1.circle(file_sizes, results['ecc_encrypt'], color="blue", size=6)
|
||||||
|
p1.legend.location = "top_left"
|
||||||
|
|
||||||
|
# Decryption time comparison
|
||||||
|
p2 = figure(title="Decryption Time Comparison", x_axis_label="File Size (MB)",
|
||||||
|
y_axis_label="Time (seconds)", width=400, height=300)
|
||||||
|
p2.line(file_sizes, results['rsa_decrypt'], legend_label="RSA", line_color="red", line_width=2)
|
||||||
|
p2.circle(file_sizes, results['rsa_decrypt'], color="red", size=6)
|
||||||
|
p2.line(file_sizes, results['ecc_decrypt'], legend_label="ECC", line_color="blue", line_width=2)
|
||||||
|
p2.circle(file_sizes, results['ecc_decrypt'], color="blue", size=6)
|
||||||
|
p2.legend.location = "top_left"
|
||||||
|
|
||||||
|
# Key generation comparison
|
||||||
|
p3 = figure(title="Key Generation Time", x_axis_label="Algorithm",
|
||||||
|
y_axis_label="Time (seconds)", width=400, height=300,
|
||||||
|
x_range=["RSA", "ECC"])
|
||||||
|
p3.vbar(x=["RSA", "ECC"], top=[results['rsa_keygen'][0], results['ecc_keygen'][0]],
|
||||||
|
width=0.5, color=["red", "blue"])
|
||||||
|
|
||||||
|
# Key size comparison
|
||||||
|
p4 = figure(title="Key Size Comparison", x_axis_label="Algorithm",
|
||||||
|
y_axis_label="Size (bytes)", width=400, height=300,
|
||||||
|
x_range=["RSA", "ECC"])
|
||||||
|
p4.vbar(x=["RSA", "ECC"], top=[results['rsa_key_size'], results['ecc_key_size']],
|
||||||
|
width=0.5, color=["red", "blue"])
|
||||||
|
|
||||||
|
# Create grid layout
|
||||||
|
grid = gridplot([[p1, p2], [p3, p4]])
|
||||||
|
show(grid)
|
||||||
|
|
||||||
|
|
||||||
|
def print_security_analysis():
|
||||||
|
"""Print security analysis and comparison"""
|
||||||
|
print("\nSecurity Analysis - RSA vs ECC")
|
||||||
|
print("=" * 50)
|
||||||
|
print("RSA (2048-bit):")
|
||||||
|
print(" • Security Level: ~112 bits")
|
||||||
|
print(" • Key Size: Large (2048+ bits)")
|
||||||
|
print(" • Resistance: Integer factorization problem")
|
||||||
|
print(" • Quantum Threat: Vulnerable to Shor's algorithm")
|
||||||
|
print(" • Computational Overhead: High for large keys")
|
||||||
|
print()
|
||||||
|
print("ECC (secp256r1):")
|
||||||
|
print(" • Security Level: ~128 bits")
|
||||||
|
print(" • Key Size: Small (256 bits)")
|
||||||
|
print(" • Resistance: Elliptic curve discrete logarithm problem")
|
||||||
|
print(" • Quantum Threat: Vulnerable to modified Shor's algorithm")
|
||||||
|
print(" • Computational Overhead: Lower than equivalent RSA")
|
||||||
|
print()
|
||||||
|
print("Summary:")
|
||||||
|
print(" • ECC provides equivalent security with smaller keys")
|
||||||
|
print(" • ECC is more efficient for mobile/embedded systems")
|
||||||
|
print(" • RSA is more widely supported and established")
|
||||||
|
print(" • Both require post-quantum alternatives for future security")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function to run the file transfer comparison"""
|
||||||
|
file_sizes = [1, 5, 10] # MB
|
||||||
|
|
||||||
|
print("Secure File Transfer System - RSA vs ECC Comparison")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Measure performance
|
||||||
|
results = measure_performance(file_sizes)
|
||||||
|
|
||||||
|
# Create performance graphs
|
||||||
|
create_performance_graphs(results)
|
||||||
|
|
||||||
|
# Print security analysis
|
||||||
|
print_security_analysis()
|
||||||
|
|
||||||
|
print(f"\nPerformance graphs saved to: file_transfer_performance.html")
|
||||||
|
print("Open the HTML file in your browser to view the interactive graphs.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
39
IS/Lab/Lab3/RSA.py
Normal file
39
IS/Lab/Lab3/RSA.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from Crypto.PublicKey import RSA
|
||||||
|
from Crypto.Cipher import PKCS1_OAEP
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
def rsa_keygen(bits=2048):
|
||||||
|
key = RSA.generate(bits)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def rsa_en(ptext, pub_key):
|
||||||
|
cipher = PKCS1_OAEP.new(pub_key)
|
||||||
|
ctext = cipher.encrypt(ptext.encode('utf-8'))
|
||||||
|
return ctext
|
||||||
|
|
||||||
|
def rsa_de(ctext, priv_key):
|
||||||
|
cipher = PKCS1_OAEP.new(priv_key)
|
||||||
|
decrypted = cipher.decrypt(ctext)
|
||||||
|
return decrypted.decode('utf-8')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to RSA")
|
||||||
|
ptext = input("Enter plaintext: ")
|
||||||
|
|
||||||
|
# RSA key pair
|
||||||
|
key = rsa_keygen()
|
||||||
|
pub_key = key.publickey()
|
||||||
|
priv_key = key
|
||||||
|
|
||||||
|
print("\nPublic Key (n, e):")
|
||||||
|
print("n =", hex(pub_key.n))
|
||||||
|
print("e =", pub_key.e)
|
||||||
|
|
||||||
|
ctext = rsa_en(ptext, pub_key)
|
||||||
|
print("\nYour ciphertext (hex):", binascii.hexlify(ctext).decode())
|
||||||
|
|
||||||
|
decrypted = rsa_de(ctext, priv_key)
|
||||||
|
print("Your decrypted plaintext:", decrypted)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Add table
Add a link
Reference in a new issue