Table of Contents
Precondiții pentru construirea unui protocol de comunicare securizat în C
Înainte de scufundări în implementare, asigurați-vă că mediul de dezvoltare include un compilator C (GCC sau Clang), cunoștințe de bază de programare a prizei, și biblioteca OpenSSL instalată. OpenSSL oferă implementări robuste de algoritmi hidrolizați, făcându-l alegerea standard pentru comunicații securizate în C. Pe Linux, instalați OpenSSL prin intermediul managerului de pachete (de exemplu, ). Pe Windows, utilizați binarele precompilate sau construiți din sursă. Familiaritatea cu prize TCP/IP și modelul client-server este, de asemenea, asumat.
Înțelegerea blocurilor de clădiri criptografice
Un protocol de comunicare securizat se bazează pe trei piloni: confidențialitate, integritate și autentificare. Confidențialitatea se realizează prin criptare, asigurându-se că numai destinatarul vizat poate citi mesajul. Integritatea asigură că datele nu au fost modificate în tranzit. Autentificarea verifică identitatea părților care comunică. Într-un protocol personalizat, combinați de obicei criptare simetrică, hashing cu codurile de autentificare a mesajelor (HMAC) și un mecanism cheie de schimb precum zzie
Criptare simetrică cu AES
Standardul de criptare avansată (AES) este cel mai utilizat cod simetric. Acesta funcționează pe blocuri de 128 de biți și suportă dimensiuni cheie de 128, 192, sau 256 biți. Pentru comunicații securizate, preferă AES în Galois/Mode Counter (GCM), care oferă atât confidențialitate și integritate într-o singură operațiune. OpenSSL
Schimb cheie cu Diffie
Pentru a fi în siguranţă de acord asupra unui secret comun pe un canal nesecret, utilizaţi schimbul cheie Diffie
Integritatea mesajului și autentificarea cu HMAC
Pentru a verifica dacă un mesaj nu a fost modificat, se atașează un cod de autentificare a mesajului pe bază de hași (HMAC) la fiecare cifru criptat. HMAC utilizează o cheie secretă comună și o funcție hash tripartită (de exemplu, SHA-256). Receptorul recalculează HMAC pe datele primite și îl compară cu valoarea transmisă. Această etapă previne reluarea și manipularea atacurilor. Alternativ, AES-GCM include o etichetă de autentificare care servește aceluiași scop, simplificând protocolul.
Configurare OpenSSL în proiectul dvs. C
OpenSSL necesită inițializare atentă. Include antetele și apelul și la începutul programului. Pentru manipularea erorilor, utilizați și . Când vă conectați, adăugați la steagurile compilatorului. O configurare minimă arată astfel:
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/err.h>
// Initialize OpenSSL
void init_openssl() {
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
}
Construirea Stratului de Socket TCP
Transportul de bază pentru protocolul dumneavoastră va fi TCP, care oferă o livrare fiabilă, comandată. Creați un server care ascultă conexiunile de intrare și un client care inițiază strângerea de mână. Utilizați prizele standard POSIX cu , , , ] pe partea serverului, și , ]] pe partea client. Amintiți-vă să gestionați erorile grațios și aproape de descriptorii fișiere după utilizare.
Exemplu server Skeleton
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
bind(server_fd, (struct sockaddr*)&address, sizeof(address));
listen(server_fd, 3);
int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);
Exemplu Client Skeleton
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
Implementarea schimbului de chei Hellman
După stabilirea conexiunii TCP, clientul și serverul efectuează un schimb de chei DH. Fiecare parte generează o pereche de chei DH folosind OpenSSL
// Generate DH parameters
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
EVP_PKEY_paramgen_init(pctx);
EVP_PKEY_CTX_set_dh_paramgen_prime_len(pctx, 2048);
EVP_PKEY *params = NULL;
EVP_PKEY_paramgen(pctx, ¶ms);
// Generate key pair
EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new(params, NULL);
EVP_PKEY_keygen_init(kctx);
EVP_PKEY *my_key = NULL;
EVP_PKEY_keygen(kctx, &my_key);
// Export public key to send
unsigned char *pub_key_der = NULL;
int pub_len = i2d_PUBKEY(my_key, &pub_key_der);
send(sock, pub_key_der, pub_len, 0);
La sfârșitul primirii, importurile inter pares cheia publică folosind și apoi obține secretul comun. Secretul derivat poate fi hashed (de exemplu, cu SHA-256) pentru a produce o cheie uniformă pentru AES și HMAC.
Criptarea și decriptarea mesajelor cu AES-GCM
AES-GCM este modul preferat deoarece oferă atât criptarea, cât și o etichetă de autentificare într-o singură operațiune. Utilizați OpenSSL:21] cu . Aveți nevoie de o tag-ul 12-byte nonce (IV) și tasta 256-bit derivat din secretul comun DH. Textul cifrului este produs în bucăți, și după actualizarea finală, veți prelua tag-ul 16-byte. Trimiteți nonce, cifrutext, și tag-ul împreună. Receptorul efectuează , stabilește eticheta, și decriptează. Dacă verificarea etichetei nu reușește, mesajul este respins.
// Encryption
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, nonce);
unsigned char ciphertext[1024];
int outlen;
EVP_EncryptUpdate(ctx, ciphertext, &outlen, plaintext, len);
int tmplen;
EVP_EncryptFinal_ex(ctx, ciphertext + outlen, &tmplen);
unsigned char tag[16];
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);
Adăugarea de integritate cu HMAC (sau Lemising GCM Tag)
Dacă optați să nu utilizați AES-GCM, puteți cripta cu AES-CBC și apoi calculați un HMAC peste cifru. Utilizați de la OpenSSL cu SHA‐256. Appendați HMAC după cifru. Receptorul recalculează și compară. Această abordare necesită două chei: una pentru criptare, una pentru HMAC. Derive atât din secretul comun folosind o funcție de derivare cheie (KDF) ca HKDF. Cu toate acestea, AES-GCM elimină necesitatea unui HMAC separat, reducând complexitatea și greșelile potențiale.
Punerea ei împreună: fluxul de lucru complet
- Stabilește o conexiune TCP între client și server.
- Ambele părți generează perechi de chei efemere Diffie-Hellman.
- Schimb de chei publice și calcula secretul comun.
- Derive a 256-bit AES cheie și o cheie HMAC 256-bit (sau utilizați aceeași cheie pentru GCM).
- Clientul trimite un nonce (12 octeți aleatorie) și apoi mesajul AES-GCM criptat plus tag. Server decriptează și verifică.
- Serverul trimite un răspuns folosind un nou nonce (niciodată să nu reutilizeze nonces cu aceeași cheie).
- Ambele părţi pot continua schimbul de mesaje; pentru sesiuni lungi, rekey periodic folosind aceeaşi strângere de mână DH sau un mecanism de clichet.
Cele mai bune practici în materie de securitate
- Folosiţi generatoare puternice aleatorii de numere. Apel din OpenSSL pentru a genera chei, nonces și DH chei private.Nu utilizaţi niciodată sau în scopuri descriptive.
- Validați toate datele primite.Lungimile de verificare, parametrii cheie publici (de exemplu, asigurați-vă că p este prim, g este un generator) și etichetele HMAC înainte de procesare.
- [ ] Evitați cheile hardcodate sau implicit. Negociază întotdeauna chei proaspete pe sesiune pentru a oferi secretul perfect înainte.
- Erorile mânerului cu graţie.Dacă decriptarea eşuează sau verificarea HMAC eşuează, închide conexiunea şi loghează evenimentul.Nu dezvălui de ce a avut loc eşecul.
- Păstrați dependențele actualizate. Actualizează regulat OpenSSL pentru a patch-uri vulnerabilități cunoscute. OpenSSL documentation oferă îndrumări privind deprecizarea și cele mai bune practici.
- Consider folosind TLS mai degrabă decât un protocol personalizat. Pentru sistemele de producție, se bazează pe protocoale bine testate, cum ar fi TLS 1.3. Construirea unui protocol personalizat de la zero este predispusă la erori și nu este recomandată decât dacă aveți expertiză descriptivă profundă.
Testarea protocolului
Testați-vă implementarea prin rularea client și server pe aceeași mașină (localhost) și verificarea că mesajele decriptează corect. Introduceți erori, cum ar fi criptotext modificat sau nonces invalid pentru a se asigura că protocolul le respinge. Utilizați instrumente precum Wireshark pentru a inspecta traficul de rețea brută și confirmați că purtextul simplu nu este vizibil. Pentru testarea unitară, bateți joc de stratul de priză și de primitivele de testare monofazate separat. OpenSSL Depanarea poate ajuta la verificarea valorilor intermediare se potrivesc cu rezultatele așteptate.
Concluzie
Construirea unui protocol de comunicare securizat în C este un exercițiu de învățare excelent, dar necesită o atenție meticulos la detalii. Prin pârghie OpenSSL . Implementări dovedite ale Diffie-Hellman, AES-GCM, și HMAC, puteți crea un sistem care oferă confidențialitate, integritate și autentificare. Urmăriți întotdeauna cele mai bune practici [FLT]: utilizarea aleatorie puternică, obține chei de sesiune cu un KDF, nu refolosi niciodată nonces, și validați în detaliu toate datele. Pentru orice altceva dincolo de un proiect de învățare, luați în considerare adoptarea unui protocol standard, cum ar fi TLS 1.3, care a fost revizuit și implementat riguros la scară. Comunicarea sigură este un proces continuu de îmbunătățire; rămâneți informați cu privire la amenințările emergente și actualizați implementarea în consecință.