Modified Lab 2 IS
This commit is contained in:
parent
a1b2495e47
commit
47d2a871e9
4 changed files with 482 additions and 21 deletions
|
@ -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):
|
||||
n = len(text) % 8
|
||||
return text + (b' ' * n)
|
||||
def pad_key(key, length):
|
||||
return key.ljust(length)[:length].encode('utf-8')
|
||||
|
||||
def des_128(ptext, key):
|
||||
cipher=DES.new(key, DES.MODE_ECB)
|
||||
def encrypt_with_timing(cipher_func, ptext, key, *args):
|
||||
# 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_192(ptext, key):
|
||||
def aes_256(ptext, key):
|
||||
def aes_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
|
||||
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():
|
||||
print("The AES/DES Encryptor")
|
||||
ptext = input("Enter plaintext: ")
|
||||
key = b'input("Enter key: ")'
|
||||
print("DES 128 Bit Cyphertext: ", des_128(ptext, key))
|
||||
print("DES 192 Bit Cyphertext: ", des_192(ptext, key))
|
||||
print("DES 256 Bit Cyphertext: ", des_256(ptext, key))
|
||||
print("AES 128 Bit Cyphertext: ", aes_128(ptext, key))
|
||||
print("AES 192 Bit Cyphertext: ", aes_192(ptext, key))
|
||||
print("AES 256 Bit Cyphertext: ", aes_256(ptext, key))
|
||||
print("The AES/DES Encryptor with Performance Analysis")
|
||||
|
||||
# Get exactly 5 messages from user
|
||||
messages = []
|
||||
print("\nEnter exactly 5 messages to encrypt:")
|
||||
for i in range(5):
|
||||
while True:
|
||||
message = input(f"Message {i+1}: ")
|
||||
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__':
|
||||
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
|
@ -0,0 +1,176 @@
|
|||
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.models import HoverTool
|
||||
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 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 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_en(ptext, key):
|
||||
cipher = des_cipher(key)
|
||||
ptext = pad(ptext.encode('utf-8'), DES.block_size)
|
||||
return cipher.encrypt(ptext)
|
||||
|
||||
def des_de(ctext, key):
|
||||
cipher = des_cipher(key)
|
||||
decrypted = cipher.decrypt(ctext)
|
||||
return unpad(decrypted, DES.block_size).decode('utf-8')
|
||||
|
||||
def des_pad_key(key):
|
||||
return key.ljust(8)[:8]
|
||||
|
||||
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():
|
||||
print("AES-256 vs DES Performance Comparison")
|
||||
print("=====================================")
|
||||
|
||||
plaintext = input("Enter plaintext: ")
|
||||
key = input("Enter key: ")
|
||||
max_iterations = int(input("Enter maximum number of iterations (default 1000): ") or "1000")
|
||||
|
||||
print(f"\nBenchmarking across iteration ranges up to {max_iterations}...")
|
||||
results = benchmark_ciphers(plaintext, key, max_iterations)
|
||||
|
||||
# Calculate average times for comparison
|
||||
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("\nAverage Results (time per operation):")
|
||||
print(f"AES-256 Encryption: {avg_aes_enc:.8f} seconds")
|
||||
print(f"DES Encryption: {avg_des_enc:.8f} seconds")
|
||||
print(f"AES-256 Decryption: {avg_aes_dec:.8f} seconds")
|
||||
print(f"DES Decryption: {avg_des_dec:.8f} seconds")
|
||||
|
||||
print("\nSpeed comparison:")
|
||||
if avg_aes_enc < avg_des_enc:
|
||||
ratio = avg_des_enc / avg_aes_enc
|
||||
print(f"AES-256 encryption is {ratio:.2f}x faster than DES")
|
||||
else:
|
||||
ratio = avg_aes_enc / avg_des_enc
|
||||
print(f"DES encryption is {ratio:.2f}x faster than AES-256")
|
||||
|
||||
plot_results(results, len(plaintext))
|
||||
|
||||
if __name__ == '__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
Loading…
Add table
Add a link
Reference in a new issue