This commit is contained in:
blue-lemon0104
2026-04-07 13:35:22 +08:00
commit 0120fa9ce3
1530 changed files with 424864 additions and 0 deletions

114
include/kms/ikms_core.hpp Executable file
View File

@@ -0,0 +1,114 @@
#ifndef I_KMS_CORE_HPP
#define IKMS_CORE_HPP
#include "kms_common.hpp"
#include <iostream>
#include "json.hpp"
using json = nlohmann::json;
class IKmsCore {
public:
virtual ~IKmsCore() = default;
/**
* @brief 自定义初始化逻辑
* local解析json, 随后LoadCmkByUsername
* tencent或许可以是从配置文件中读取参数
*/
virtual bool init() = 0;
/* ------------------------------------CMK 管理-----------------------------------------------*/
/**
* @brief 查询用户是否有cmk
* @param user_name 输入:用户名
* @return bool 返回 true 表示存在false 表示不存在
*/
virtual bool hasCmk(const std::string &user_name) const = 0;
/**
* @brief 创建新的客户主密钥CMK
* @param user_name 输入:用户名,用于关联 CMK
* @param rotate_period 输入CMK 轮换周期(天数)
* @param new_cmk 输出:创建的 CMK 结构体,包含密钥 ID、数据等信息
* @param ks 输入:密钥编码结构,默认为 RAW
* @param alg 输入:加密算法,默认为 AES128
* @return bool 返回 true 表示创建成功false 表示失败
*/
virtual bool createCmk(const std::string& user_name, int rotate_period,
KeyStruct ks = KeyStruct::RAW, AlgorithmType alg = AlgorithmType::AES128) = 0;
/**
* @brief 删除指定用户的 CMK
* @param user_name 输入:要删除 CMK 的用户名
* @return bool 返回 true 表示删除成功false 表示失败
*/
virtual bool deleteCmk(const std::string& user_name) = 0;
virtual bool describeCmk(const std::string &user_name, std::string &result, bool decrypt) = 0;
/* ------------------------------------ 轮转 -----------------------------------------------*/
/**
* 非纯虚函数, 可以不实现
*/
/**
* @brief 立即轮换指定用户的 CMK
* @param user_name 输入:要轮换 CMK 的用户名
* @return bool 返回 true 表示轮换成功false 表示失败
*/
virtual bool rotateCmkNow(const std::string& user_name){
std::cout << "not implement" << std::endl;
}
/**
* @brief 启用或者关闭自动轮转
* @param auto_rotate_action 输入/输出:轮换命令(如启动或停止自动轮换),可能为 nullptr
* @param user_name 输入:用户名
* @return bool 返回 true 表示命令处理成功false 表示失败
*/
virtual bool handleAutoRotateCmd(std::string* auto_rotate_action, const std::string& user_name){
std::cout << "not implement" << std::endl;
}
/**
* @brief 获取指定用户的 CMK 自动轮换状态
* @param user_name 输入:用户名
* @return bool 返回 true 表示自动轮换启用false 表示未启用或用户不存在
*/
virtual bool getCmkAutoRotateStatusByUsername(const std::string& user_name){
std::cout << "not implement" << std::endl;
}
/* ------------------------------------ 加密解密 -----------------------------------------------*/
/**
* 这里是使用哪个CMK的问题
* 在Local中, 我通过在 initialize 的时候设置好 _user_name 成员, 随后通过 init -> LoadCmkByUsername 保存在 KMS的 _cmk 变量中 中
* 此后的加密(认为一个pgConn不会切换用户, 始终使用同一个cmk, 如果轮换在轮换结尾设置新的 _cmk )
* TencentKMS 应该无法这样做(无法缓存在本地), 只能保存 _user_name 然后每次加解密都选用 _user_name 对应的 cmk
*/
/**
* @brief 使用 CMK 加密 DEK
* @param dek 输入/输出:要加密的 DEK 数据,加密后存储在原变量
* @return bool 返回 true 表示加密成功false 表示失败
*/
virtual bool encryptData(std::string& dek) = 0;
/**
* @brief 使用 CMK 解密 DEK
* @param dek 输入/输出:要解密的 DEK 密文,解密后存储在原变量
* @return bool 返回 true 表示解密成功false 表示失败
*/
virtual bool decryptData(std::string& dek) = 0;
/* ------------------------------------新建DEK -------------------------------------------------*/
/**
* @brief 通过列名与CMK 派生出 col_dek, 表级 列密钥使用 "" 空字符串派生
*/
virtual bool createDek(std::string &col_dek, const std::string &column_name) = 0;
};
#endif

24837
include/kms/json.hpp Executable file

File diff suppressed because it is too large Load Diff

123
include/kms/kms_common.hpp Executable file
View File

