Table of Contents
Forutsetninger for å bygge en sikker kommunikasjonsprotokoll i C
Før du dykker i implementasjon, forsikre deg om utviklingsmiljøet ditt inkluderer en C-kompilator (GCC eller Clang), grunnleggende kunnskap om sokkelprogrammering, og OpenSSL-biblioteket installert. OpenSSL gir robuste implementeringer av kryptografiske algoritmer, noe som gjør det til standardvalget for sikker kommunikasjon i C. På Linux, installer OpenSSL via pakke manageren din (f.eks. ]). På Windows, bruk forhåndsbearbeidte binarier eller bygg fra kilde. Bekvemmelighet med TCP / IP- sokkel og klient-server modellen er også antatt.
Forstå de kryptografiske byggesteinene
En sikker kommunikasjonsprotokoll hviler på tre søyler: konfidensialitet, integritet og autentisering. Konfidensialitet oppnås gjennom kryptering, som sikrer at bare den tiltenkte mottakeren kan lese meldingen. Integritet sikrer at data ikke er endret i transitt. Autentisering bekrefter identitetene til kommuniserende parter. I en egendefinert protokoll kombinerer du vanligvis symmetrisk kryptering, hashing med meldingsautentiseringskoder (HMAC) og en nøkkelutvekslingsmekanisme som Diffie-Hellman.
Symmetrisk kryptering med AES
Den avanserte krypteringsstandarden (AES) er den mest brukte symmetriske krypteringskoden. Den fungerer på 128-biters blokker og støtter nøkkelstørrelser på 128, 192, eller 256 bits. For sikker kommunikasjon, foretrekker AES i Galois/Counter Mode (GCM), som gir både konfidensialitet og integritet i en enkelt operasjon. OpenSSLs EVP-grensesnitt gjør det enkelt å kryptere og dekryptere data med AES-GCM. Unngå eldre moduser som ECB eller CBC med mindre kombinert med forsiktig polstring og autentisering.
Nøkkelutveksling med Diffie ⁇ Hellman
For å sikkert bli enige om en delt hemmelighet over en usikret kanal, bruk Diffie-Hellman (DH) nøkkelutveksling. Begge parter genererer private nøkler og bytte offentlige parametere, og deretter beregne en felles hemmelighet. Diffie-Hellman er sårbare for man-i-midle angrep hvis ikke autentisert, så du kan senere utvide dette med digitale signaturer eller forhåndsdelte nøkler. For produksjonsbruk, vurdere å bruke efemeral Diffie-Hellman (DHE) til å gi perfekt videre hemmeliggjøring.
Melding Integritet og autentisering med HMAC
For å bekrefte at en melding ikke er manipulert med, legger til en Hash-basert meldingsautentiseringskode (HMAC) til hver kryptert krypteringstekst. HMAC bruker en delt hemmelig nøkkel og en kryptografisk hashfunksjon (f.eks. SHA-256). Mottakeren reberegner HMAC på de mottatte dataene og sammenligner den med den overførte verdien. Dette trinnet hindrer gjenspilling og manipulering av angrep. Alternativt inneholder AES-GCM en autentiseringstagg som tjener samme formål, forenkler protokollen.
Å sette opp OpenSSL i C-prosjektet ditt
OpenSSL krever forsiktig initialisering. Inkluder de nødvendige overskriftene og ring og i starten av programmet. For feilhåndtering, bruk og . Når du kobler til, legg til til dine kompilatorflagg. Et minimalt oppsett ser ut som dette:
#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();
}
Bygge TCP-socketlaget
Den underliggende transporten for protokollen vil være TCP, som gir pålitelig, bestilt levering. Opprett en server som lytter til innkommende forbindelser og en klient som starter håndtaket. Bruk standard POSIX-sokkel med , , , på serversiden, og ], på klientsiden. Husk å håndtere feil med graciøs og nær fildeskriptorer etter bruk.
Servereksempel 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);
Kundeeksempel 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));
Implementere Diffie-Hellman Key Exchange
Etter å ha opprettet TCP-tilkoblingen, utfører klienten og serveren en DH-nøkkelutveksling. Hver side genererer et DH-nøkkelpar ved hjelp av OpenSSLs API. Den offentlige nøkkelen sendes over sokkelen, og begge sider utledes en felles hemmelighet ved hjelp av ]. For enkelhet, bruk en fast primgruppe (f.eks. ] med parametere fra ). I en ekte protokoll, vil du forhandle gruppen eller bruke forhåndsdefinerte parametere.
// 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);
På mottakende slutten importerer peeren den offentlige nøkkelen ved å bruke og deretter stammer den felles hemmeligheten. Den avledede hemmeligheten kan hashed (f.eks. med SHA-256) for å produsere en ensartet nøkkel for AES og HMAC.
Kryptere og dekryptere meldinger med AES ⁇ GCM
AES ⁇ GCM er den foretrukne modusen fordi den gir både kryptering og autentiseringstag i én operasjon. Bruk OpenSSLs med . Du trenger en 12 ⁇ byte nonce (IV) og 256 ⁇ bit-tasten som er avledet fra DH-delte hemmelighet. Cifferteksten er produsert i biter, og etter den endelige oppdateringen henter du 16 ⁇ byte-taggen. Send ikke-send, krypteringstekst og tag sammen. Mottakeren utfører , angir merket og dekryptererer. Hvis taggen feiler, blir meldingen avvist.
// 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);
Legg til integritet med HMAC (eller Levering GCM Tag)
Hvis du velger å ikke bruke AES ⁇ GCM, kan du kryptere med AES ⁇ CBC og deretter beregne en HMAC over krypteringsteksten. Bruk fra OpenSSL med SHA ⁇ 256. Legg til HMAC etter krypteringsteksten. Mottakeren reberegner og sammenligner. Denne tilnærmingen krever to nøkler: en for kryptering, en for HMAC. Avlede begge fra den delte hemmeligheten ved hjelp av en nøkkelavledet funksjon (KDF) som HKDF. Men AES ⁇ GCM eliminerer behovet for en egen HMAC, redusere kompleksitet og potensielle feil.
Sette det sammen: Komplett arbeidsflyt
- Opprette en TCP-forbindelse mellom klient og server.
- Begge sider genererer efemeral Diffie - Hellman nøkkelpar.
- Bytt offentlige nøkler og beregne den delte hemmeligheten.
- Avlede en 256-bits AES-nøkkel og en 256-bits HMAC-nøkkel (eller bruk samme nøkkel for GCM).
- Kunden sender en ikke-selvstendig (12 byte tilfeldig) og deretter AES-GCM kryptert melding pluss tag. Server dekrypterer og verifiserer.
- Serveren sender et svar ved hjelp av en ny nonce (aldri gjenbruk nons med samme nøkkel).
- Begge sider kan fortsette å bytte ut meldinger; i lange økter, rekey periodisk ved hjelp av den samme DH håndtak eller en rottemekanisme.
Sikkerhetsbeste praksis
- Bruk sterke tilfeldige tallgeneratorer. Ring fra OpenSSL til å generere nøkler, noder og DH private nøkler. Bruk aldri ] eller til kryptografiske formål.
- Valider alle mottatte data. Sjekk lengder, offentlige nøkkelparametre (f.eks. sikre p er primtal, g er en generator), og HMAC-tagger før behandling.
- Avoid hardkodede nøkler eller standard. Forhandle alltid nøkler friske per sesjon for å gi perfekt fremover hemmeligholdelse.
- Handle feiler graciøst. Hvis dekryptering mislykkes eller HMAC-verifisering mislykkes, stenger tilkoblingen og logger hendelsen. Ikke avslør hvorfor feilen oppstod.
- Hold avhengighetene oppdaterte. Vanlig oppdatering OpenSSL til å patche kjente sårbarheter. OpenSSL-dokumentasjon gir veiledning om avskrivning og beste praksis.
- Consider bruker TLS i stedet for en egendefinert protokoll. For produksjonssystemer, stole på veltestede protokoller som TLS 1.3. Bygging av en egendefinert protokoll fra ripe er feil ⁇ prone og ikke anbefalt med mindre du har dyp kryptografisk kompetanse.
Testing av protokollen
Test implementeringen din ved å kjøre klient og server på samme maskin (lokalvert) og verifisere at meldinger dekrypterer riktig. Introdusere feil som manipulert krypteringstekst eller ugyldige nybegynnere for å sikre at protokollen avviser dem. Bruk verktøy som Wireshark for å inspisere rånettverkstrafikken og bekrefte at klartekst ikke er synlig. For enhetstesting, spotte sokkellaget og test kryptografiske primitiver separat. OpenSSLs ] feilsøking kan bidra til å verifisere mellomliggende verdier som samsvarer med forventet utganger.
Konklusjon
Bygge en sikker kommunikasjonsprotokoll i C er en utmerket læringsøvelse, men det krever nøye oppmerksomhet til detaljer. Ved å utnytte OpenSSLs dokumenterte implementeringer av Diffie-Hellman, AES-GCM og HMAC, kan du opprette et system som gir konfidensialitet, integritet og autentisering. Alltid følge kryptografiske beste praksis: bruk sterk tilfeldighet, utlede sesjonsnøkler med en KDF, aldri gjenbruke nyhetene, og grundig validere alle data. For noe utenfor et læringsprosjekt, vurdere å vedta en standardprotokoll som TLS 1.3, som har blitt strengt gjennomgått og utplassert i skala. Sikker kommunikasjon er en kontinuerlig prosess for forbedring; holde seg informert om nye trusler og oppdatere implementeringene dine i samsvar med dette.