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
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
diff --git a/ES/Lab/Lab3/add128bit.asm b/ES/Lab/Lab3/add128bit.asm
new file mode 100644
index 0000000..6ac4247
--- /dev/null
+++ b/ES/Lab/Lab3/add128bit.asm
@@ -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
\ No newline at end of file
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 a5e45c7..e903caa 100644
--- a/IS/Lab/Lab2/des_vs_aes256.py
+++ b/IS/Lab/Lab2/des_vs_aes256.py
@@ -1,87 +1,176 @@
-from Crypto.Cipher import DES, AES
-from Crypto.Util.Padding import pad, unpad
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 ColumnDataSource
-from bokeh.io import output_file
+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 benchmark_encryption_decryption(cipher_func, data, key):
- # Measure encryption time
- start_time = time.time()
- encrypted = cipher_func(data, key)
- encrypt_time = time.time() - start_time
+def aes_en(ptext, key):
+ cipher = aes_cipher(key)
+ ptext = pad(ptext.encode('utf-8'), AES.block_size)
+ return cipher.encrypt(ptext)
- # Measure decryption time
- start_time = time.time()
- decrypted = cipher_func(encrypted, key, decrypt=True)
- decrypt_time = time.time() - start_time
+def aes_de(ctext, key):
+ cipher = aes_cipher(key)
+ decrypted = cipher.decrypt(ctext)
+ 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):
- cipher = DES.new(key.encode('utf-8'), DES.MODE_ECB)
- if decrypt:
- return unpad(cipher.decrypt(data), DES.block_size).decode('utf-8')
- else:
- padded_data = pad(data.encode('utf-8'), DES.block_size)
- return cipher.encrypt(padded_data)
+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 aes_cipher(data, key, decrypt=False):
- cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB)
- 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 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():
- message = "Performance Testing of Encryption Algorithms"
+ print("AES-256 vs DES Performance Comparison")
+ print("=====================================")
- # Test with different key sizes
- des_key = "12345678" # 8 bytes for DES
- aes_key = "12345678901234567890123456789012" # 32 bytes for AES-256
+ plaintext = input("Enter plaintext: ")
+ key = input("Enter key: ")
+ max_iterations = int(input("Enter maximum number of iterations (default 1000): ") or "1000")
- # Benchmark DES
- des_encrypt_time, des_decrypt_time = benchmark_encryption_decryption(des_cipher, message, des_key)
+ print(f"\nBenchmarking across iteration ranges up to {max_iterations}...")
+ results = benchmark_ciphers(plaintext, key, max_iterations)
- # Benchmark AES-256
- aes_encrypt_time, aes_decrypt_time = benchmark_encryption_decryption(aes_cipher, message, aes_key)
+ # 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 results
- print("Performance Results:")
- print("-" * 40)
- print(f"DES Encryption: {des_encrypt_time:.9f} seconds")
- print(f"DES Decryption: {des_decrypt_time:.9f} seconds")
- print(f"AES-256 Encryption: {aes_encrypt_time:.9f} seconds")
- print(f"AES-256 Decryption: {aes_decrypt_time:.9f} seconds")
+ 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")
- # Create Bokeh visualization
- algorithms = ['DES', 'AES-256']
- encrypt_times = [des_encrypt_time, aes_encrypt_time]
- decrypt_times = [des_decrypt_time, aes_decrypt_time]
-
- # Create the plot
- p = figure(x_range=algorithms, height=400, title="Encryption/Decryption Performance Comparison",
- 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)
+ 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()
\ No newline at end of file
+ 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
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..dcac7e0
--- /dev/null
+++ b/IS/Lab/Lab3/DiffieHellman.py
@@ -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()
\ No newline at end of file
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