@@ -0,0 +1,123 @@
// common.hpp
#ifndef KMS_COMMON_HPP
#define KMS_COMMON_HPP
#include <string>
#include <queue>
#include <unordered_map>
#define AES_BLOCK_SIZE 16
// 密钥类型
typedef enum {
KEY_TYPE_AES,
KEY_TYPE_ORE,
KEY_TYPE_SAHE,
KEY_TYPE_SMHE
} KeyType;
// 编码结构
typedef enum {
RAW
} KeyStruct;
// 加密算法
typedef enum {
SM4,
AES128
} AlgorithmType;
// CMK结构体
typedef struct {
std::uint32_t _key_id; //密钥id
std::string _user_name; //数据库用户名
std::string _cmk_data; //cmk数据
time_t _create_time; //创建时间
int _length; //密钥长度
KeyStruct _struct; //编码结构
AlgorithmType _alg; //加密算法
int _rotate_period; //轮换周期(天数)
bool _is_rotated; //是否被轮转
bool _is_primary_version; //是否是主版本
bool _auto_rotate; //自动轮转状态
} CMK;
// DEK数据库存储结构体
typedef struct {
std::string _user_name; //数据库用户名
std::string _table; //数据库表名
std::string _column; //数据库列名
KeyType _type; //密钥类型(必须有吗)
std::string _dek_cipher; //dek密文数据
bool _status; //是否启用(轮换)
time_t _create_time; //创建时间(必须自动轮换吗,这个可不可以只手动轮换,合同里没写要不只允许手动轮换)
int _rotate_time; //轮换周期(如果不是自动是不是可以没有)
int _length; //密钥长度(需要吗)
KeyStruct _struct; //编码结构(需要吗)
AlgorithmType _alg; //被加密算法(安全性)
} DEK;
// DEK缓存结构体存的东西越少越好
typedef struct {
std::string _user_name; //数据库用户名
std::string _table; //数据库表名
std::string _column; //数据库列名
KeyType _type; //密钥类型(必须有吗)
std::string _dek_plain; //dek明文数据
time_t _find_time; //缓存创建时间
int _cache_time; //缓存时间
int _length; //密钥长度(必须有吗)
KeyStruct _struct; //编码结构(必须有吗)
} DEK_CACHE;
//表信息(user -> db -> table -> col?)
typedef struct {
std::string user_name;
std::string db_name;
std::string table_name;
std::queue<std::string> col_name;
std::unordered_map<std::string, std::string> dek_store_tmp;
std::unordered_map<std::string, std::string> dek_store_tmp_for_update;
std::string dek_table_level_tmp;
std::string dek_table_level_for_update;
} DbInfo;
// ============ 配置基类和具体配置类 ============
// 基础配置接口
class IKmsConfig {
public:
virtual ~IKmsConfig() = default;
virtual std::string getType() const = 0;
};
class LocalKmsConfig: public IKmsConfig {
public:
const char *file_path_;
const char *key_path_;
const char *cmk_auto_rotate_status_path_;
const char *user_name_;
const char *db_name_;
LocalKmsConfig(const char *file_path, const char *key_path, const char *cmk_auto_rotate_status_path, const char* user_name, const char* db_name)
:file_path_(file_path),key_path_(key_path),cmk_auto_rotate_status_path_(cmk_auto_rotate_status_path),user_name_(user_name),db_name_(db_name){}
std::string getType() const override { return "local"; }
};
// Tencent KMS 配置
class TencentKmsConfig : public IKmsConfig {
public:
std::string access_key;
std::string secret_key;
std::string region;
std::string endpoint;
// ... 自定义
TencentKmsConfig(const std::string& ak, const std::string& sk, const std::string& r)
: access_key(ak), secret_key(sk), region(r) {}
std::string getType() const override { return "tencent"; }
};
#endif // KMS_COMMON_HPP

109
include/kms/kms_core_local.hpp Executable file
View File

