init
This commit is contained in:
114
include/kms/ikms_core.hpp
Executable file
114
include/kms/ikms_core.hpp
Executable 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
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
123
include/kms/kms_common.hpp
Executable 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
109
include/kms/kms_core_local.hpp
Executable 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
24
include/kms/kms_factory.hpp
Executable 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
54
include/kms/kms_interface.hpp
Executable 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user