Introducere RC4
RC4 a fost dezvoltat de Ronald Levitt în 1987. Deși numele său oficial este „Rivest Cipher 4”, acronimul RC poate fi înțeles și ca „Codul lui Ron”.
RC4 este o tehnologie foarte populară de criptare a fluxurilor. Deoarece criptarea și decriptarea folosesc aceeași cheie secretă, este un algoritm de criptare simetric. Mai mult, lungimea datelor rămâne neschimbată înainte și după criptarea RC4. Nu există grupare și blocare și nu este nevoie să adăugați octeți. Prin urmare, are mari avantaje în domeniul transmisiei de date.
Vulnerabilități
Implementare pas cu pas
Pentru a explica lucrurile simplu, RC4 se bazează pe acest model pas cu pas:
- Inițializare: introduceți o cheie secretă și textul pe care doriți să îl protejați.
- Criptare: Cifrul vă amestecă textul prin criptare. Procesarea are loc octet cu octet.
- Trimitere: textul dvs. amestecat se îndreaptă către destinatar. Acea persoană ar trebui să aibă o copie a cheii secrete pe care ați folosit-o pentru a proteja datele.
- Decriptare: destinatarul parcurge acești pași pentru a descoperi textul original.
Pentru cei pasionați de matematică, să săpăm puțin mai adânc. RC4 se bazează pe două concepte matematice:
KSA – Key-scheduling algorithm:
Algoritmul de programare a cheilor este utilizat pentru a inițializa permutarea în matricea „S”. „keylength” este definită ca numărul de octeți din cheie și poate fi în intervalul 1 ≤ keylength ≤ 256, de obicei între 5 și 16, corespunzând unei lungimi a cheii de 40-128 de biți. Mai întâi, matricea „S” este inițializată la permutarea identității. S este apoi procesat pentru 256 de iterații într-un mod similar cu PRGA, dar se amestecă și în octeți ai cheii în același timp.
PRGA – Pseudo-random generation algorithm:
Datele sunt alimentate octet cu octet, iar un model matematic le modifică. Modelul caută valori, le adaugă la 256 și folosește suma ca octet în fluxul de chei. Schimbă fiecare element cu altul cel puțin o dată la 256 de runde.
PRGA modifică starea și emite un octet din fluxul de chei pentru un numar necesar de iterații.
În fiecare iterație, PRGA execută:
- incremente i;
- caută al i-lea element al lui S, S[i] și îl adaugă la j;
- schimbă valorile lui S[i] și S[j], apoi folosește suma S[i] + S[j] (modulul 256) ca index pentru a prelua un al treilea element al lui S (valoarea fluxului de cheie K de mai jos);
- apoi OR exclusiv pe biți (XOR) cu următorul octet al mesajului pentru a produce următorul octet fie din text cifrat, fie din text simplu.
- Fiecare element al lui S este schimbat cu un alt element cel puțin o dată la 256 de iterații.
Astfel acest algoritm produce un șir de octeți K[0], K[1], … apoi se aplică operația XOR cu textul de criptat pentru a obține textul criptat.
ciphertext[l] = plaintext[l] ⊕ K[l].
<br />#define KEY_LENGTH 6<br />#define TEXT_LENGTH 10<br /><br />typedef struct RC4_KEY_S{<br /> unsigned char S[256];<br />}RC4_KEY;<br /><br />/*S is initialized to the identity permutation, mixes in bytes of the key.*/<br />void RC4_key(RC4_KEY *rc4_key, unsigned char *key, int *keylength);<br /><br />/*Encrypt the plaintext and output the ciphertext.*/<br />void RC4(RC4_KEY *rc4_key, unsigned char *plaintext, int *plaintext_length, unsigned char *ciphertext);<br /><br />/*S is initialized to the identity permutation, mixes in bytes of the key.*/ <br />void RC4_key(RC4_KEY *rc4_key, unsigned char *key, int *keylength)<br />{ <br /> int i, j, temp; <br /> /*Initialize S*/ <br /> for (i = 0; i < 256; i++) <br /> {<br /> rc4_key -> S[i] = i; <br /> }<br /> <br /> j = 0; <br /> for (i = 0; i < 256; i++)<br /> { <br /> j = (j + rc4_key -> S[i] + *(key + i % *keylength)) % 256; <br /> /*Swap rc4_key -> S[i] and rc4_key -> S[j]*/ <br /> temp = rc4_key -> S[i]; <br /> rc4_key -> S[i] = rc4_key -> S[j]; <br /> rc4_key -> S[j] = temp; <br /> } <br />}<br /><br />/* Generate the key stream which length is the same as plaintext's and encrypt the plaintext and output the ciphertext.*/ <br />void RC4(RC4_KEY *rc4_key, unsigned char *plaintext, int *plaintext_length, unsigned char *ciphertext)<br />{ <br /> int i = 0, j = 0, k = 0, n, temp; <br /> for (k = 0; k < *plaintext_length; k++)<br /> { <br /> i = (i + 1) % 256; <br /> j = (j + rc4_key -> S[i]) % 256; <br /> /*Swap rc4_key -> S[i] and rc4_key -> S[j]*/ <br /> temp = rc4_key -> S[i]; <br /> rc4_key -> S[i] = rc4_key -> S[j]; <br /> rc4_key -> S[j] = temp; n = rc4_key -> S[(rc4_key -> S[i] + rc4_key -> S[j]) % 256]; <br /> /*Encryption*/ <br /> *(ciphertext + k) = *(plaintext + k) ^ n; <br /> } <br />}<br /><br />int Test_RC4() <br />{ <br />int i, x; <br />int *p; <br />unsigned char plaintext[TEXT_LENGTH]; <br />unsigned char key[KEY_LENGTH] = "cipher"; <br />unsigned char ciphertext[TEXT_LENGTH]; <br />RC4_KEY rc4_key; <br />printf("------------------------------n----------RC4 CIPHER----------n------------------------------n"); <br />printf("Please enter the plaintext(%d characters): ", TEXT_LENGTH); <br />for (i = 0; i < TEXT_LENGTH; i++) <br />scanf("%c", &plaintext[i]); <br />/*Encryption*/ <br />x = KEY_LENGTH; <br />p = &x; <br />RC4_key(&rc4_key, &key[0], p); <br />x = TEXT_LENGTH; <br />RC4(&rc4_key, &plaintext[0], p, &ciphertext[0]); <br />printf("The plaintext is: "); <br />for (i = 0; i < TEXT_LENGTH; i++) <br />printf("%x ", plaintext[i]); <br />printf("nThe key is: "); <br />for (i = 0; i < KEY_LENGTH; i++) <br />printf("%x ", key[i]); <br />printf("nThe ciphertext is: "); <br />for (i = 0; i <TEXT_LENGTH; i++) <br />printf("%x ", ciphertext[i]); <br />printf("nn"); <br />return 0; <br />}<br />
- Wiki RC4
- https://programming.vip/docs/rc4-algorithm-c-language-separating-algorithm-from-openssl-library-i.html
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-113.pdf
- https://paginas.fe.up.pt/~ei10109/ca/rc4-vulnerabilities.html
- https://github.com/Maihj/RC4
Pentru întrebari și/sau consultanță tehnică vă stau la dispozitie pe blog sau pe email simedruflorin@automatic-house.ro. O seară/zi plăcută tuturor !