Förutsättningar för att bygga ett säkert kommunikationsprotokoll i C

Innan dykning i genomförandet, se till att din utvecklingsmiljö innehåller en C-kompilator (GCC eller Clang), grundläggande kunskap om socketprogrammering och OpenSSL-biblioteket installerat. OpenSSL ger robusta implementeringar av kryptografiska algoritmer, vilket gör det till standardvalet för säker kommunikation i C. På Linux, installera OpenSSL via din pakethanterare (t.ex. ]]]) använd precompiled binaries eller bygg från källa. Familiaritet med TCP / IP-uttag och klient-ser är också antagen.

Förstå Kryptografiska byggstenar

Ett säkert kommunikationsprotokoll vilar på tre pelare: sekretess, integritet och autentisering. Konfidentialitet uppnås genom kryptering, se till att endast den avsedda mottagaren kan läsa meddelandet. Integritet säkerställer att data inte har ändrats i transit. Authentication verifierar identiteterna hos de kommunicerande parterna. I ett anpassat protokoll kombinerar du vanligtvis symmetrisk kryptering, hashing med meddelandeautentiseringskoder (HMAC) och en nyckelutbytesmekanism som Diffie-Hellman.

Symmetrisk kryptering med AES

Advanced Encryption Standard (AES) är den mest använda symmetriska chifferen. Det fungerar på 128-bitars block och stöder nyckelstorlekar på 128, 192 eller 256 bitar. För säker kommunikation, föredrar AES i Galois / Counter Mode (GCM), som ger både konfidentialitet och integritet i en enda operation. OpenSSL: s EVP-gränssnitt gör det enkelt att kryptera och dekryptera data med AES-GCM. Undvik äldre lägen som ECB eller CBC

Key Exchange med Diffie-Hellman

För att säkert komma överens om en delad hemlighet över en osäkrad kanal, använd Diffie-Hellman (DH) nyckelutbyte. Båda parterna genererar privata nycklar och utbyta offentliga parametrar, beräkna sedan en gemensam hemlighet. ]] Diffie-Hellman är sårbar för man-i-mitten attacker om inte autentiseras, så att du senare kan utvidga detta med digitala signaturer eller fördelade nycklar.

Meddelande Integritet och Autentisering med HMAC

För att verifiera att ett meddelande inte har manipulerats, appendera en Hash-baserad meddelandeautentiseringskod (HMAC) till varje krypterad chiffertext. HMAC använder en delad hemlig nyckel och en kryptografisk hashfunktion (t.ex. SHA‐256). Mottagaren recomputes HMAC på mottagna data och jämför det med det överförda värdet. Detta steg förhindrar replay och manipulering av attacker. Alternativt innehåller AES-GCM en autentifieringslappning som tjänar samma syfte.

Ställa in OpenSSL i ditt C-projekt

OpenSSL kräver noggrann initiering. Inkludera nödvändiga rubriker och ring ] och ] i början av ditt program. För felhantering, använd ] och ]]]]. När du länkar, lägg till till dina kompilatorflaggor. En minimal inställning ser ut så här:

#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();
}

Bygga TCP Socket Layer

Den underliggande transporten för ditt protokoll kommer att vara TCP, som ger tillförlitlig, beställd leverans. Skapa en server som lyssnar på inkommande anslutningar och en klient som initierar handskakning. Använd standard POSIX-uttag med , ], ]], ]] på serversidan och ]], ]] på klientsidan. Kom ihåg att hantera fel gracefullt och stänga filbeskrivnings.

Server Exempel 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);

Kund Exempel 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));

Genomföra Diffie-Hellman Key Exchange

Efter att ha etablerat TCP-anslutningen, klienten och servern utför en DH-nyckelutbyte. Varje sida genererar ett DH-nyckelpar med OpenSSL: s ]] API. Den offentliga nyckeln skickas över uttaget, och båda sidorna härleder en delad hemlighet med ]. För enkelhet, använd en fast prime-grupp (t.ex. ] med parametrar från ]]]) skulle du förhandla fram gruppen eller använda den.

// 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, &params);

// 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);

På mottagaränden importerar peer den offentliga nyckeln med ] och kommer sedan den delade hemligheten. Den härledda hemligheten kan hashed (t.ex. med SHA-256) för att producera en enhetlig nyckel för AES och HMAC.

