Proviamo a riscrivere il codice creando la nostra logica di crittografia asimmetrica senza usare librerie esterne come RSA o simili, solo una libreria (random) per la generazione di numeri.
Per farlo bisogna usare una funzione particolare, quella di Eulero che restituisce il numero degli interi positivi minori di n che sono coprimi rispetto a n, cioè che non hanno fattori primi comuni con n.
- Per la chiave privata per garantire la sicurezza d deve essere l'inverso moltiplicativo di e modulo φ(n). Significa che d * e ≡ 1 (mod φ(n)).
- Per la chiave pubblica l'esponente e deve essere un numero intero positivo minore di φ(n) e coprimo con φ(n).
Vediamo come funziona il codice, inizialmente la funzione generate_key_pair() genera una coppia di chiavi RSA casuali per Samuele e Marco. In questa funzione si sceglie due numeri primi casuali, si calcola il modulo n e si applica la logica della funzione di Eulero (phi), quindi si genera un esponente pubblico "e" e privato "d". In conclusione restituisce le chiavi pubbliche e private come tuple.
Le funzioni gcd(a, b) e mod_inverse(a, m) vengono usate rispettivamente per calcolare l'mcd tra due numeri e l'inverso modulo indispensabile per la restituzione.
encrypt(message, public_key) prende un messaggio in input e lo cripta usando la chiave pubblica RSA generato in precedenza. Il messaggio viene suddiviso in caratteri e ognuno viene convertito nel suo valore ASCII ed elevato all'esponente (pubblico) e, Infine il risultato è una lista di valori criptati illeggibili.
decrypt(encrypted_msg, private_key) prende un messaggio criptato e lo decripta usando la chiave privata RSA, anche quella generata all'inizio con Eulero. I valori criptati vengono elevati all'esponente privato d, il risultato è una sfilza di valori ASCII che vengono convertiti in caratteri e concatenati per ottenere il messaggio leggibile.
Importante il ciclo while True dove viene eseguito un loop infinito in cui Samuele e Marco possono scambiarsi messaggi.
Riassumendo Samuele invia un messaggio, lo cripta utilizzando la chiave pubblica di Marco, Marco lo decripta utilizzando la sua chiave privata. Poi Marco invia un messaggio lo cripta usando la chiave pubblica di Samuele e Samuele lo decripta utilizzando la sua chiave privata continuando così all'infinito.
import random
def generate_key_pair():
# Funzione di Eulero
prime_numbers = [n for n in range(2, 100) if all(n % i != 0 for i in range(2, int(n**0.5) + 1))]
p = random.choice(prime_numbers)
q = random.choice(prime_numbers)
while p == q:
q = random.choice(prime_numbers)
n = p * q
phi_n = (p - 1) * (q - 1)
e = random.randint(2, phi_n - 1)
while gcd(e, phi_n) != 1:
e = random.randint(2, phi_n - 1)
d = mod_inverse(e, phi_n)
public_key = (n, e)
private_key = (n, d)
return public_key, private_key
def gcd(a, b):
# mcd di due numeri
while b != 0:
a, b = b, a % b
return a
def mod_inverse(a, m):
# Calcola l'inverso modulo di a rispetto a m
if gcd(a, m) != 1:
return None
u1, u2, u3 = 1, 0, a
v1, v2, v3 = 0, 1, m
while v3 != 0:
q = u3 // v3
v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3
return u1 % m
def encrypt(message, public_key):
# Cripta con pubblica RSA
n, e = public_key
encrypted_msg = [pow(ord(c), e, n) for c in message]
return encrypted_msg
def decrypt(encrypted_msg, private_key):
# Decripta privata RSA
n, d = private_key
decrypted_msg = [chr(pow(c, d, n)) for c in encrypted_msg]
return ''.join(decrypted_msg)
# Generazione chiave per utenti...
sam_pub, sam_priv = generate_key_pair()
mar_pub, mar_priv = generate_key_pair()
while True:
sam_msg = input("Samuele: ")
encrypted_msg = encrypt(sam_msg, mar_pub)
print("Samuele ha inviato il seguente messaggio cifrato:", encrypted_msg)
decrypted_msg = decrypt(encrypted_msg, mar_priv)
print("Marco: Ho ricevuto il messaggio decifrato:", decrypted_msg)
mar_msg = input("Marco: ")
encrypted_msg = encrypt(mar_msg, sam_pub)
print("Marco ha inviato il seguente messaggio cifrato:", encrypted_msg)
decrypted_msg = decrypt(encrypted_msg, sam_priv)
print("Samuele: Ho ricevuto il messaggio decifrato:", decrypted_msg)