Криптография в C++: шифрование и хеши с OpenSSL и Crypto++
Надёжная защита данных — базовая потребность любого современного приложения. C++ предоставляет разработчикам мощные инструменты для реализации криптографических алгоритмов: от простого хеширования до сложных схем асимметричного шифрования. В этой статье мы разберём две самые популярные библиотеки — OpenSSL и Crypto++ — и покажем, как с их помощью решать типовые задачи: хеширование, симметричное шифрование (AES) и асимметричное шифрование (RSA).
1. OpenSSL: универсальный криптопровайдер
OpenSSL — де-факто стандарт для криптографии на C/C++. Библиотека поддерживает все основные алгоритмы, сертификаты X.509 и протоколы TLS. Для работы потребуется установить пакет libssl-dev (Linux) или скачать бинарные сборки для Windows.
1.1 Хеширование SHA-256
Простейшая задача — вычислить хеш строки. Используем низкоуровневый API (EVP).
#include <iostream>
#include <openssl/evp.h>
#include <iomanip>
std::string sha256(const std::string& str) {
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr);
EVP_DigestUpdate(ctx, str.data(), str.size());
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
EVP_DigestFinal_ex(ctx, hash, &hash_len);
EVP_MD_CTX_free(ctx);
std::stringstream ss;
for (unsigned int i = 0; i < hash_len; ++i)
ss << std::hex << std::setw(2) << std::setfill('0')
<< (int)hash[i];
return ss.str();
}
int main() {
std::cout << sha256("Hello, Crypto!") << std::endl;
return 0;
}
1.2 Симметричное шифрование AES-256-CBC
Для шифрования данных одним ключом используем AES в режиме CBC. Важно: ключ и IV (вектор инициализации) должны быть случайными.
#include <openssl/evp.h>
#include <vector>
std::vector<unsigned char> aes_encrypt(
const std::vector<unsigned char>& plaintext,
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv)
{
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key.data(), iv.data());
std::vector<unsigned char> ciphertext(plaintext.size() + 16);
int out_len, tmp_len;
EVP_EncryptUpdate(ctx, ciphertext.data(), &out_len, plaintext.data(), plaintext.size());
EVP_EncryptFinal_ex(ctx, ciphertext.data() + out_len, &tmp_len);
out_len += tmp_len;
ciphertext.resize(out_len);
EVP_CIPHER_CTX_free(ctx);
return ciphertext;
}
Расшифровка выполняется аналогично через EVP_DecryptInit_ex и EVP_DecryptUpdate.
1.3 Асимметричное шифрование RSA
RSA используется для обмена ключами или подписи данных. Генерация пары ключей:
#include <openssl/rsa.h>
#include <openssl/pem.h>
RSA* generate_rsa_keypair(int bits = 2048) {
RSA* rsa = RSA_new();
BIGNUM* e = BN_new();
BN_set_word(e, 65537);
RSA_generate_key_ex(rsa, bits, e, nullptr);
BN_free(e);
return rsa;
}
// Сохранение публичного ключа в PEM
void save_public_key(RSA* rsa, const char* filename) {
BIO* bio = BIO_new_file(filename, "w");
PEM_write_bio_RSA_PUBKEY(bio, rsa);
BIO_free(bio);
}
2. Crypto++: C++-ориентированная альтернатива
Crypto++ (библиотека Wei Dai) предлагает более «родной» для C++ интерфейс: шаблоны, RAII, потоки. Не требует внешних зависимостей.
2.1 Хеширование SHA-256 в Crypto++
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <iostream>
std::string sha256_cryptopp(const std::string& msg) {
CryptoPP::SHA256 hash;
byte digest[CryptoPP