Il cifrario a flusso RC4 fu ideato nel 1987 da Ron Rivest e rimase segreto (per ragioni commerciali) fino al 1997, anno in cui l’algoritmo che ne regola il funzionamento fu inviato al remailer anonimo Cypherpunks. Oggi, tale cifrario, è ampiamente utilizzato nell’ambito di moltissime applicazioni, quali SSL/TLS (per il Web) oppure WEP e WPA (per le reti wi-fi).
Sostanzialmente RC4 effettua tre operazioni:
1) inizializzazione del vettore S;
2) permutazione iniziale di S;
3) generazione del keystream (altrimenti detta generazione del flusso).
Inizializzazione di S (in pseudocodice)
for i = 0 to 255 do S[i] = i; Temp[i] = K[i mod keylen];
Inizialmente tutti gli elementi di S verranno posti uguali alla posizione da essi occupata. Ad esempio:
S[0] = 0, S[1] = 1, S[2] = 2, ... ,S[255] = 255
dove, come si può facilmente notare, S è un vettore di 256 posizioni (da 0 a 255).
Successivamente, se la chiave K data in pasto allo pseudo random byte generator ha dimensione (keylen) pari a 256 byte, essa verrà completamente copiata all’interno del vettore Temp. Invece, nel caso in cui keylen fosse inferiore a 256 byte (poichè RC4 prevede l’uso di chiavi di lunghezza variabile), la chiave K verrà copiata tante volte in Temp fino a riempirlo completamente.
Permutazione iniziale di S (in pseudocodice)
j = 0; for i = 0 to 255 do j = (j + S[i] + T[i]) mod 256; Scambia (S[i], S[j]);
Ad esempio, per i = 0, S[0] = 1 e T[0] = 3 avrò:
j = (0 + S[0] + T[0]) = (0 + 1 + 3) = 4; Scambia (S[0], S[4]); // Scambio il byte in posizione 0 con il byte in posizione 4
Stesso procedimento va fatto per i = 1, i = 2 fino ad i = 255.
A questo punto l’array Temp non mi servirà più, in quanto la chiave era necessaria solo per calcolare la permutazione iniziale di S.
Generazione del keystream (in pseudocodice)
i, j = 0; while (true) //continuo ad effettuare tale operazione fino a quando ho cifrato tutti i byte del plaintext i = (i + 1) mod 256; j = (j + S[i] ) mod 256; Scambia (S[i], S[j]) mod 256; k = S[t]; // k (da non confondere con K) è il byte del keystream che andrò a "xorare" con un byte del plaintext.
Osservazioni
Sia i che j sono variabili a 8 bit (quindi rappresentano un byte). Il massimo valore (in base 10) che può assumere un byte è pari a 256 (8 bit tutti pari a 1). All’interno dello pseudocodice, quindi, l’uso dell’aritmetica modulare si è rivelato necessario, in quanto sia i che j non devono mai assumere valori superiori a 256.
Facciamo un esempio:
j = (38 + S[128] + T[128]) = (38 + 64 + 192 ) = 294;
ma questo numero non è rappresentabile con 8 bit. Quindi calcolo 294 mod 256 che avrà come risultato 38.
Vengono inoltre usati 8 bit per le variabili i e j in quanto il vettore S che le utilizza come indici consta di 256 posizioni (come detto in precedenza).
Per maggiori informazioni relative all’aritmetica modulare vi rimando a questo indirizzo.
Nei prossimi post vedremo come un uso sbagliato di RC4 possa portare a seri problemi legati alla sicurezza. A presto.
sei stato chiarissimo, grazie per questo post! 😉
Figurati 😉