Передумови побудови протоколу безпечного зв'язку в С

Перед тим як перезбавити в реалізацію, забезпечити середовище розробки включає в себе компілятор C (GCC або Clang), базові знання програмування розетки, і встановлена бібліотека OpenSSL. OpenSSL забезпечує надійні виконання криптографічних алгоритмів, що робить його стандартним вибором для безпечного зв'язку в C. На Linux, встановити OpenSSL через ваш менеджер пакетів (наприклад, ). На Windows, використовують попередньо підготовлені бункери або будувати з джерела. Допускається також сімейство з розетками TCP / IP і модель клієнтського сервера.

Розуміння блоків Cryptoграфічного будівництва

Забезпечити протокол зв'язку переходить на три стовпи: конфіденційність, цілісність та автентифікація. Конфіденційність досягається за допомогою шифрування, що тільки призначений одержувач може прочитати повідомлення. Інтегрність гарантує, що дані не були змінені в транзиті. Ауттентифікація перевіряє ідентичності сторін спілкування. У користувальницькому протоколі ви зазвичай поєднує симетричне шифрування, що має повідомлення автентичні коди (HMAC), і ключовий механізм обміну, такі як Дифуй-Хеллман.

Симетричне шифрування з AES

Розширений стандарт шифрування (AES) є найбільш широко використовуваним симетричним cipher. Він працює на 128-бітних блоках і підтримує ключові розміри 128, 192 або 256 біт. Для захищених комунікацій воліють AES в Galois / Counter Mode (GCM), що забезпечує як конфіденційність і цілісність в одній операції. Інтерфейс OpenSSL робить його прямим для шифрування та розшифрування даних з AES‐GCM. Уникайте старих режимів, таких як ECB або CBC, якщо об'єднані з обережним наповнювачем і автентифікацією.

Обмін з дифузі-Хеллман

Щоб безпечно погодитися на загальний секрет над непрокурним каналом, скористайтеся Diffie-Hellman (DH) ключовим обміном. Обидві сторони генерують приватні ключі та обмінюються публічними параметрами, потім компралюють загальний секрет. Diffie-Hellman] вразливий до манітерно-середні атаки, якщо не автентифікований, тому ви можете пізніше продовжити це цифровими підписами або передовим поголені ключі. Для використання виробництва розглянемо використання ефемерного дифу - Хеллман (DHE) для забезпечення ідеальної передньої секреції.

Інтеграція з HMAC

Для перевірки, що повідомлення не було трамперовано, застосуньте Hash‐based Code Authentication (HMAC) до кожного зашифрованого ciphertext. HMAC використовує спільний секретний ключ і функцію криптографічного хешу (наприклад, SHA‐256). Ресівер переходить на HMAC на отриманих даних і порівнює його до перезавантаження. Цей крок запобігає релей і тампераційних атак. Крім того, AES‐GCM включає в себе автентифікаційний тег, який служить тим самим, що спрощення протоколу.

Налаштування OpenSSL в проекті C

OpenSSL вимагає ретельної ініціалізації. Включаючи необхідні заголовки і виклик і ] на старті вашої програми. Для обробки помилок використовуйте і . При зв'язку додайте до ваших прапорів компілятора. Мінімальне налаштування виглядає так:

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

Будівництво шарів TCP Socket

Основний транспорт для вашого протоколу буде TCP, який забезпечує надійну, замовлену доставку. Створіть сервер, який слухає для вхідних підключень і клієнта, який ініціює за допомогою запікання. Використовуйте стандартні розетки POSIX з , , , ] на серверній стороні, а , ]] на стороні клієнта. Пам'ятайте, що обробляти помилки витончено і закривають декриптори файлів після використання.

Приклад сервера 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);

Приклад клієнта Скелет

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

Реалізація дифузі-Hellman Key Exchange

Після встановлення підключення TCP клієнт і сервер виконує DH-ключну обмін. Кожна сторона генерує DH-ключну пару за допомогою API 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, &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);

Наприкінці прийому, однолітків імпортує публічний ключ за допомогою , а потім лікує загальний секрет. Отриманий секрет може бути захоплений (наприклад, з SHA‐256) для отримання однорідного ключа для AES і HMAC.

Сшифрування та розшифрування повідомлень з AES‐GCM

