Implementazione del Cifrario di Cesare e realizzazione di un attacco a forma bruta

Il Cifrario di Cesare è uno dei metodi di crittografia più antichi e semplici, utilizzato dallo stesso Giulio Cesare per proteggere le sue comunicazioni. Questo metodo consiste nel sostituire ogni lettera di un messaggio con un’altra lettera, spostata di un numero fisso di posizioni nell’alfabeto. In questo articolo, esploreremo come implementare questo sistema crittografico in Python e vedremo come attaccarlo con la forza bruta.

Cos’è il Cifrario di Cesare?

Il Cifrario di Cesare è un tipo di cifratura a sostituzione in cui ciascuna lettera del messaggio viene spostata di un numero fisso di posizioni nell’alfabeto. Ad esempio, con una chiave di 3, la lettera “A” diventa “D”, “B” diventa “E”, e così via. Una volta raggiunta la fine dell’alfabeto, si riparte dall’inizio.

Esempio:

  • Testo in chiaro: CIFRA
  • Chiave: 3
  • Testo cifrato: FLIUD

L’alfabeto è semplicemente “ruotato” a seconda della chiave, spostando le lettere verso destra.

L’alfabeto italiano

Per la nostra implementazione useremo l’alfabeto italiano che contiene 21 lettere, escludendo “J”, “K”, “W”, “X” e “Y”. Questo ci permette di utilizzare un alfabeto adatto per testi in lingua italiana.

Ecco l’alfabeto italiano che utilizzeremo:

ABCDEFGHILMNOPQRSTUVZ

Implementazione in Python

Dividiamo l’implementazione in tre moduli principali:

  1. Cifratura e decifratura.
  2. Attacco a forza bruta.
  3. Programma principale.

1. Cifratura e Decifratura

La prima parte riguarda le funzioni di cifratura e decifratura. La cifratura funziona spostando ogni lettera del messaggio di un numero di posizioni determinato dalla chiave. La decifratura è semplicemente l’operazione inversa: si spostano le lettere indietro.

Funzione di cifratura

Nella cifratura, prendiamo il testo, lo convertiamo in maiuscolo e poi, per ogni lettera, la spostiamo in avanti nell’alfabeto del numero di posizioni specificato dalla chiave. Se incontriamo caratteri non alfabetici, come spazi o punteggiatura, li lasciamo inalterati.

ALFABETO_ITALIANO = "ABCDEFGHILMNOPQRSTUVZ"

def cifra_cesare(testo, chiave):
    """
    Funzione che cifra un testo in chiaro usando il Cifrario di Cesare con una chiave data.
    :param testo: Il testo in chiaro da cifrare.
    :param chiave: La chiave di cifratura (numero di posizioni da spostare).
    :return: Il testo cifrato.
    """
    risultato = ""
    testo = testo.upper()  # Convertiamo tutto in maiuscolo per uniformità
    for carattere in testo:
        if carattere in ALFABETO_ITALIANO:
            indice = ALFABETO_ITALIANO.index(carattere)
            nuovo_indice = (indice + chiave) % len(ALFABETO_ITALIANO)
            risultato += ALFABETO_ITALIANO[nuovo_indice]
        else:
            risultato += carattere  # Mantiene i caratteri non alfabetici inalterati
    return risultato

Funzione di decifratura

La decifratura funziona allo stesso modo, ma le lettere vengono spostate all’indietro. Anche qui, i caratteri non alfabetici vengono mantenuti intatti.

def decifra_cesare(testo, chiave):
    """
    Funzione che decifra un testo cifrato usando il Cifrario di Cesare con una chiave data.
    :param testo: Il testo cifrato.
    :param chiave: La chiave usata per la cifratura.
    :return: Il testo in chiaro decifrato.
    """
    risultato = ""
    testo = testo.upper()
    for carattere in testo:
        if carattere in ALFABETO_ITALIANO:
            indice = ALFABETO_ITALIANO.index(carattere)
            nuovo_indice = (indice - chiave) % len(ALFABETO_ITALIANO)
            risultato += ALFABETO_ITALIANO[nuovo_indice]
        else:
            risultato += carattere
    return risultato

2. Attacco a Forza Bruta

Un cifrario di Cesare è facilmente vulnerabile a un attacco a forza bruta, perché ci sono solo 20 chiavi possibili con l’alfabeto italiano (poiché l’alfabeto ha 21 lettere). In un attacco a forza bruta, proviamo ogni possibile chiave e verifichiamo il risultato.

