Criptografie (2) - Algoritmul RC4

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 

RC4 este deosebit de vulnerabil atunci când începutul fluxului de chei de ieșire nu este eliminat. RC4-dropN, fiind N un multiplu de 256 este o îmbunătățire pentru a rezolva această problemă. De asemenea, este vulnerabil atunci când sunt utilizate chei non-aleatoare sau asociate, deoarece poate duce la un sistem foarte nesigur, cum ar fi WEP. 

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].

 

Cod de test (sursele)


#define KEY_LENGTH 6
#define TEXT_LENGTH 10

typedef struct RC4_KEY_S{
    unsigned char S[256];
}RC4_KEY;

/*S is initialized to the identity permutation, mixes in bytes of the key.*/
void RC4_key(RC4_KEY *rc4_key, unsigned char *key, int *keylength);

/*Encrypt the plaintext and output the ciphertext.*/
void RC4(RC4_KEY *rc4_key, unsigned char *plaintext, int *plaintext_length, unsigned char *ciphertext);

/*S is initialized to the identity permutation, mixes in bytes of the key.*/ 
void RC4_key(RC4_KEY *rc4_key, unsigned char *key, int *keylength)
{ 
  int i, j, temp; 
  /*Initialize S*/ 
  for (i = 0; i < 256; i++) 
  {
    rc4_key -> S[i] = i; 
  }
  
  j = 0; 
  for (i = 0; i < 256; i++)
  { 
    j = (j + rc4_key -> S[i] + *(key + i % *keylength)) % 256; 
    /*Swap rc4_key -> S[i] and rc4_key -> S[j]*/ 
    temp = rc4_key -> S[i]; 
    rc4_key -> S[i] = rc4_key -> S[j]; 
    rc4_key -> S[j] = temp; 
  } 
}

/* Generate the key stream which length is the same as plaintext's and encrypt the plaintext and output the ciphertext.*/ 
void RC4(RC4_KEY *rc4_key, unsigned char *plaintext, int *plaintext_length, unsigned char *ciphertext)
{ 
  int i = 0, j = 0, k = 0, n, temp; 
  for (k = 0; k < *plaintext_length; k++)
  { 
    i = (i + 1) % 256; 
    j = (j + rc4_key -> S[i]) % 256; 
    /*Swap rc4_key -> S[i] and rc4_key -> S[j]*/ 
    temp = rc4_key -> S[i]; 
    rc4_key -> S[i] = rc4_key -> S[j]; 
    rc4_key -> S[j] = temp; n = rc4_key -> S[(rc4_key -> S[i] + rc4_key -> S[j]) % 256]; 
    /*Encryption*/ 
    *(ciphertext + k) = *(plaintext + k) ^ n; 
  } 
}

int Test_RC4() 
{ 
int i, x; 
int *p; 
unsigned char plaintext[TEXT_LENGTH]; 
unsigned char key[KEY_LENGTH] = "cipher"; 
unsigned char ciphertext[TEXT_LENGTH]; 
RC4_KEY rc4_key; 
printf("------------------------------\n----------RC4 CIPHER----------\n------------------------------\n"); 
printf("Please enter the plaintext(%d characters): ", TEXT_LENGTH); 
for (i = 0; i < TEXT_LENGTH; i++) 
scanf("%c", &plaintext[i]); 
/*Encryption*/ 
x = KEY_LENGTH; 
p = &x; 
RC4_key(&rc4_key, &key[0], p); 
x = TEXT_LENGTH; 
RC4(&rc4_key, &plaintext[0], p, &ciphertext[0]); 
printf("The plaintext is: "); 
for (i = 0; i < TEXT_LENGTH; i++) 
printf("%x ", plaintext[i]); 
printf("\nThe key is: "); 
for (i = 0; i < KEY_LENGTH; i++) 
printf("%x ", key[i]); 
printf("\nThe ciphertext is: "); 
for (i = 0; i <TEXT_LENGTH; i++) 
printf("%x ", ciphertext[i]); 
printf("\n\n"); 
return 0; 
}

Etichete

Afișați mai multe

Arhiva

Afișați mai multe