AES‐GCM є кращим режимом, оскільки він забезпечує як шифрування, так і автентифікаційний тег в одній операції. Використовуйте OpenSSL з . Вам потрібно 12‐byte notce (IV) і 256-bit ключ, отриманий від DH загальний секрет. Тефтекст виробляється в шматках, і після остаточного оновлення ви отримуєте 16-байт тег. Відправте несуть, ciphertext і tag разом. Ресивер виконує , встановлює тег, і розшифровує. Якщо тег не вдається, повідомлення відхилено.

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

Додавання доброчесності з HMAC (або Leveraging GCM тег)

Якщо ви не можете використовувати AES‐GCM, ви можете зашифрувати AES‐CBC, а потім компute HMAC над ciphertext. Використовуйте від OpenSSL з SHA‐256. Застосуйте HMAC після ciphertext. Ресивер рекалькулює і порівнює. Цей підхід вимагає двох ключових ключів: один для шифрування, один для HMAC. Вигідний як з спільного секрету за допомогою функції ключового видалення (KDF) як HKDF. Однак AES‐GCM усуває необхідність окремого HMAC, зменшення складності та потенційних помилок.

Поставляючи його разом: повний робочий процес

  1. Створення підключення ТCP між клієнтом та сервером.
  2. Обидві сторони генерують ефемеральні дифузі-Hellman ключові пари.
  3. Обмін публічними ключами та складанням спільного секрету.
  4. Видаляє ключ 256-бітних AES і 256-бітний ключ HMAC (або використовувати той же ключ для GCM).
  5. Клієнт надсилає нецей (12 байт випадковим) і потім зашифроване повідомлення AES‐GCM плюс тег. Сервер розшифровує і виправляє.
  6. Сервер надішле відповідь за допомогою нових нездійснених (необхідних випадків повторного використання з тим же ключем).
  7. Обидві сторони можуть продовжувати обмін повідомленнями; для довгих сеансів, під ключ періодично використовують той же механізм DH руки, що робить або ратичним механізмом.

Найкращі практики безпеки

  • Використовувати потужні генератори випадкових чисел ] з OpenSSL для створення ключів, некції та DH приватних ключів. Ніколи не використовуйте або для криптографічних цілей.
  • Валістан усіх отриманих даних] Перевірити довжини, параметри публічного ключа (наприклад, забезпечити р-н - прайм, г - генератор), а теги HMAC перед обробкою.
  • Avoid hardcoded keys або за замовчуванням Завжди веде переговори ключів свіжої за сеанс, щоб забезпечити ідеальний передній секрецію.
  • Попередження помилок Якщо розшифрування не вдалося або не вдається верифікації HMAC, закривши з'єднання і ввійти захід. Не розкрийте, чому збоїлася невдача.
  • Keep залежності оновлений Регулярно оновлення OpenSSL для патч відомих вразливостей. OpenSSL документація забезпечує керівництво по депрокації та кращих практик.
  • Consider using TLS, а не користувацький протокол Для виробничих систем, спираючись на добре перевірені протоколи, такі як TLS 1.3. Побудова користувацького протоколу з нуля є помилкою і не рекомендується, якщо у вас є глибока криптографічна експертиза.

Тестування протоколу

Тестуйте свою реалізацію, використовуючи запущений клієнт і сервер на одному машині (localhost) і перевірте, що повідомлення розшифровувати правильно. Введення помилок, таких як tampered ciphertext або невірні невірні не означає, що протокол відхиляє їх. Використовуйте інструменти, такі як Wireshark для перевірки ринку сировини і підтвердити, що звичайний текст не видно. Для тестування блоку, змусити шар розетки і тестувати криптографічні примітиви окремо. OpenSSL можна відхилити проміжні значення, що відповідають очікуваним виходом.

Висновок

Створення захищеного протоколу зв'язку в C є відмінним навчальним вправою, але це вимагає безглуздої уваги до деталей. За допомогою важеліювання перевірених імплементацій OpenSSL Diffie‐Hellman, AES‐GCM, і HMAC ви можете створити систему, яка забезпечує конфіденційність, цілісність і автентифікацію. Завжди слідувати криптографічним кращим практикам: використання сильної випадковості, деревої сесії ключі з KDF, ніколи не повторювати неправдиві дані, а також ретельно перевіряти ваші дані. Для будь-якого за межами проекту, розглянемо отримання стандартного протоколу, наприклад TLS 1.3, який був суворим чином, що було розширено оновлений огляд і повністю оновлений огляд