added labeval
This commit is contained in:
parent
00c58d5d17
commit
60ebd2b53c
1 changed files with 156 additions and 0 deletions
156
IS/Lab/Eval/test.py
Normal file
156
IS/Lab/Eval/test.py
Normal file
|
@ -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()
|
Loading…
Add table
Add a link
Reference in a new issue