Memo pentru crearea unui canal de comunicare securizat, note ale programatorului

1. Afirmația problemei

Există utilizatori A și B, care schimbă mesaje. Ei pot folosi protocolul TCP, UDP, email sau chat - acum nu contează. Există E atacator care poate intercepta, înlocui și rearanja aceste mesaje, le face să dispară fără urmă, și a trimite mesaje în numele A și B. Sarcina - pentru a ajuta la A și schimb de mesaje B într-un mod care E nu a putut găsi conținutul lor. Nu poți scăpa de E în nici un fel.







2. Criptarea datelor

Ca algoritm de criptare, Schneier și Ferguson recomandă utilizarea AES (Rijndael cu o dimensiune de bloc de 128 de biți) cu o lungime de cheie de 256 de biți în modul CTR. În acest mod, dimensiunea maximă a unui singur mesaj este de 16,22 octeți. Este puțin probabil ca cineva să fie constrâns de această restricție. În cazuri extreme, puteți rupe mesajul în părți.

Pentru a cripta un mesaj cu un număr i având o mărime de biți L, este necesar să se calculeze biții L în modul următor:

unde funcția EK (128 biți la ieșire) - algoritmul de criptare, K (256 biți) - cheia de criptare, argumentul funcției (128 biți) - datele criptate și operatorul || înseamnă concatenarea datelor. După calculul biților b1 ... bL le adăugăm prin Zhegalkin (exclusiv OR, operația XOR, ⊕) cu biții mesajului, rezultând textul criptat. Pentru decriptare, trebuie să faceți exact aceeași succesiune de acțiuni pe textul cifrat.

Aici este important să se acorde atenție la două puncte. În primul rând, cheile de criptare pentru trimiterea datelor de la A la B și de la B la A trebuie să fie diferite. În al doilea rând, este necesar să se potrivească secvența de octeți în argumentul funcției EK. Ordinea octeților în numere pe 32 de biți poate varia în funcție de arhitectura procesorului utilizat. În mod tradițional, protocoalele de rețea și formatele de fișiere utilizează ordinul de octeți de la cei mai în vârstă până la cei mai tineri.

3. Funcția Hash

Să presupunem că am instalat cu succes o cheie de sesiune folosind algoritmul Diffie-Hellman. Ca urmare, A și B au primit o cheie comună K. Apoi se efectuează următoarea secvență de acțiuni:

// Scapa de structura algebrică a cheii
K = SHAd-256 (K)
// Construiți 4 chei pentru copii:
// 1. Criptarea de la A la B
key_send_enc = SHAd -256 (K || "Enc de la A la B")
// 2. Criptarea de la B la A
key_recv_enc = SHAd -256 (K || "Enc de la B la A")
3. Autentificarea de la A la B
key_send_auth = SHAd -256 (K || "Auth de la A la B")
// 4. Autentificarea de la B la A
key_recv_auth = SHAd -256 (K || "Auth de la B la A")

4. Codurile de autentificare a mesajelor

Fiecare mesaj trebuie să fie însoțit de o imitație (MAC). În funcție de MAC, Schneier și Ferguson recomandă utilizarea HMAC-SHA-256:

Aici, ai este codul de autentificare pentru mesajul i. HMACK (m) este o funcție hash a cărei valoare depinde nu numai de mesajul m, dar și de tasta K. Ca și în cazul criptării, MAC ar trebui să utilizeze două chei independente pentru A și B. Așa cum am menționat deja, ⊕ - este o operație de biți exclusive OR (este XOR).

În criptografia practică, există un accent deosebit pe importanța autentificării nu numai a mesajelor mi. care este secvența uzuală de octeți, dar și semnificația ei. Să presupunem că mi = a || b || c, adică se compune din mai multe câmpuri cu o anumită lungime. Să ne imaginăm că, după următoarea actualizare a protocolului, dimensiunile câmpurilor s-au schimbat. Apoi, dacă atacatorul E poate înlocui versiunea protocolului, mesajul nu va fi interpretat corect. Mai mult, nu contează cum un atacator va reuși să facă acest lucru - securitatea unei părți a sistemului nu ar trebui să depindă de siguranța celorlalți.







De aceea avem nevoie de mai multe informații xi. inclusiv id-ul protocolului (semnătură, IP: portul receptorului și expeditor), versiunea protocolului, id-ul mesajului, dimensiunea și numele câmpurilor mesajelor. Mai mult, informația xi trebuie codificată astfel încât să poată fi decodificată în mod unic. L (xi) în formula noastră este evident lungimea lui xi. Din fericire, toate aceste hemoroizii pot fi evitate pur și simplu prin trimiterea de mesaje într-un format de date asemănător XML, adică în cazul în care informații suplimentare despre semnificația mesajului sunt deja incluse în mesajul însuși. Aici este important să nu uitați să includeți în fiecare mesaj toate informațiile suplimentare enumerate mai sus.

