From 60ebd2b53c60ab1d307aeb2b7fa02f78d29876b3 Mon Sep 17 00:00:00 2001 From: Student Date: Tue, 2 Sep 2025 09:24:32 +0530 Subject: [PATCH] added labeval --- IS/Lab/Eval/test.py | 156 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 IS/Lab/Eval/test.py diff --git a/IS/Lab/Eval/test.py b/IS/Lab/Eval/test.py new file mode 100644 index 0000000..e747ffc --- /dev/null +++ b/IS/Lab/Eval/test.py @@ -0,0 +1,156 @@ +from functools import partial +import time +import numpy as np +import string +import matplotlib.pyplot as plt +from Crypto.PublicKey import RSA +from Crypto.Cipher import AES, PKCS1_OAEP +from Crypto.Util.Padding import pad, unpad +from Crypto.Random import get_random_bytes +from sympy import Matrix # only for the 2×2 Hill inverse + + +# 1. Hill-Cipher utilities (2×2 matrix [[3,3],[2,5]]) + +hillkey = np.array([[3, 3], + [2, 5]], dtype=int) +ALPH = string.ascii_uppercase +m_len = 2 # block size + +def clean(txt): + return ''.join(ch.upper() for ch in txt if ch.isalpha()) + +def hill_encrypt(pt, key=hillkey): + pt = clean(pt) + if len(pt) % m_len: # padding + pt += 'X' * (m_len - len(pt) % m_len) + cipher = [] + for i in range(0, len(pt), m_len): + block = np.array([ALPH.index(ch) for ch in pt[i:i+m_len]]) + cipher.extend((key @ block) % 26) + return ''.join(ALPH[i] for i in cipher) + +def hill_decrypt(ct, key=hillkey): + # modular inverse of the matrix + M = Matrix(key) + detinv = pow(int(M.det()) % 26, -1, 26) + adj = M.adjugate() + inv_key = (detinv * adj) % 26 + inv_key = np.array(inv_key).astype(int) + + plain = [] + for i in range(0, len(ct), m_len): + block = np.array([ALPH.index(ch) for ch in ct[i:i+m_len]]) + plain.extend((inv_key @ block) % 26) + return ''.join(ALPH[i] for i in plain) + +# Generic timing wrapper +def timed(fn, *a, **kw): + t0 = time.perf_counter() + for _ in range(100_000): # 100 000 loops → 1 000 000 calls + fn(*a, **kw) + delta = time.perf_counter() - t0 + return delta + +# Menu +def menu(): + while True: + print("\n===== Cryptographic Demo =====") + print("1. Hill-cipher demo") + print("2. RSA + envelope (share AES)") + print("3. AES-128 encrypt / decrypt") + print("4. Speed graph (100k it loops)") + print("0. Quit") + ch = input("Select >> ").strip() + if ch == '0': break + elif ch == '1': hill_demo() + elif ch == '2': rsa_env_demo() + elif ch == '3': aes_demo() + elif ch == '4': speed_graph() + else: print("Invalid choice") + +# 1. Hill demo +def hill_demo(): + msg = 'The key is hidden under the mattress' + print("\n------- 1. Hill-Cipher Demo -------") + print("Key matrix:\n", hillkey) + ct = hill_encrypt(msg) + print("Cipher :", ct) + pt = hill_decrypt(ct) + print("Plain :", pt) # uppercase / padded – expected + +# 2. RSA Envelope demo +AES_KEY = b"0123456789ABCDEF" # 16-byte AES-128 key (truncated from prompt) + +def rsa_env_demo(): + print("\n------- 2. RSA × AES envelope Demo -------") + # generate RSA pairs + encoder_priv = RSA.generate(2048) + encoder_pub = encoder_priv.publickey() + + decoder_priv = RSA.generate(2048) # strictly not needed, but shown + decoder_pub = decoder_priv.publickey() + + # Use encoder_pub to encrypt the shared AES key + cipher_rsa = PKCS1_OAEP.new(encoder_pub) + enc_key = cipher_rsa.encrypt(AES_KEY) + + # Show keys + print("Encoder public key (PEM):\n", encoder_pub.export_key().decode()) + print("Encoder private key (PEM):\n", encoder_priv.export_key().decode()) + print("Encrypted AES key (hex):", enc_key.hex()) + + # Decrypt back using encoder’s private key + dec_rsa = PKCS1_OAEP.new(encoder_priv) + dec_key = dec_rsa.decrypt(enc_key) + print("Decrypted AES key :", dec_key.hex(), " match=", dec_key==AES_KEY) + +# 3. AES-128 +def aes_demo(): + msg = input("Enter AES plaintext:") + print("\n------- 3. AES-128 Demo -------") + cipher = AES.new(AES_KEY, AES.MODE_CBC) # random IV + ct = cipher.encrypt(pad(msg.encode(), AES.block_size)) + print("Raw key :", AES_KEY.hex()) + print("Ciphertext (incl. IV) :", cipher.iv.hex() + ct.hex()) + decipher = AES.new(AES_KEY, AES.MODE_CBC, cipher.iv) + pt = unpad(decipher.decrypt(ct), AES.block_size).decode() + print("Recovered plaintext :", pt) + +# 4. Speed test +def speed_graph(): + print("\n------- Benchmark (100 000 loops = 1 Mio calls) -------") + # prepare one big dummy block for AES + aes_cipher = AES.new(AES_KEY, AES.MODE_ECB) + dummy_aes = b"A" * 16 + + # RSA encryption of AES key just once + pub_key = RSA.generate(2048).publickey() + rsa_cipher = PKCS1_OAEP.new(pub_key) + dummy_rsa = AES_KEY + + # Hill needs string + hill_string = "HELLOWORLD" + hill_ct = hill_encrypt(hill_string) # pre-compute to keep test same + + # timing + t_hill = timed(hill_encrypt, hill_string) + t_rsa = timed(rsa_cipher.encrypt, dummy_rsa) + t_aes = timed(aes_cipher.encrypt, dummy_aes) + + methods = ['Hill-cipher\n(str encrypt)', 'RSA-OAEP\n(key wrap)', 'AES-128\n(block)'] + timings = [t_hill, t_rsa, t_aes] + for name,val in zip(methods,timings): + print(f"{name:25s} : {val:9.4f} s (100 000 loops)") + + plt.bar(methods, timings, color=['gold','coral','dodgerblue']) + plt.ylabel("Time (s) for 100 000 iterations") + plt.title("Relative speed among 3 algorithms") + plt.tight_layout() + plt.show() + +############################################################## +# main +############################################################## +if __name__ == "__main__": + menu()