Nel nostro programma, scriveremo una funzione che prova tutte le chiavi possibili e visualizza ogni possibile decifratura. Questo ci permette di scoprire facilmente quale chiave è stata utilizzata per cifrare il messaggio originale.

from cesare import decifra_cesare, ALFABETO_ITALIANO

def attacco_forza_bruta(testo_cifrato):
    """
    Funzione che esegue un attacco a forza bruta su un testo cifrato con il Cifrario di Cesare.
    Prova tutte le chiavi da 1 a 20 e stampa i risultati.
    :param testo_cifrato: Il testo cifrato da decifrare.
    """
    for chiave in range(1, len(ALFABETO_ITALIANO)):
        testo_decifrato = decifra_cesare(testo_cifrato, chiave)
        print(f"Chiave {chiave}: {testo_decifrato}")

3. Programma Principale

Infine, il programma principale richiederà all’utente di inserire un testo e una chiave per cifrare il messaggio. L’utente potrà quindi decidere se eseguire un attacco a forza bruta per tentare di decifrare il messaggio.

from cesare import cifra_cesare, decifra_cesare, ALFABETO_ITALIANO
from attacco import attacco_forza_bruta

def main():
    # Informiamo l'utente che useremo l'alfabeto italiano
    print(f"Alfabeto usato: {ALFABETO_ITALIANO}")

    # Prendi il testo in chiaro dall'utente
    testo_in_chiaro = input("Inserisci il testo da cifrare (usa solo lettere dell'alfabeto italiano): ")
    
    # Prendi la chiave dall'utente
    chiave = int(input(f"Inserisci la chiave di cifratura (numero tra 1 e {len(ALFABETO_ITALIANO) - 1}): "))
    
    # Cifra il testo
    testo_cifrato = cifra_cesare(testo_in_chiaro, chiave)
    print(f"Testo cifrato: {testo_cifrato}")
    
    # Chiedi all'utente se desidera eseguire un attacco a forza bruta
    eseguire_attacco = input("Vuoi eseguire un attacco a forza bruta sul testo cifrato? (s/n): ").lower()
    
    if eseguire_attacco == 's':
        print("Risultati dell'attacco a forza bruta:")
        attacco_forza_bruta(testo_cifrato)

if __name__ == "__main__":
    main()

Attacco a Forza Bruta

Immaginiamo di aver ricevuto un messaggio cifrato con il Cifrario di Cesare ma senza conoscere la chiave. Un attacco a forza bruta ci permette di provare tutte le chiavi possibili per scoprire il testo originale. Questa tecnica è utile quando si sa che un messaggio è stato cifrato con un metodo semplice come il Cifrario di Cesare.

Esempio di Attacco

Supponiamo che il messaggio cifrato sia FLIUD. Non conoscendo la chiave, possiamo eseguire un attacco a forza bruta che prova tutte le chiavi possibili, da 1 a 20, e ci restituisce vari tentativi di decifratura.

Risultati dell’attacco:

Chiave 1: EHHTC
Chiave 2: DGGSB
Chiave 3: CFFRA
Chiave 4: BEEQZ
Chiave 5: ADDPY
...

Osservando i risultati, possiamo identificare facilmente il messaggio corretto, che in questo caso sarà CIFRA con la chiave 3.

Considerazioni sulla Sicurezza

Sebbene il Cifrario di Cesare sia affascinante per la sua semplicità storica, è estremamente insicuro per qualsiasi utilizzo pratico. Con solo 20 possibili chiavi, un attacco a forza bruta è molto semplice e veloce da eseguire. Per crittografie moderne si utilizzano metodi molto più sofisticati, come l’algoritmo AES (Advanced Encryption Standard), che rendono la decifratura senza la chiave praticamente impossibile.

Conclusione

Il Cifrario di Cesare è un eccellente punto di partenza per chiunque sia interessato alla crittografia. Sebbene non sia sicuro per applicazioni reali, è un metodo storico interessante che ci permette di comprendere i concetti fondamentali della cifratura e della decifratura.

Se sei interessato a vedere il codice completo che abbiamo usato per implementare il Cifrario di Cesare in Python, puoi trovarlo al link seguente:

Vedi il codice completo del progetto

Con questo articolo, spero di averti dato una buona panoramica del funzionamento del Cifrario di Cesare e di come possiamo implementarlo e attaccarlo usando Python. Se hai domande o suggerimenti, lascia un commento qui sotto!

Foto di Zanyar Ibrahim su Unsplash