Kryptera och dekryptera meddelanden med AES-GCM

AES-GCM är det föredragna läget eftersom det ger både kryptering och en autentiseringstagg i en operation. Använd OpenSSL: s ]] med ]. Du behöver en 12-byte nonce (IV) och 256-bitars nyckel härrör från DH delad hemlighet. Klippantexten produceras i bitar, och efter den slutliga uppdateringen hämtar du 16-byte taggen. Skicka nonce, chiffhertext och taggar , set],

// 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);

Lägga till integritet med HMAC (eller dra nytta av GCM-taggen)

Om du väljer att inte använda AES-GCM kan du kryptera med AES-CBC och sedan beräkna en HMAC över chiffertexten. Använd ] från OpenSSL med SHA‐256. Appendera HMAC efter chiffertexten. Mottagaren räknar och jämför. Detta tillvägagångssätt kräver två nycklar: en för kryptering, en för HMAC. Derive både från den delade hemligheten med en nyckelriveringsfunktion (KDF) som HKDF.

Att sätta ihop det: Fullständigt arbetsflöde

  1. Skapa en TCP-anslutning mellan klient och server.
  2. Båda sidorna genererar ephemerala Diffie-Hellman-nyckelpar.
  3. Utbyta offentliga nycklar och beräkna den delade hemligheten.
  4. Derive en 256-bitars AES-nyckel och en 256-bitars HMAC-nyckel (eller använd samma nyckel för GCM).
  5. Kunden skickar en nonce (12 byte slumpmässigt) och sedan AES-GCM krypterade meddelande plus tag. Server decrypts och verifierar.
  6. Server skickar ett svar med en ny nonce (återanvänd aldrig icke-skivor med samma nyckel).
  7. Båda sidorna kan fortsätta att byta meddelanden; under långa sessioner, återkomma periodiskt med samma DH handskakning eller en ratchet mekanism.

Säkerhet bästa praxis

  • ] Använd starka slumptalsgeneratorer. Ring ]] från OpenSSL för att generera nycklar, nonces och DH privata nycklar. Använd aldrig ] eller för kryptografiska ändamål.
  • ]Validate all mottagen data. Kontrolllängder, allmänna nyckelparametrar (t.ex., se till att p är prime, g är en generator) och HMAC-taggar före bearbetning.
  • ]Frida hårdkodade nycklar eller standarder. Förhandla alltid nycklar per session för att ge perfekt framåt sekretess.
  • ]] Handle fel graciöst. Om dekryptering misslyckas eller HMAC-verifiering misslyckas, stäng anslutningen och logga händelsen. avslöja inte varför felet inträffade.
  • ]] Behålla beroenden uppdaterade. Uppdatera regelbundet OpenSSL för att patcha kända sårbarheter. ]OpenSSL-dokumentation] ger vägledning om avskrivningar och bästa praxis.
  • ] Tänk på att använda TLS snarare än ett anpassat protokoll. För produktionssystem, förlita sig på väl beprövade protokoll som TLS 1.3. Bygga ett anpassat protokoll från grunden är fel-benägen och rekommenderas inte om du inte har djup kryptografisk expertis.

Testa protokollet

Testa ditt genomförande genom att köra klient och server på samma maskin (localhost) och verifiera att meddelanden dekrypterar korrekt. Introducera fel som manipulerad chiffertext eller ogiltiga nonces för att säkerställa att protokollet avvisar dem. Använd verktyg som Wireshark för att inspektera rånätstrafiken och bekräfta att klartext inte är synlig. För enhetstestning, håna socket lagret och testa kryptografiska primitiva separat. OpenSSL: s debugging kan hjälpa till att verifiera mellanliggande värderingar.

Slutsats

Att bygga ett säkert kommunikationsprotokoll i C är en utmärkt inlärningsövning, men det kräver noggrann uppmärksamhet på detaljer. Genom att utnyttja OpenSSL: s beprövade genomföranden av Diffie-Hellman, AES-GCM och HMAC kan du skapa ett system som ger konfidentialitet, integritet och autentisering. Alltid följa kryptografiska bästa praxis: använd stark slumpmässighet, härleda sessionsnycklar med en KDF, återanvänd aldrig nonces och noggrant validera alla data.