add old lci module
This commit is contained in:
1 parent
38a6e815f0
commit
8499631091
171 files changed
+25562
No files matched your search
@@ -0,0 +1,145 @@
|
||||
#include "Crypto_Basic.hpp"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#define CRYPTO_CHECK(condition, message) \
|
||||
if (!(condition)) { \
|
||||
throw std::runtime_error(message); \
|
||||
}
|
||||
namespace qing {
|
||||
class AES_CBC: public qing::Crypto_Basic {
|
||||
public:
|
||||
/* 构造函数 初始化一个随即的密钥和初始化向量 */
|
||||
AES_CBC() {
|
||||
generate_key_iv(key, iv);
|
||||
}
|
||||
AES_CBC(std::vector<unsigned char> &key, std::vector<unsigned char> &iv) {
|
||||
this->key = key;
|
||||
this->iv = iv;
|
||||
}
|
||||
std::string get_key() {
|
||||
return bytes_to_hex(key);
|
||||
}
|
||||
std::string get_iv() {
|
||||
return bytes_to_hex(iv);
|
||||
}
|
||||
|
||||
std::string encrypt(std::string original_text) {
|
||||
std::vector<unsigned char> plaintext(original_text.begin(), original_text.end());
|
||||
std::vector<unsigned char> ciphertext = aes_encrypt(plaintext, key, iv);
|
||||
|
||||
// hex-bytes转换测试
|
||||
/*std::string hex = bytes_to_hex(ciphertext);
|
||||
std::vector<unsigned char> cipher2 = hex_to_bytes(hex);
|
||||
print_bytes(ciphertext);
|
||||
print_bytes(cipher2);*/
|
||||
|
||||
return bytes_to_hex(ciphertext);
|
||||
}
|
||||
|
||||
std::string decrypt(std::string cipher_hex) {
|
||||
std::vector<unsigned char> ciphertext = hex_to_bytes(cipher_hex);
|
||||
std::vector<unsigned char> decrypted = aes_decrypt(ciphertext, key, iv);
|
||||
return std::string(decrypted.begin(), decrypted.end());
|
||||
}
|
||||
|
||||
static void print_bytes(std::vector<unsigned char>& bytes) {
|
||||
for (unsigned char byte : bytes) {
|
||||
std::cerr << std::setw(2) << static_cast<int>(byte);
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> key;
|
||||
std::vector<unsigned char> iv;
|
||||
// 生成随机密钥和IV
|
||||
static void generate_key_iv(std::vector<unsigned char>& key,
|
||||
std::vector<unsigned char>& iv) {
|
||||
key.resize(32); // AES-256 需要 32 字节密钥
|
||||
iv.resize(16); // AES 块大小 16 字节(128-bit)
|
||||
|
||||
// 生成随即密钥
|
||||
CRYPTO_CHECK(RAND_bytes(key.data(), key.size()) == 1, "密钥生成失败");
|
||||
|
||||
// 生成随即IV
|
||||
CRYPTO_CHECK(RAND_bytes(iv.data(), iv.size()) == 1, "IV生成失败");
|
||||
}
|
||||
|
||||
// AES-256-CBC 加密
|
||||
static 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();
|
||||
CRYPTO_CHECK(ctx != nullptr, "无法创建加密上下文");
|
||||
|
||||
// 初始化加密操作
|
||||
CRYPTO_CHECK(EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
|
||||
key.data(), iv.data()) , "加密初始化失败");
|
||||
|
||||
// 输出缓冲区 (密文可能比明文长一个块)
|
||||
std::vector<unsigned char> ciphertext(plaintext.size() + EVP_CIPHER_CTX_block_size(ctx));
|
||||
int len = 0;
|
||||
int ciphertext_len = 0;
|
||||
|
||||
// 提供明文数据
|
||||
CRYPTO_CHECK(EVP_EncryptUpdate(ctx, ciphertext.data(), &len,
|
||||
plaintext.data(), plaintext.size()) == 1, "加载更新失败");
|
||||
ciphertext_len = len;
|
||||
|
||||
// 完成加密(处理填充)
|
||||
CRYPTO_CHECK(EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &len) == 1, "加密结束失败");
|
||||
ciphertext_len += len;
|
||||
|
||||
// 调整到实际密文长度
|
||||
ciphertext.resize(ciphertext_len);
|
||||
|
||||
// 处理上下文
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return ciphertext;
|
||||
|
||||
}
|
||||
|
||||
// AES-256-CBC
|
||||
static std::vector<unsigned char> aes_decrypt(const std::vector<unsigned char>& ciphertext,
|
||||
const std::vector<unsigned char>& key,
|
||||
const std::vector<unsigned char>& iv) {
|
||||
// 创建上下文
|
||||
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
||||
CRYPTO_CHECK(ctx != nullptr, "无法创建解密上下文");
|
||||
|
||||
// 初始化解密操作
|
||||
CRYPTO_CHECK(EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr,
|
||||
key.data(), iv.data()) == 1, "解密初始化失败");
|
||||
|
||||
// 输出缓冲区(明文可能比密文短,但最大为密文长度)
|
||||
std::vector<unsigned char> plaintext(ciphertext.size());
|
||||
int len = 0;
|
||||
int plaintext_len = 0;
|
||||
|
||||
// 提供密文数据
|
||||
CRYPTO_CHECK(EVP_DecryptUpdate(ctx, plaintext.data(), &len,
|
||||
ciphertext.data(), ciphertext.size()) == 1, "解密更新失败");
|
||||
plaintext_len = len;
|
||||
|
||||
// 完成解密(处理填充)
|
||||
CRYPTO_CHECK(EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len) == 1, "解密结束失败");
|
||||
plaintext_len += len;
|
||||
|
||||
// 调整到实际明文长度
|
||||
plaintext.resize(plaintext_len);
|
||||
|
||||
// 清理上下文
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
namespace qing {
|
||||
class Crypto_Basic {
|
||||
public:
|
||||
class CryptoExp: public std::runtime_error {
|
||||
public:
|
||||
CryptoExp(const std::string& msg): std::runtime_error(msg) {
|
||||
;
|
||||
}
|
||||
};
|
||||
protected:
|
||||
/* 字节码转十六进制字符串 */
|
||||
static std::string bytes_to_hex(const std::vector<unsigned char>& data) {
|
||||
static const char hex_chars[] = "0123456789abcdef";
|
||||
std::string hex_string;
|
||||
hex_string.reserve(data.size() * 2);
|
||||
|
||||
for (unsigned char byte: data) {
|
||||
hex_string.push_back(hex_chars[byte >> 4]); // 高4位
|
||||
hex_string.push_back(hex_chars[byte & 0x0F]); // 低4位
|
||||
}
|
||||
|
||||
return hex_string;
|
||||
}
|
||||
|
||||
/* 十六进制字符串转字节码 */
|
||||
static std::vector<unsigned char> hex_to_bytes(const std::string &hex) {
|
||||
// 检查长度是否为偶数
|
||||
if (hex.size() % 2 != 0) {
|
||||
throw std::invalid_argument("十六进制字符串长度必须为偶数");
|
||||
}
|
||||
|
||||
std::vector<unsigned char> bytes;
|
||||
bytes.reserve(hex.size() / 2);
|
||||
|
||||
auto char_to_nibble = [](char c) -> unsigned char {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
|
||||
if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
|
||||
throw std::invalid_argument("无效的十六进制字符:" + std::string(1, c));
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < hex.size(); i += 2) {
|
||||
unsigned char high = char_to_nibble(hex[i]);
|
||||
unsigned char low = char_to_nibble(hex[i + 1]);
|
||||
bytes.push_back((high << 4) | low);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
#pragma once
|
||||
#include "Crypto_Basic.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/core_names.h>
|
||||
// 错误处理宏
|
||||
#define HANDLE_SSL_ERROR() { \
|
||||
char err_buf[512]; \
|
||||
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); \
|
||||
std::cerr << "SSL error: " << err_buf << std::endl; \
|
||||
}
|
||||
// 自定义删除器用于管理OpenSSL资源
|
||||
struct EVP_PKEY_deleter {
|
||||
void operator()(EVP_PKEY* pkey) const { EVP_PKEY_free(pkey); }
|
||||
};
|
||||
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY, EVP_PKEY_deleter>;
|
||||
|
||||
struct EVP_PKEY_CTX_deleter {
|
||||
void operator()(EVP_PKEY_CTX* ctx) const { EVP_PKEY_CTX_free(ctx); }
|
||||
};
|
||||
using EVP_PKEY_CTX_ptr = std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_deleter>;
|
||||
|
||||
struct BIO_deleter {
|
||||
void operator()(BIO* bio) const { BIO_free_all(bio); }
|
||||
};
|
||||
using BIO_ptr = std::unique_ptr<BIO, BIO_deleter>;
|
||||
|
||||
namespace qing {
|
||||
class MyRSA: public qing::Crypto_Basic {
|
||||
public:
|
||||
class Generator {
|
||||
public:
|
||||
Generator() {
|
||||
key = generate_rsa_key();
|
||||
}
|
||||
void save_pri_key(const std::string filename) {
|
||||
if (!save_private_key(key.get(), filename)) {
|
||||
throw Crypto_Basic::CryptoExp("保存私钥失败。");
|
||||
}
|
||||
}
|
||||
void save_pub_key(const std::string filename) {
|
||||
if(!save_public_key(key.get(), filename)) {
|
||||
throw Crypto_Basic::CryptoExp("保存公钥失败。");
|
||||
}
|
||||
}
|
||||
private:
|
||||
EVP_PKEY_ptr key;
|
||||
// 生成 RSA 密钥对
|
||||
|
||||
static EVP_PKEY_ptr generate_rsa_key(size_t key_bits = 2048) {
|
||||
EVP_PKEY_CTX_ptr ctx(EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr));
|
||||
if (!ctx) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
if (EVP_PKEY_keygen_init(ctx.get()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 设置 RSA 密钥长度
|
||||
OSSL_PARAM params[] = {
|
||||
OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS, &key_bits),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
if (EVP_PKEY_CTX_set_params(ctx.get(), params) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EVP_PKEY* pkey = nullptr;
|
||||
if (EVP_PKEY_generate(ctx.get(), &pkey) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return EVP_PKEY_ptr(pkey);
|
||||
}
|
||||
|
||||
// 保存私钥到文件
|
||||
static bool save_private_key(EVP_PKEY* pkey, const std::string& filename,
|
||||
const char* password = nullptr) {
|
||||
BIO_ptr bio(BIO_new_file(filename.c_str(), "wb"));
|
||||
if (!bio) {
|
||||
std::cerr << "Failed to open file: " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 选择加密算法
|
||||
const EVP_CIPHER* cipher = password ? EVP_aes_256_cbc() : nullptr;
|
||||
|
||||
int ret = PEM_write_bio_PrivateKey(bio.get(), pkey, cipher,
|
||||
(unsigned char*) password,
|
||||
password ? strlen(password) : 0,
|
||||
nullptr, nullptr);
|
||||
|
||||
if (ret != 1) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 保存公钥到文件
|
||||
static bool save_public_key(EVP_PKEY* pkey, const std::string& filename) {
|
||||
BIO_ptr bio(BIO_new_file(filename.c_str(), "wb"));
|
||||
if (!bio) {
|
||||
std::cerr << "Failed ot open file: " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int ret = PEM_write_bio_PUBKEY(bio.get(), pkey);
|
||||
if (ret != 1) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Private_Key: Crypto_Basic {
|
||||
public:
|
||||
Private_Key(const std::string fullpath) {
|
||||
if (!(pri_key = load_private_key(fullpath)))
|
||||
throw Crypto_Basic::CryptoExp("读取私钥失败");
|
||||
}
|
||||
std::string Decrypt(const std::string cipher_hex) {
|
||||
std::vector<unsigned char> ciphertext = hex_to_bytes(cipher_hex);
|
||||
std::vector<unsigned char> decrypted = rsa_decrypt(pri_key.get(), ciphertext);
|
||||
if (decrypted.empty()) throw Crypto_Basic::CryptoExp("解密失败");
|
||||
return std::string(decrypted.begin(), decrypted.end());
|
||||
}
|
||||
private:
|
||||
EVP_PKEY_ptr pri_key;
|
||||
// 从文件加载私钥
|
||||
EVP_PKEY_ptr load_private_key(const std::string& filename,
|
||||
const char* password = nullptr) {
|
||||
BIO_ptr bio(BIO_new_file(filename.c_str(), "rb"));
|
||||
if (!bio) {
|
||||
std::cerr << "Failed to open file: " << filename << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 密码回调函数,显示转换为函数指针类型
|
||||
pem_password_cb* callback = +[] (char *buf, int size, int rwflag, void * u) {
|
||||
if (!u) return 0;
|
||||
const char* pass = (const char*)u;
|
||||
int len = strlen(pass);
|
||||
if (len > size) len = size;
|
||||
memcpy(buf, pass, len);
|
||||
return len;
|
||||
};
|
||||
pem_password_cb* cb = password ? nullptr : callback;
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio.get(), nullptr, cb, (void*)password);
|
||||
if (!pkey) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return EVP_PKEY_ptr(pkey);
|
||||
}
|
||||
|
||||
// 使用私钥解密数据
|
||||
static std::vector<unsigned char> rsa_decrypt(EVP_PKEY* private_key,
|
||||
const std::vector<unsigned char>& ciphertext) {
|
||||
EVP_PKEY_CTX_ptr ctx(EVP_PKEY_CTX_new(private_key, nullptr));
|
||||
if (!ctx) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 使用 OAEP 填充
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 获取输出缓冲区大小
|
||||
size_t outlen = 0;
|
||||
if (EVP_PKEY_decrypt(ctx.get(), nullptr, &outlen,
|
||||
ciphertext.data(), ciphertext.size()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 执行解密
|
||||
std::vector<unsigned char> plaintext(outlen);
|
||||
if (EVP_PKEY_decrypt(ctx.get(), plaintext.data(), &outlen,
|
||||
ciphertext.data(), ciphertext.size()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
plaintext.resize(outlen);
|
||||
return plaintext;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Public_Key: public Crypto_Basic {
|
||||
public:
|
||||
Public_Key(const std::string filename) {
|
||||
if (!(pub_key = load_public_key(filename)))
|
||||
throw Crypto_Basic::CryptoExp("读取公钥失败");
|
||||
}
|
||||
std::string Encrypt(std::string original_text) {
|
||||
std::vector<unsigned char> plaintext(original_text.begin(), original_text.end());
|
||||
std::vector<unsigned char> ciphertext = rsa_encrypt(pub_key.get(), plaintext);
|
||||
if (ciphertext.empty()) throw Crypto_Basic::CryptoExp("加密失败");
|
||||
return bytes_to_hex(ciphertext);
|
||||
}
|
||||
private:
|
||||
EVP_PKEY_ptr pub_key;
|
||||
|
||||
// 从文件加载公钥
|
||||
static EVP_PKEY_ptr load_public_key(const std::string& filename) {
|
||||
BIO_ptr bio(BIO_new_file(filename.c_str(), "rb"));
|
||||
if (!bio) {
|
||||
std::cerr << "Failed to open file: " << filename << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio.get(), nullptr, nullptr, nullptr);
|
||||
if (!pkey) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return EVP_PKEY_ptr(pkey);
|
||||
}
|
||||
|
||||
// 使用公钥加密数据
|
||||
static std::vector<unsigned char> rsa_encrypt(EVP_PKEY* public_key,
|
||||
const std::vector<unsigned char>& plaintext) {
|
||||
EVP_PKEY_CTX_ptr ctx(EVP_PKEY_CTX_new(public_key, nullptr));
|
||||
if (!ctx) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 使用 OAEP 填充
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 获取输出缓冲区大小
|
||||
size_t outlen =0 ;
|
||||
if (EVP_PKEY_encrypt(ctx.get(), nullptr, &outlen,
|
||||
plaintext.data(), plaintext.size()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
// 执行加密
|
||||
std::vector<unsigned char> ciphertext(outlen);
|
||||
if (EVP_PKEY_encrypt(ctx.get(), ciphertext.data(), &outlen,
|
||||
plaintext.data(), plaintext.size()) <= 0) {
|
||||
HANDLE_SSL_ERROR();
|
||||
return {};
|
||||
}
|
||||
|
||||
ciphertext.resize(outlen);
|
||||
return ciphertext;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user