From 47d2a871e92d2600ea85d5c74c64ab5b552e88a1 Mon Sep 17 00:00:00 2001 From: sherlock Date: Wed, 6 Aug 2025 00:19:31 +0530 Subject: [PATCH 1/8] Modified Lab 2 IS --- IS/Lab/Lab2/aes_des_bit.py | 205 +++++++++++++++++++++--- IS/Lab/Lab2/des_vs_aes256.html | 61 +++++++ IS/Lab/Lab2/des_vs_aes256.py | 176 ++++++++++++++++++++ IS/Lab/Lab2/encryption_performance.html | 61 +++++++ 4 files changed, 482 insertions(+), 21 deletions(-) create mode 100644 IS/Lab/Lab2/des_vs_aes256.html create mode 100644 IS/Lab/Lab2/encryption_performance.html diff --git a/IS/Lab/Lab2/aes_des_bit.py b/IS/Lab/Lab2/aes_des_bit.py index 102768f..f176d95 100644 --- a/IS/Lab/Lab2/aes_des_bit.py +++ b/IS/Lab/Lab2/aes_des_bit.py @@ -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() diff --git a/IS/Lab/Lab2/des_vs_aes256.html b/IS/Lab/Lab2/des_vs_aes256.html new file mode 100644 index 0000000..6946309 --- /dev/null +++ b/IS/Lab/Lab2/des_vs_aes256.html @@ -0,0 +1,61 @@ + + + + + Bokeh Plot + + + + + +
+ + + + + \ No newline at end of file diff --git a/IS/Lab/Lab2/des_vs_aes256.py b/IS/Lab/Lab2/des_vs_aes256.py index e69de29..e903caa 100644 --- a/IS/Lab/Lab2/des_vs_aes256.py +++ b/IS/Lab/Lab2/des_vs_aes256.py @@ -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() diff --git a/IS/Lab/Lab2/encryption_performance.html b/IS/Lab/Lab2/encryption_performance.html new file mode 100644 index 0000000..fee1247 --- /dev/null +++ b/IS/Lab/Lab2/encryption_performance.html @@ -0,0 +1,61 @@ + + + + + Bokeh Plot + + + + + +
+ + + + + \ No newline at end of file From b43a1d33604e017867ebb68a852db7b34eeefd31 Mon Sep 17 00:00:00 2001 From: aadit Date: Thu, 7 Aug 2025 11:48:42 +0530 Subject: [PATCH 2/8] Add ES/Lab/Lab2/array_reversal.asm --- ES/Lab/Lab2/array_reversal.asm | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 ES/Lab/Lab2/array_reversal.asm diff --git a/ES/Lab/Lab2/array_reversal.asm b/ES/Lab/Lab2/array_reversal.asm new file mode 100644 index 0000000..94337b6 --- /dev/null +++ b/ES/Lab/Lab2/array_reversal.asm @@ -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 \ No newline at end of file From 0b57ac833fe19d4441c5f45579a954642db3deeb Mon Sep 17 00:00:00 2001 From: aadit Date: Thu, 7 Aug 2025 12:04:24 +0530 Subject: [PATCH 3/8] Add ES/Lab/Lab3/ADDER.asm --- ES/Lab/Lab3/ADDER.asm | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 ES/Lab/Lab3/ADDER.asm diff --git a/ES/Lab/Lab3/ADDER.asm b/ES/Lab/Lab3/ADDER.asm new file mode 100644 index 0000000..abd58e3 --- /dev/null +++ b/ES/Lab/Lab3/ADDER.asm @@ -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 \ No newline at end of file From e73f664627427f313cd105bc58190f5c0bbdbffc Mon Sep 17 00:00:00 2001 From: aadit Date: Thu, 7 Aug 2025 12:21:11 +0530 Subject: [PATCH 4/8] Add ES/Lab/Lab3/add128bit.asm --- ES/Lab/Lab3/add128bit.asm | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 ES/Lab/Lab3/add128bit.asm diff --git a/ES/Lab/Lab3/add128bit.asm b/ES/Lab/Lab3/add128bit.asm new file mode 100644 index 0000000..38cce39 --- /dev/null +++ b/ES/Lab/Lab3/add128bit.asm @@ -0,0 +1,45 @@ + 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, R1 + TEQ R3, #0 + BNE UP; + + LDR R4, =Result + STR R2, [R4], #4 + STR R5, [R4] + + +STOP + B STOP + ALIGN + +N1 DCD 0x10002000, 0x30004000, 0x50006000, 0x70008000 +N2 DCD 0x10002000, 0x30004000, 0x50006000, 0x70008000 + + AREA mydata, DATA, READWRITE + + +Result DCD 0 + + END \ No newline at end of file From 951bf4024a2a46733588ba794b662352dcfba2a2 Mon Sep 17 00:00:00 2001 From: aadit Date: Thu, 7 Aug 2025 12:38:58 +0530 Subject: [PATCH 5/8] Update ES/Lab/Lab3/add128bit.asm --- ES/Lab/Lab3/add128bit.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ES/Lab/Lab3/add128bit.asm b/ES/Lab/Lab3/add128bit.asm index 38cce39..0013637 100644 --- a/ES/Lab/Lab3/add128bit.asm +++ b/ES/Lab/Lab3/add128bit.asm @@ -21,7 +21,7 @@ UP LDR R4, [R1], #4 LDR R5, [R2], #4 ADCS R6, R5, R4 - SUB R3, R1 + SUB R3, #1 TEQ R3, #0 BNE UP; From a8ced71b76eea414d5c123695f88580b8f3dc134 Mon Sep 17 00:00:00 2001 From: aadit Date: Thu, 7 Aug 2025 12:50:55 +0530 Subject: [PATCH 6/8] Update ES/Lab/Lab3/add128bit.asm --- ES/Lab/Lab3/add128bit.asm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ES/Lab/Lab3/add128bit.asm b/ES/Lab/Lab3/add128bit.asm index 0013637..6ac4247 100644 --- a/ES/Lab/Lab3/add128bit.asm +++ b/ES/Lab/Lab3/add128bit.asm @@ -25,10 +25,9 @@ UP TEQ R3, #0 BNE UP; - LDR R4, =Result - STR R2, [R4], #4 - STR R5, [R4] - + LDR R8, =Result + STR R2, [R8], #4 + STR R5, [R8] STOP B STOP From 4cab136b7a1e74db0b2c361bfe5005ca32a2ec27 Mon Sep 17 00:00:00 2001 From: sherlock Date: Tue, 12 Aug 2025 02:15:01 +0530 Subject: [PATCH 7/8] Added Lab2/Lab3 IS --- IS/Lab/Lab2/multiround_aes_192 | 61 +++++++ IS/Lab/Lab3/DiffieHellman.py | 122 ++++++++++++++ IS/Lab/Lab3/ECC.py | 58 +++++++ IS/Lab/Lab3/ElGamal.py | 57 +++++++ IS/Lab/Lab3/FileTransfer.py | 299 +++++++++++++++++++++++++++++++++ IS/Lab/Lab3/RSA.py | 39 +++++ 6 files changed, 636 insertions(+) create mode 100644 IS/Lab/Lab2/multiround_aes_192 create mode 100644 IS/Lab/Lab3/DiffieHellman.py create mode 100644 IS/Lab/Lab3/ECC.py create mode 100644 IS/Lab/Lab3/ElGamal.py create mode 100644 IS/Lab/Lab3/FileTransfer.py create mode 100644 IS/Lab/Lab3/RSA.py diff --git a/IS/Lab/Lab2/multiround_aes_192 b/IS/Lab/Lab2/multiround_aes_192 new file mode 100644 index 0000000..858cea9 --- /dev/null +++ b/IS/Lab/Lab2/multiround_aes_192 @@ -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() \ No newline at end of file diff --git a/IS/Lab/Lab3/DiffieHellman.py b/IS/Lab/Lab3/DiffieHellman.py new file mode 100644 index 0000000..eb1e9fc --- /dev/null +++ b/IS/Lab/Lab3/DiffieHellman.py @@ -0,0 +1,122 @@ +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() + + diff --git a/IS/Lab/Lab3/ECC.py b/IS/Lab/Lab3/ECC.py new file mode 100644 index 0000000..f85fb9d --- /dev/null +++ b/IS/Lab/Lab3/ECC.py @@ -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() \ No newline at end of file diff --git a/IS/Lab/Lab3/ElGamal.py b/IS/Lab/Lab3/ElGamal.py new file mode 100644 index 0000000..074a5b3 --- /dev/null +++ b/IS/Lab/Lab3/ElGamal.py @@ -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() \ No newline at end of file diff --git a/IS/Lab/Lab3/FileTransfer.py b/IS/Lab/Lab3/FileTransfer.py new file mode 100644 index 0000000..d8a5bbd --- /dev/null +++ b/IS/Lab/Lab3/FileTransfer.py @@ -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() diff --git a/IS/Lab/Lab3/RSA.py b/IS/Lab/Lab3/RSA.py new file mode 100644 index 0000000..c3fd98d --- /dev/null +++ b/IS/Lab/Lab3/RSA.py @@ -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() \ No newline at end of file From 011d5aded19f75e9d3ae3f5f4cd7ee81383ab723 Mon Sep 17 00:00:00 2001 From: sherlock Date: Tue, 12 Aug 2025 02:15:20 +0530 Subject: [PATCH 8/8] Added Lab2/Lab3 IS --- IS/Lab/Lab3/DiffieHellman.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/IS/Lab/Lab3/DiffieHellman.py b/IS/Lab/Lab3/DiffieHellman.py index eb1e9fc..dcac7e0 100644 --- a/IS/Lab/Lab3/DiffieHellman.py +++ b/IS/Lab/Lab3/DiffieHellman.py @@ -117,6 +117,4 @@ def main(): if __name__ == "__main__": - main() - - + main() \ No newline at end of file