@@ -0,0 +1,109 @@
// local_kms_core.hpp
#ifndef LOCAL_KMS_CORE_HPP
#define LOCAL_KMS_CORE_HPP
#pragma once
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <ctime>
#include <fstream>
#include <random>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <sstream>
#include <iomanip>
#include <algorithm>
//#include <libpq-fe.h>
#include "json.hpp"
#include <thread>
#include <chrono>
#include <mutex>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <map>
#include "kms_factory.hpp"
#include "kms_interface.hpp"
#include "kms_common.hpp"
#include "json.hpp"
using json = nlohmann::json;
class LocalKmsCore : public IKmsCore {
private:
json _data; // 解析出的 JSON 数据
std::string _path; // CMK 信息存储路径JSON 文件)
std::string _key_path; // 加密 CMK 的密钥路径
std::string _user_name;
std::string _db_name;
std::string _cmk; // 当前用户的 CMK
std::string _cmk_auto_rotate_status_path; // CMK 自动轮转状态存储路径
std::map<std::string, pid_t> cmk_auto_rotate_pids; // 自动轮转进程 ID
std::map<std::string, bool> cmk_auto_rotate_status; // 自动轮转状态
std::vector<unsigned char> readBinaryFile(const std::string& path);
std::vector<unsigned char> xorBuffers(const std::vector<unsigned char>& a, const std::vector<unsigned char>& b);
std::vector<unsigned char> hmac_sha256(const std::vector<unsigned char>& key, const std::vector<unsigned char>& message);
std::vector<unsigned char> getSystemIDHash16();
std::vector<unsigned char> sha256(const std::string& input);
std::string base64_encode(const unsigned char *data, size_t length);
std::string base64_decode(const std::string &encoded);
void getRootKey(unsigned char *key, size_t len);
std::string deriveKey(const std::string& master_key, const std::string& column_name);
std::string generateSalt(const std::string& column_name);
bool getRandomCmk(std::string &_cmk_data, AlgorithmType alg, int &length);
bool getRandomDek(std::string &_dek_data);
void _rand(std::string &rand, int length_in_bytes);
bool encryptKey(std::string &ori_key);
bool decryptKey(std::string &ori_key);
bool createDerivedDek(std::string& dek, const std::string& column_name);
void loadAutoRotateStatus();
void saveAutoRotateStatus();
void autoRotateProcess(const std::string &user_name);
bool storeCmk(CMK &cmk, bool rotate=false);
bool LoadCmkByUsername(const std::string &user_name);
bool save();
public:
LocalKmsCore(const IKmsConfig &config);
~LocalKmsCore();
// KMSInterface 实现
bool init() override;
// cmk 相关
bool hasCmk(const std::string &user_name) const override;
bool createCmk(const std::string& user_name, int rotate_period,
KeyStruct ks = KeyStruct::RAW, AlgorithmType alg = AlgorithmType::AES128) override;
bool deleteCmk(const std::string& user_name) override;
bool describeCmk(const std::string &user_name, std::string &result, bool decrypt) override;
// 自动轮转辅助方法
bool rotateCmkNow(const std::string& user_name) override;
bool handleAutoRotateCmd(std::string* auto_rotate_action, const std::string& user_name) override;
bool getCmkAutoRotateStatusByUsername(const std::string& user_name) override;
// 加解密
bool encryptData(std::string& dek) override;
bool decryptData(std::string& dek) override;
// 新建DEK
bool createDek(std::string &col_dek, const std::string &column_name) override;
static void registerLocalKms(){
KmsFactory::instance().registerCreator("local", [](const IKmsConfig& config) {
return myPtr::make_unique<LocalKmsCore>(config);
});
}
};
#endif // LOCAL_KMS_CORE_HPP

24
include/kms/kms_factory.hpp Executable file
View File

@@ -0,0 +1,24 @@
// kms_factory.hpp
#ifndef KMS_FACTORY_HPP
#define KMS_FACTORY_HPP
#include "kms_interface.hpp"
class KmsFactory {
public:
using CreatorFunc = std::function<std::unique_ptr<IKmsCore>(const IKmsConfig &)>;
static KmsFactory& instance();
void registerCreator(const std::string& name, CreatorFunc func);
std::unique_ptr<IKmsCore> create(const IKmsConfig& config) const;
std::vector<std::string> listRegistered() const;
private:
std::unordered_map<std::string, CreatorFunc> creators_;
};
#endif // KMS_FACTORY_HPP

54
include/kms/kms_interface.hpp Executable file
View File

@@ -0,0 +1,54 @@
// kms_interface.hpp
#ifndef KMS_INTERFACE_HPP
#define KMS_INTERFACE_HPP
#include <memory>
#include <functional>
#include "ikms_core.hpp"
namespace myPtr{
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
// 静态库接口类
class KMSInterface {
private:
static thread_local std::unique_ptr<IKmsCore> instance_;
public:
// 初始化并"创建" IKmsCore 实例
static bool initialize( const IKmsConfig& config );
static void cleanup(); // 清理当前线程绑定的 core 实例
// 获取当前线程的 KMS 实例(如需特殊用途)
static IKmsCore* getInstance();
// 包装接口
static bool hasCmk(const std::string& user_name);
static bool createCmk(const std::string& user_name, int rotate_period,
KeyStruct ks = KeyStruct::RAW, AlgorithmType alg = AlgorithmType::AES128);
static bool deleteCmk(const std::string& user_name);
static bool describeCmk(const std::string &user_name, std::string &result, bool decrypt);
// 轮转相关
static bool rotateCmkNow(const std::string& user_name);
static bool handleAutoRotateCmd(std::string* action, const std::string& user_name);
static bool getCmkAutoRotateStatusByUsername(const std::string& user_name);
// 加解密
static bool encryptData(std::string& dek);
static bool decryptData(std::string& dek);
// 创建DEK
static bool createDek(std::string &col_dek, const std::string &column_name);
};
#endif // KMS_INTERFACE_HPP