Ce altceva ar trebui să știu despre MAC?

  • Puteți reduce valoarea HMAC-SHA-256 la 16 octeți. A face acest lucru nu este de dorit, dar această soluție este mai bună decât utilizarea HMAC-MD5 pentru a reduce cantitatea de date transferate.
  • Se recomandă să calculați mai întâi MAC-ul, apoi să criptați mesajul împreună cu MAC-ul. și nu invers.

5. Descrierea mesageriei

Presupunem că utilizatorii A și B au negociat deja cheia sesiunii și au calculat cheile copilului, așa cum este descris în pasul 3.

Important! Pentru fiecare sesiune nouă, trebuie să generați noi chei de criptare și autentificare.

Acordul cheilor merită scrierea unui post separat, dacă nu doi, așa că acum nu îl considerăm.

Acum, mesajele A și B fac schimb de mesaje într-un format similar cu XML (sau urmați instrucțiunile furnizate pentru o situație diferită, consultați pasul 4). Fiecare mesaj are un număr unic de 32 de biți. Numerotarea mesajelor începe cu o unitate - este mai ușor să urmăriți momentul în care se termină numerele. Când se întâmplă acest lucru, trebuie să reconciliați cheile. Puteți utiliza numere de mesaje pe 64 de biți, dar fiecare mesaj va fi de 4 octeți mai lung. În plus, din când în când, este necesar să actualizați cheile, astfel încât 32 de biți sunt doar corecte.

Dacă protocolul UDP este utilizat pentru transmisia de date, mesajul trebuie retransmis pentru un anumit interval de timp în cazul în care cealaltă parte nu răspunde la acesta. Atunci când utilizați TCP acest lucru nu este necesar - stratul de transport are grijă de livrarea garantată a pachetelor. Un atacator E poate întrerupe o sesiune de comunicare între A și B prin coruperea unuia dintre mesaje sau prin rearanjarea câtorva mesaje în locații. Dar din moment ce avem un "om în mijloc", el poate în orice caz să rupă legătura dintre A și B. De aici concluzia:

Nu pierde timpul să scrieți "TCP" dvs. pe un alt protocol - folosiți doar protocolul TCP. Desigur, în aplicația dvs. acest lucru este posibil.

Când utilizatorul A dorește să trimită un mesaj mi. aceasta calculează MAC-ul acestui mesaj ai în conformitate cu pasul 4. Apoi criptează mesajul mi || ai. așa cum este descris în pasul 2 și trimite utilizatorului B următoarele: i || m'i || a'i. După aceasta, A mărește valoarea contorului mesajelor trimise de unul.

Când utilizatorul B primește i || m'i || a'i. decriptează mi și aia. Verifică codul de autentificare. Mesajele cu MAC incorect sunt ignorate (acestea ar putea fi trimise de către atacatorul E). Apoi se verifică valoarea i - dacă este mai mică decât numărul așteptat al mesajului, pentru claritate îl numim j, mesajul este eliminat. În caz contrar (i> = j) se atribuie valoarea j i + 1 și se procesează mesajul mi.

Există mai multe puncte aici, care ar trebui subliniate. În primul rând, după cum se menționează la punctul 2, numerele de mesaje trebuie transmise în ordine de octeți, de la cel mai vechi la cel mai mic. În al doilea rând, verificarea numărului de mesaj ar putea fi efectuată și înainte de decodificare. Dar, în acest caz, în cazul în care un mesaj cu un număr nevalid un atacator trimite E este găsit (și apoi înregistrate în jurnal), eroarea „numărul mesajului greșit“, atunci când, de fapt, a apărut o eroare „mesaj incorect codul de autentificare.“ Criptografii sunt în primul rând preocupați de securitatea și buna funcționare a aplicațiilor, nu de performanță. Unii programatori au ceva de învățat de la ei.

Din păcate, dacă un atacator E intervine activ în transmisia de date, utilizatorul B poate primi doar un subset de mesaje trimise către A. Dacă există o pierdere de mesaje, atunci comportamentul utilizatorilor ar trebui să depindă de tipul de informații pe care le schimbă. În unele cazuri, pierderea unei părți a mesajului poate să nu fie critică, în celălalt caz, poate necesita încheierea sesiunii de comunicare.

6. Concluzie

Foarte multe momente nu au fost luate în considerare în acest post. Cum se potrivesc A și B cheile de sesiune? De unde în timpul coordonării cheilor către utilizator Și se știe, ce comunică cu B dacă o condiție a unei probleme E se poate trăda pentru oricine?

Nu mai puțin interesante întrebări - cum să generați corect numerele pseudo-aleatoare? Cum de a contracara atacurile de sincronizare? Ce se întâmplă dacă sistemul de operare plasează aplicația în execuție cu toate cheile din fișierul de paginare? Cum să ștergeți definitiv un fișier cu o pereche de chei RSA depășite? Atacantul E deși nu cunoaște conținutul mesajelor, dar știe dimensiunea lor și timpul de trimitere - este periculos și cum să reziste?

Îți place postul? Trimiteți-le altora:







Trimiteți-le prietenilor: