diff --git a/CMakeLists.txt b/CMakeLists.txt index 100de63..60682ba 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,22 +93,18 @@ set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" ) + + message(${CMAKE_MODULE_PATH}) file(GLOB_RECURSE Cpp_Files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/encryptsql/*.cpp" ) file(GLOB_RECURSE C_Files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/encryptsql/*.c") -# file(GLOB_RECURSE KMS_Cpp_Files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/KMS/*.cpp") file(GLOB_RECURSE DEK_Cpp_Files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/KMSAdapter/*.cpp") add_subdirectory(src/KMS) -# file(GLOB_RECURSE UtilsFiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/utils/*.cpp") -#set(Files "${Cpp_Files};${C_Files};src/utils/cryptoUtils.cpp;src/utils/cryptoCaller.cpp;src/utils/utils.cpp;src/utils/base64.c;src/utils/opensslUtils.cpp" -# src/KMS/KeyManagementService.cpp -# src/KMS/json.hpp) -# set(Files "${Cpp_Files};${C_Files};${KMS_Cpp_Files};${DEK_Cpp_Files};src/utils/cryptoUtils.cpp;src/utils/cryptoCaller.cpp;src/utils/utils.cpp;src/utils/base64.c;src/utils/opensslUtils.cpp") set(Files "${Cpp_Files};${C_Files};${DEK_Cpp_Files};src/utils/cryptoUtils.cpp;src/utils/cryptoCaller.cpp;src/utils/utils.cpp;src/utils/base64.c;src/utils/opensslUtils.cpp") list(REMOVE_ITEM Files "src/crypto/symmetria_2/symmetria_2/Interface_c.c") @@ -177,11 +173,6 @@ filter_regex(EXCLUDE "Interface_c" Files ${Files}) filter_regex(EXCLUDE "symmetria" Files ${Files}) -# message(STATUS ${SOURCES}) - -# find_package(PkgConfig REQUIRED) -# pkg_search_module(OPENSSL REQUIRED openssl) -# pkg_search_module(GMP REQUIRED gmp) find_package(jsoncpp REQUIRED) find_package(GMP REQUIRED) find_package(LOG4CPP REQUIRED) @@ -206,8 +197,10 @@ set(jsoncpp_LIBRARY jsoncpp_lib) set(jsoncpp_STATIC_LIBRARY jsoncpp_lib_static) SET(CryptoLib src/crypto/cryptolib) -set(PG_LIB_PATH "/usr/local/postgresql/lib") -set(PG_INCLUDE_PATH "/usr/local/postgresql/include") +# TODO UPDATE +set(PG_INSTALL_DIR "/usr/local/postgresql" CACHE PATH "PostgreSQL install dir") +set(PG_LIB_PATH "${PG_INSTALL_DIR}/lib") +set(PG_INCLUDE_PATH "${PG_INSTALL_DIR}/include") include_directories(src/utils ${OPENSSL_INCLUDE_DIR} ${GMP_INCLUDE_DIR} ${CryptoLib}/symmetria ${jsoncpp_INCLUDE} ${PG_INCLUDE_PATH}) @@ -216,7 +209,6 @@ SET(SYM_Lib symmetria) SET(HE_Lib he) SET(ORE_Lib ore) add_subdirectory(${CryptoLib}) -# add_subdirectory(src/Server) add_subdirectory(src/KeyDistribution) if(${CMAKE_BUILD_TYPE} EQUAL "Debug") @@ -224,15 +216,29 @@ if(${CMAKE_BUILD_TYPE} EQUAL "Debug") endif() # add_subdirectory(tests) add_library(${TARGET} SHARED ${Files}) -# target_link_libraries(${TARGET} ${OPENSSL_LIBRARIES} ${jsoncpp_LIBRARY} ${KMS_LIBRARY} -L${PG_LIB_PATH}) -target_link_libraries(${TARGET} ${OPENSSL_LIBRARIES} ${jsoncpp_LIBRARY} ${KMS_LIBRARY} -L${PG_LIB_PATH} keydistribution_client tls_server_host) +target_link_libraries(${TARGET} + ${OPENSSL_LIBRARIES} + ${jsoncpp_LIBRARY} + ${KMS_LIBRARY} + -L${PG_LIB_PATH} + keydistribution_client tls_server_host) + +if(NO_ENCRYPTSQL_USE_RECOVERY) + target_compile_definitions(your_target PRIVATE NO_ENCRYPTSQL_USE_RECOVERY) +endif() + +# TODO UPDATE target_link_libraries(encryptsql /new_enc/postgresql-14.2/src/port/libpgport.a /new_enc/postgresql-14.2/src/common/libpgcommon.a ) target_link_libraries(${TARGET} -Wl,--no-as-needed /usr/local/lib/libgmssl.so -Wl,--as-needed) target_link_libraries(${TARGET} ${SYM_Lib}) -target_include_directories(${TARGET} PRIVATE include pg_include ${KMS_INCLUDE_DIRS} src) + +target_include_directories(${TARGET} PRIVATE + include + pg_include + ${KMS_INCLUDE_DIRS} src) # if(${USE_SGX}) # add_custom_target( genKey ALL @@ -248,4 +254,34 @@ add_executable(restore src/bkup/restore.cpp) # 链接 stdc++fs(GCC 8/9 必需) target_link_libraries(backup stdc++fs) -target_link_libraries(restore stdc++fs) \ No newline at end of file +target_link_libraries(restore stdc++fs) + +set(ENCRYPTSQL_INSTALL_DIR "/usr/local/postgresql" CACHE PATH "PostgreSQL install prefix (e.g., /usr/local/postgresql)") +set(ENCRYPTSQL_CONFIG_DIR "/etc/encryptsql" CACHE PATH "Directory for encryptsql config files (e.g., map.json)") +set(DK_SERVER_HOST "127.0.0.1" CACHE STRING "DK server host") +set(DK_SERVER_PORT "9443" CACHE STRING "DK server port") + +if(NOT ENCRYPTSQL_INSTALL_DIR) + message(FATAL_ERROR "ENCRYPTSQL_INSTALL_DIR must be specified via -DENCRYPTSQL_INSTALL_DIR=...") +endif() + +configure_file(en_config.h.in ../include/en_config.h @ONLY) +configure_file(en_config.h.in ../src/utils/en_config.h @ONLY) + + +target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + +install(FILES + createudf.sql + mask_funcs.sql + DESTINATION ${ENCRYPTSQL_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +install(FILES + config.json + map.json + DESTINATION ${ENCRYPTSQL_CONFIG_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ) + +install(TARGETS backup restore + RUNTIME DESTINATION ${ENCRYPTSQL_INSTALL_DIR}/bin) \ No newline at end of file diff --git a/Makefile b/Makefile index 3bf0ad7..5e70e68 100755 --- a/Makefile +++ b/Makefile @@ -53,6 +53,7 @@ install: all $(INSTALL_DATA) build/lib/libencryptsql.so '$(DESTDIR)$(libdir)' $(INSTALL_DATA) build/lib/libudf.so '$(DESTDIR)$(libdir)' cp build/lib/enclave.signed.so /etc/encryptsql/ +# cp src/encryptsql/enclave.signed.so /etc/encryptsql/ # ./config no-autoalginit no-autoerrinit no-comp no-ct no-dso no-ec no-ec2m no-engine no-err no-gost no-pic no-pinshared no-posix-io no-psk no-rdrand no-shared no-sock no-sse2 no-stdio CFLAGS="-nostdinc" CXXFLAGS="-nostdinc++" LDFLAGS="-Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles" diff --git a/en_config.h.in b/en_config.h.in new file mode 100644 index 0000000..90ef921 --- /dev/null +++ b/en_config.h.in @@ -0,0 +1,28 @@ +#ifndef ENCRYPTSQL_CONFIG_H +#define ENCRYPTSQL_CONFIG_H + +// 安装路径(由 -DENCRYPTSQL_INSTALL_DIR=... 指定) +#define ENCRYPTSQL_INSTALL_DIR "@ENCRYPTSQL_INSTALL_DIR@" +#define ENCRYPTSQL_CONFIG_DIR "@ENCRYPTSQL_CONFIG_DIR@" +#define DK_SERVER_HOST "@DK_SERVER_HOST@" +#define DK_SERVER_PORT "@DK_SERVER_PORT@" + +#define CREATEUDF_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/createudf.sql" +#define MASK_FUNCS_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/mask_funcs.sql" + +#define MAP_JSON_PATH ENCRYPTSQL_CONFIG_DIR "/map.json" +#define MAP_JSON_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/map.json.backup" + +#define CMK_FILE_PATH ENCRYPTSQL_CONFIG_DIR "/output.json" +#define CMK_FILE_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/output.json.backup" + +#define CMK_KEY_PATH ENCRYPTSQL_CONFIG_DIR "/domainkey" +#define CMK_ROTATE_STATUS_PATH ENCRYPTSQL_CONFIG_DIR "/CMK_auto_rotate_status.json" + +#define ROOT_KEY_GEN_PATH ENCRYPTSQL_CONFIG_DIR "/kms_root" + +#define BACKUP_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/backup" +#define RESTORE_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/restore" + + +#endif /* ENCRYPTSQL_CONFIG_H */ \ No newline at end of file diff --git a/encryptsql.zip b/encryptsql.zip deleted file mode 100755 index c0289fc..0000000 Binary files a/encryptsql.zip and /dev/null differ diff --git a/include/en_config.h b/include/en_config.h new file mode 100644 index 0000000..abec66a --- /dev/null +++ b/include/en_config.h @@ -0,0 +1,28 @@ +#ifndef ENCRYPTSQL_CONFIG_H +#define ENCRYPTSQL_CONFIG_H + +// 安装路径(由 -DENCRYPTSQL_INSTALL_DIR=... 指定) +#define ENCRYPTSQL_INSTALL_DIR "/usr/local/postgresql" +#define ENCRYPTSQL_CONFIG_DIR "/etc/encryptsql" +#define DK_SERVER_HOST "127.0.0.1" +#define DK_SERVER_PORT "9443" + +#define CREATEUDF_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/createudf.sql" +#define MASK_FUNCS_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/mask_funcs.sql" + +#define MAP_JSON_PATH ENCRYPTSQL_CONFIG_DIR "/map.json" +#define MAP_JSON_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/map.json.backup" + +#define CMK_FILE_PATH ENCRYPTSQL_CONFIG_DIR "/output.json" +#define CMK_FILE_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/output.json.backup" + +#define CMK_KEY_PATH ENCRYPTSQL_CONFIG_DIR "/domainkey" +#define CMK_ROTATE_STATUS_PATH ENCRYPTSQL_CONFIG_DIR "/CMK_auto_rotate_status.json" + +#define ROOT_KEY_GEN_PATH ENCRYPTSQL_CONFIG_DIR "/kms_root" + +#define BACKUP_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/backup" +#define RESTORE_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/restore" + + +#endif /* ENCRYPTSQL_CONFIG_H */ diff --git a/include/kms/ikms_core.hpp b/include/kms/ikms_core.hpp index e7f6618..74cde21 100755 --- a/include/kms/ikms_core.hpp +++ b/include/kms/ikms_core.hpp @@ -1,4 +1,4 @@ -#ifndef I_KMS_CORE_HPP +#ifndef IKMS_CORE_HPP #define IKMS_CORE_HPP #include "kms_common.hpp" @@ -11,7 +11,7 @@ public: virtual ~IKmsCore() = default; /** - * @brief 自定义初始化逻辑 + * @brief 自定义初始化逻辑,不需要手动调用,会在单例第一次被创建时自动调用 * local:解析json, 随后LoadCmkByUsername * tencent:或许可以是从配置文件中读取参数 */ diff --git a/include/kms/kms_common.hpp b/include/kms/kms_common.hpp index 8da2208..631a701 100755 --- a/include/kms/kms_common.hpp +++ b/include/kms/kms_common.hpp @@ -5,7 +5,7 @@ #include #include #include - +#include #define AES_BLOCK_SIZE 16 @@ -105,19 +105,45 @@ public: std::string getType() const override { return "local"; } }; -// Tencent KMS 配置 -class TencentKmsConfig : public IKmsConfig { +// Huawei KMS 配置 +class HuaweiKmsConfig : public IKmsConfig { public: - std::string access_key; - std::string secret_key; + // 必需参数 + std::string accessKey; + std::string secretKey; + std::string projectId; 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 endpoint = ""; + std::string keyAlias = "default-key"; - std::string getType() const override { return "tencent"; } + // 实现 getType() 方法 + std::string getType() const override { + return "huawei"; + } + + // 有参构造函数 + HuaweiKmsConfig(const std::string& ak, const std::string& sk, + const std::string& pid, const std::string& reg, + const std::string& ep = "", const std::string& alias = "") + : accessKey(ak), secretKey(sk), projectId(pid), + region(reg), endpoint(ep), keyAlias(alias) {} + + // 安全清除敏感信息 + void ClearSensitiveData() { + OverwriteString(accessKey); + OverwriteString(secretKey); + } + +private: + void OverwriteString(std::string& str) { + if (!str.empty()) { + // 使用OpenSSL安全清除内存 + OPENSSL_cleanse(&str[0], str.size()); + str.clear(); + } + } }; #endif // KMS_COMMON_HPP \ No newline at end of file diff --git a/include/kms/kms_core_local.hpp b/include/kms/kms_core_local.hpp index 36964a9..272d15b 100755 --- a/include/kms/kms_core_local.hpp +++ b/include/kms/kms_core_local.hpp @@ -48,7 +48,6 @@ private: std::map cmk_auto_rotate_pids; // 自动轮转进程 ID std::map cmk_auto_rotate_status; // 自动轮转状态 - std::vector readBinaryFile(const std::string& path); std::vector xorBuffers(const std::vector& a, const std::vector& b); std::vector hmac_sha256(const std::vector& key, const std::vector& message); diff --git a/readme.md b/readme.md index 12ff4d3..ad42579 100755 --- a/readme.md +++ b/readme.md @@ -76,14 +76,18 @@ sudo cp config.json /etc/encryptsql/ ln -s ../../../include db_include rm -rf build -mkdir build -cd build -cmake .. +mkdir build && cd build +cmake .. \ + -DENCRYPTSQL_INSTALL_DIR=/usr/local/postgresql \ + -DENCRYPTSQL_CONFIG_DIR=/etc/encryptsql \ + -DDK_SERVER_HOST=127.0.0.1 \ + -DDK_SERVER_PORT=9443 sudo make -j `nproc` cd ../../../../../ -sudo touch src/interfaces/libpq/encryptsql/build/lib/enclave.signed.so -sudo make install +cmake --build src/interfaces/libpq/encryptsql/build --target enclave.signed.so -j"$(nproc)" +cp /etc/encryptsql/enclave.signed.so src/interfaces/libpq/encryptsql/build/lib/enclave.signed.so +make install sudo rm /usr/local/postgresql/lib/libudf.so sudo cp src/interfaces/libpq/encryptsql/build/lib/libudf.so /usr/local/postgresql/lib @@ -99,15 +103,16 @@ sudo cp src/interfaces/libpq/encryptsql/build/bin/backup /usr/local/postgresql/b sudo cp src/interfaces/libpq/encryptsql/build/bin/restore /usr/local/postgresql/bin/ # 创建cmk存储路径 -sudo mkdir -p /new_enc/kms_test -sudo cp src/interfaces/libpq/encryptsql/src/KMS/domainkey /new_enc/kms_test/ +sudo mkdir -p /etc/encryptsql/kms_test +sudo cp src/interfaces/libpq/encryptsql/src/KMS/domainkey /etc/encryptsql/kms_test/ cd /etc/encryptsql sudo chmod 777 map.json # 创建kms_root根密钥相关文件 -sudo mkdir -p /new_enc/kms_root -cd /new_enc/kms_root +sudo mkdir -p /etc/encryptsql/kms_root + +cd /etc/encryptsql/kms_root sudo head -c 16 /dev/urandom > frag_a sudo head -c 16 /dev/urandom > frag_b sudo head -c 16 /dev/urandom > frag_c @@ -135,6 +140,14 @@ source ~/.bashrc initdb +vim /usr/local/postgresql/data/postgresql.conf +# vim 打开后,将下面内容加入到尾部 +shared_preload_libraries = 'keydist_receiver' +keydist.listen_host = '127.0.0.1' +keydist.listen_port = '9443' +keydist.enclave_signed_path = '/new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/bin/tls_server_enclave.signed' + + pg_ctl start su root diff --git a/rebuild.sh b/rebuild.sh index 349fccc..1bec7ac 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -1,9 +1,11 @@ -rm /usr/local/postgresql/lib/libudf.so +mkdir -p /usr/local/postgresql/lib cd /new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql make clean -mkdir build && cd build && cmake .. +mkdir build && cd build +cmake .. -DENCRYPTSQL_INSTALL_DIR=/usr/local/postgresql make -j `nproc` -cp /new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/lib/libudf.so /usr/local/postgresql/lib -rm /usr/local/postgresql/lib/libencryptsql.so -cp /new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/lib/libencryptsql.so /usr/local/postgresql/lib +rm -f /usr/local/postgresql/lib/libudf.so +cp /new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/lib/libudf.so /usr/local/postgresql/lib/ +rm -f /usr/local/postgresql/lib/libencryptsql.so +cp /new_enc/postgresql-14.2/src/interfaces/libpq/encryptsql/build/lib/libencryptsql.so /usr/local/postgresql/lib/ diff --git a/replaced_file/fe-exec.14.c b/replaced_file/fe-exec.14.c index 56d1030..093e729 100755 --- a/replaced_file/fe-exec.14.c +++ b/replaced_file/fe-exec.14.c @@ -2350,7 +2350,7 @@ PQexecStart(PGconn *conn) return true; } extern void decryptResult(int, int, void *, void **); -#ifdef USE_BACKUP_ENCRYPT +#ifdef ENCRYPTSQL_USE_RECOVERY extern void delete_backup(bool is_transaction); #endif /* diff --git a/src/KMS/CMakeLists.txt b/src/KMS/CMakeLists.txt index d10f690..c6179d6 100755 --- a/src/KMS/CMakeLists.txt +++ b/src/KMS/CMakeLists.txt @@ -2,20 +2,24 @@ cmake_minimum_required(VERSION 3.0) # 设置KMS库项目 -set(KMS_TARGET kms_lib) +set(KMS_TARGET kms) # 收集KMS相关的源文件 file(GLOB_RECURSE KMS_Sources - "*.cpp" - "*.c" + CONFIGURE_DEPENDS + "*.cpp" "*.c" ) # 移除不需要的文件(如果有的话) -# list(REMOVE_ITEM KMS_Sources "unwanted_file.cpp") +list(REMOVE_ITEM KMS_Sources "${CMAKE_CURRENT_SOURCE_DIR}/kms_core_huawei.cpp") # 创建静态库 add_library(${KMS_TARGET} STATIC ${KMS_Sources}) +# 查找必要的依赖包 +find_package(jsoncpp REQUIRED) +find_package(OpenSSL REQUIRED) + # 设置包含目录 target_include_directories(${KMS_TARGET} PUBLIC @@ -29,9 +33,6 @@ target_include_directories(${KMS_TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/../crypto # crypto目录 ) -# 查找必要的依赖包 -find_package(jsoncpp REQUIRED) -find_package(OpenSSL REQUIRED) # 链接必要的库 target_link_libraries(${KMS_TARGET} @@ -39,12 +40,11 @@ target_link_libraries(${KMS_TARGET} ${OPENSSL_LIBRARIES} jsoncpp_lib PRIVATE - # 如果需要其他内部库,可以在这里添加 ) # 设置编译选项 target_compile_options(${KMS_TARGET} PRIVATE - -std=c++11 + -std=c++14 -fvisibility=hidden -fPIC # 位置无关代码选项,应用于静态库链接到共享库 ) @@ -66,4 +66,26 @@ set(KMS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/kms PARENT_SCOPE) -message(STATUS "KMS library configured: ${KMS_TARGET}") \ No newline at end of file +message(STATUS "KMS library configured: ${KMS_TARGET}") + + +# -------------------------------------- +# kms_cli 工具 +# 可执行文件 +# add_executable(kms_cli +# main.cpp +# ) + +# target_include_directories(kms_cli +# PRIVATE +# ${CMAKE_CURRENT_SOURCE_DIR}/../../include +# ${CMAKE_CURRENT_SOURCE_DIR} +# ) + +# set(PQ_LIB /usr/local/postgresql/lib/libpq.so) + +# target_link_libraries(kms_cli +# PRIVATE +# ${KMS_TARGET} +# ${PQ_LIB} +# ) diff --git a/src/KMS/KeyManagementService.cpp.bk b/src/KMS/KeyManagementService.cpp.bk deleted file mode 100755 index 6afb479..0000000 --- a/src/KMS/KeyManagementService.cpp.bk +++ /dev/null @@ -1,1072 +0,0 @@ -// -// Created by 曲晓阳 on 24-11-18. -// - -#include "kms/KeyManagementService.hpp" -#include -#include -#include -#include -#include -#include "encryptsql/fieldmap.h" -#include "crypto/crypto.h" - -extern void connectionRotationSelectDek(const std::string &user_name, const std::string &new_cmk, std::map &_dek_tmp, bool &hasDEK); - -extern void connectionRotationUpdataDek(const std::string &user_name, const std::string &new_cmk, std::map &_dek_tmp); - - -//TODO 更新init会出错的条件 -bool KeyManagerS::init() { - std::ifstream file(_path, std::ios::in); - if (file.is_open()) { - _data = json::parse(file); - } else { - _data["cmk"] = json::object(); - _data["index"] = json::object(); - _data["current_id"] = 0; - std::ofstream outFile(_path); - if (outFile.is_open()) { - outFile << _data.dump(4); - outFile.close(); - } - } - return true; -} - -//根密钥处理逻辑 - -// 读取文件内容为字节数组 -std::vector KeyManagerS::readBinaryFile(const std::string& path) { - std::ifstream file(path, std::ios::binary); - if (!file) throw std::runtime_error("Failed to open file: " + path); - return std::vector((std::istreambuf_iterator(file)), {}); -} - -// XOR 两段数据 -std::vector KeyManagerS::xorBuffers(const std::vector& a, const std::vector& b) { - size_t len = std::min(a.size(), b.size()); - std::vector out(len); - for (size_t i = 0; i < len; ++i) - out[i] = a[i] ^ b[i]; - return out; -} - -// 计算 HMAC-SHA256 -std::vector KeyManagerS::hmac_sha256(const std::vector& key, - const std::vector& message) { - unsigned char* result; - unsigned int len = SHA256_DIGEST_LENGTH; - result = HMAC(EVP_sha256(), key.data(), key.size(), message.data(), message.size(), nullptr, nullptr); - return std::vector(result, result + len); -} - -// 读取系统主板序列号并转为 16 字节 hash -std::vector KeyManagerS::getSystemIDHash16() { - std::ifstream file("/sys/class/dmi/id/board_serial"); - if (!file) throw std::runtime_error("Failed to read board_serial."); - std::ostringstream oss; - oss << file.rdbuf(); - std::string id = oss.str(); - - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256(reinterpret_cast(id.data()), id.size(), hash); - return std::vector(hash, hash + 16); // 只取前16字节 -} - -void KeyManagerS::getRootKey(unsigned char *key, size_t len) { - auto A = readBinaryFile("/new_enc/kms_root/frag_a"); - auto B = readBinaryFile("/new_enc/kms_root/frag_b"); - auto C = readBinaryFile("/new_enc/kms_root/frag_c"); - - if (A.size() != B.size() || A.size() != C.size() || A.size() != 16) - throw std::runtime_error("All key fragments must be 16 bytes."); - - // Step 2: A ⊕ B = X - auto X = xorBuffers(A, B); - - // Step 3: HMAC(C, X) = Y - auto Y_full = hmac_sha256(C, X); // 32字节 - - // Step 4: 取前16字节,和主板ID派生出的16字节 hash 做 XOR - auto Y16 = std::vector(Y_full.begin(), Y_full.begin() + 16); - auto sysID = getSystemIDHash16(); - -// auto FinalKey = xorBuffers(Y16, sysID); - auto FinalKey = xorBuffers(Y16, sysID); - for (size_t i = 0; i < len; ++i) { - key[i] = FinalKey[i]; - } -} - -bool KeyManagerS::setPath(const char *path) { - if (path == nullptr || strlen(path) == 0) { - return false; - } - _path = std::string(path); - return true; -} - -bool KeyManagerS::setKeyPath(const char *key_path) { - if (key_path == nullptr || strlen(key_path) == 0) { - return false; - } - _key_path = std::string(key_path); - return true; -} - -void KeyManagerS::setInfoUser(const std::string &user_name) { - _info.user_name = user_name; -} - -void KeyManagerS::setInfoDb(const std::string &db_name) { - _info.db_name = db_name; -} - -void KeyManagerS::setInfoTable(const std::string &table_name) { - _info.table_name = table_name; -} - -void KeyManagerS::setInfoCol(const std::string &col_name) { - _info.col_name.push(col_name); -} - -void KeyManagerS::setInfoDekTmp(const std::string &col_name, const std::string &dek_tmp) { - _info.dek_store_tmp[col_name] = dek_tmp; -} - -void KeyManagerS::clearDek() { - _info.dek_store_tmp.clear(); - _info.dek_table_level_tmp.clear(); - _info.col_name = std::queue(); -} - -void KeyManagerS::clearDekForUpdate() { - _info.dek_store_tmp_for_update.clear(); - _info.dek_table_level_for_update.clear(); -} - -std::string KeyManagerS::getInfoUser() { - return _info.user_name; -} - -std::string KeyManagerS::getInfoDb() { - return _info.db_name; -} - -std::string KeyManagerS::getInfoTable() { - return _info.table_name; -} - -std::string KeyManagerS::getInfoCol() { - if (!_info.col_name.empty()) { - auto tmp = _info.col_name.front(); - _info.col_name.pop(); - return tmp; - } - return ""; -} - -void KeyManagerS::setDekTableLevel(const std::string &dek) { - _info.dek_table_level_tmp = dek; -} - -void KeyManagerS::getDekTableLevel(std::string &dek) { - dek = _info.dek_table_level_tmp; -} - -void KeyManagerS::getDekByCol(const std::string &col_name, std::string &dek_tmp) { - if(_info.dek_store_tmp.find(col_name) != _info.dek_store_tmp.end()){ - dek_tmp = _info.dek_store_tmp[col_name]; - }else{ - dek_tmp = _info.dek_table_level_tmp; - } - -} - -bool KeyManagerS::createDek(std::string &col_dek, const std::string &column_name) { - col_dek.clear(); - return createDerivedDek(col_dek, column_name); -} - -bool KeyManagerS::createDerivedDek(std::string& dek, const std::string& column_name) { - // 获取当前用户的CMK - std::string cmk; - if (!getCmkByUsername(_info.user_name, cmk)) { - return false; - } - - // 从CMK派生DEK,使用传入的列名作为盐值 - dek = deriveKey(cmk, column_name); - - // 使用CMK加密派生的DEK - encryptDek(dek, cmk); - return true; -} - -//TODO 更新store会出错的条件 -bool KeyManagerS::storeCmk(CMK &cmk, bool rotate=false) { - - //判断该用户是否已有CMK - if (hasCmk(cmk._user_name) && !rotate) { - std::cout << cmk._user_name << " already has a cmk." << std::endl; - return false; - } - //printf("cmk._cmk_data_plain: %s\n", cmk._cmk_data.c_str()); - - //存储之前先加密_cmk_data,让它以密文形式存储 - encryptKey(cmk._cmk_data); - - //更新cmk数组 - _data["cmk"][std::to_string(cmk._key_id)] = { - {"user", cmk._user_name}, - {"length", cmk._length}, - {"struct", cmk._struct}, - {"alg", cmk._alg}, - {"cmk_data", cmk._cmk_data}, - {"rotate_period", cmk._rotate_period}, - {"create_time", cmk._create_time}, - {"is_rotated", cmk._is_rotated}, - {"is_primary_version", cmk._is_primary_version} - }; - - //更新index - _data["index"][cmk._user_name] = cmk._key_id; - - //更新current_id - _data["current_id"] = cmk._key_id + 1; - save(); - init(); - return true; -} - -bool KeyManagerS::save() { - std::ofstream outFile(_path); - if (outFile.is_open()) { - outFile << _data.dump(4); - outFile.close(); - } - return true; -} - -bool KeyManagerS::hasCmk(const std::string &user_name) const { - if (_data["index"].contains(user_name)) { - return true; - } - return false; -} - -bool -KeyManagerS::createCmk(const std::string &user_name, int rotate_period, CMK &new_cmk, KeyStruct ks, AlgorithmType alg) { - new_cmk._alg = alg; - new_cmk._struct = ks; - new_cmk._user_name = user_name; - new_cmk._create_time = time(nullptr); - new_cmk._rotate_period = rotate_period; - new_cmk._is_rotated = false; //新密钥状态未被轮转 - new_cmk._is_primary_version = true; //新密钥设为主版本 - //创建时初始化CMK轮转状态 - cmk_auto_rotate_status[user_name] = false; - if (getRandomCmk(new_cmk._cmk_data, alg, new_cmk._length)) { - //TODO :use log - printf("getRandomCmk successfully!\n"); - printf("cmk_data_plain: %s\n", new_cmk._cmk_data.c_str()); - } else { -// printf("getRandomCmk error!\n"); - return false; - }; - new_cmk._key_id = _data["current_id"]; - return true; -} - -bool KeyManagerS::deleteCmk(const std::string &user_name) { - if (!hasCmk(user_name)) { - std::cout << "No CMK found for user: " << user_name << std::endl; - return false; - } - - int cmk_id = _data["index"][user_name]; - // 修改CMk主版本状态 - _data["cmk"][std::to_string(cmk_id)]["is_primary_version"] = false; - //删除index - _data["index"].erase(user_name); - //若该用户CMK自动轮转进程开启中,将对应进程关闭,再删除自动轮转状态 - if (cmk_auto_rotate_status[user_name] == true) { - pid_t pid = cmk_auto_rotate_pids[user_name]; - kill(pid, SIGTERM); - std::cout << "The background process for CMK_auto_rotate (PID: " << pid << ", User: " << user_name << ") stops." << std::endl; - } - //删除当前用户的cmk自动轮转状态 - cmk_auto_rotate_status.erase(user_name); - saveAutoRotateStatus(); - save(); - return true; -} - -bool KeyManagerS::getRandomCmk(std::string &_cmk_data, AlgorithmType alg, int &length) { - switch (alg) { - case AES128: - case SM4: - length = 16; - break; - default: - return false; - } - _rand(_cmk_data, length); - return true; -} - -bool KeyManagerS::getRandomDek(std::string &_dek_data) { - int tmp_length = 16; - _rand(_dek_data, tmp_length); - std::string cmk_for_encrypt; - getCmkByUsername(_info.user_name, cmk_for_encrypt); - encryptDek(_dek_data, cmk_for_encrypt); - return true; -} - -void KeyManagerS::_rand(std::string &rand, int length_in_bytes) { - int cur = 0; - rand.resize(length_in_bytes); // 确保 rand 有足够的空间 - - // 使用更高质量的随机数生成器 - std::random_device rd; - std::mt19937 gen(rd()); // 初始化随机数生成器 - std::uniform_int_distribution<> dis(0, 255); // 生成范围在 [0, 255] 之间的随机数 - - while (cur < length_in_bytes) { - auto random = dis(gen); // 获取一个随机字节 - if (random >= 32 && random <= 126) // 进一步限制生成的字节范围 - { - rand[cur] = static_cast(random); - cur++; - } else { - continue; - } - } -} - -bool KeyManagerS::getCmkByUsername(const std::string &user_name, std::string &new_cmk) { - if (user_name.empty()) { - return false; - } - if (!hasCmk(user_name)) { - return false; - } - new_cmk = _data["cmk"][std::to_string((int) _data["index"][user_name])]["cmk_data"]; - decryptKey(new_cmk); - return true; -} - -void KeyManagerS::setCurrentCmk(std::string &cur_cmk) { - _cmk = cur_cmk; -} - -bool KeyManagerS::encryptDek(std::string &ori_key, const std::string &cmk) { - constexpr int key_size = 16; - std::string string_key = cmk; - unsigned char key[key_size] = {0}; - for (size_t i = 0; i < 15; i++) { - key[i] = static_cast(string_key[i]); - } - int ori_key_len = ori_key.size(); - int block_size = AES_BLOCK_SIZE; - AES_KEY encrypt_key; - if (ori_key_len % block_size != 0) { - int padding_len = block_size - (ori_key_len % block_size); - ori_key.append(padding_len, '\0'); // 填充ori_key - } - if (AES_set_encrypt_key(key, 128, &encrypt_key) < 0) { - std::cerr << "Failed to set AES encryption key!" << std::endl; - return false; - } - std::string encrypted(ori_key.size(), '\0'); - unsigned char *input_data = reinterpret_cast(&ori_key[0]); - unsigned char *output_data = reinterpret_cast(&encrypted[0]); - - for (size_t i = 0; i < ori_key.size(); i += block_size) { - AES_ecb_encrypt(input_data + i, output_data + i, &encrypt_key, AES_ENCRYPT); - } - //为了实现存储json改为base64编码,KeyStruct _struct编码结构是否需要修改? - std::string base64_encrypted = base64_encode(reinterpret_cast(encrypted.c_str()), - encrypted.size()); - ori_key = base64_encrypted; -} - -bool KeyManagerS::decryptDek(std::string &ori_key, const std::string &cmk) { - constexpr int key_size = 16; - std::string string_key = cmk; - unsigned char key[key_size] = {0}; - for (size_t i = 0; i < 15; i++) { - key[i] = static_cast(string_key[i]); - } - int ori_key_len = ori_key.size(); - int block_size = AES_BLOCK_SIZE; - std::string decoded = base64_decode(ori_key); - AES_KEY decrypt_key; - if (AES_set_decrypt_key(key, 128, &decrypt_key) < 0) { - std::cerr << "Failed to set AES decryption key!" << std::endl; - return false; - } - std::string decrypted(decoded.size(), '\0'); - unsigned char *input_data = reinterpret_cast(&decoded[0]); - unsigned char *output_data = reinterpret_cast(&decrypted[0]); - - for (size_t i = 0; i + block_size <= decoded.size(); i += block_size) { - AES_ecb_encrypt(input_data + i, output_data + i, &decrypt_key, AES_DECRYPT); - } - // 去除填充的\0 - size_t last_non_null_pos = decrypted.find_last_not_of('\0'); - if (last_non_null_pos != std::string::npos) { - decrypted.erase(last_non_null_pos + 1); // 删除从最后一个非零字符后的所有填充字符 - } - ori_key = decrypted; - return true; - -} - -bool KeyManagerS::encryptKey(std::string &ori_key) { - constexpr int key_size = 16; - int block_size = AES_BLOCK_SIZE; - int ori_key_len = ori_key.size(); - - if (ori_key_len % block_size != 0) { - int padding_len = block_size - (ori_key_len % block_size); - ori_key.append(padding_len, '\0'); // 填充ori_key - } - // 设置密钥 - unsigned char key[key_size] = {0}; - getRootKey(key, key_size); - // std::ifstream file(_key_path, std::ios::binary); - // if (file) { - // file.read(reinterpret_cast(key), key_size); - - // size_t bytesRead = file.gcount(); - // if (bytesRead < key_size) { - // std::cerr << "warning: domiankeysize is shorter than 16, filling with 0!" << std::endl; - // } - // file.close(); - // } else { - // std::cerr << "cannot open domainkey!" << std::endl; - // return -1; - // } - // 创建加密上下文 - AES_KEY encrypt_key; - if (AES_set_encrypt_key(key, 128, &encrypt_key) < 0) { - std::cerr << "Failed to set AES encryption key!" << std::endl; - return false; - } - std::string encrypted(ori_key.size(), '\0'); - unsigned char *input_data = reinterpret_cast(&ori_key[0]); - unsigned char *output_data = reinterpret_cast(&encrypted[0]); - - for (size_t i = 0; i < ori_key.size(); i += block_size) { - AES_ecb_encrypt(input_data + i, output_data + i, &encrypt_key, AES_ENCRYPT); - } - //为了实现存储json改为base64编码,KeyStruct _struct编码结构是否需要修改? - std::string base64_encrypted = base64_encode(reinterpret_cast(encrypted.c_str()), - encrypted.size()); - ori_key = base64_encrypted; - - return true; -} - -bool KeyManagerS::decryptKey(std::string &ori_key) { - const int key_size = 16; - int block_size = AES_BLOCK_SIZE; - - std::string decoded = base64_decode(ori_key); - - unsigned char key[key_size] = {0}; - getRootKey(key, key_size); - // std::ifstream file(_key_path, std::ios::binary); - // if (file) { - // file.read(reinterpret_cast(key), key_size); - - // size_t bytesRead = file.gcount(); - // if (bytesRead < key_size) { - // std::cerr << "warning: domiankeysize is shorter than 16, filling with 0!" << std::endl; - // } - // file.close(); - // } else { - // std::cerr << "cannot open domainkey!" << std::endl; - // return false; - // } - - - AES_KEY decrypt_key; - if (AES_set_decrypt_key(key, 128, &decrypt_key) < 0) { - std::cerr << "Failed to set AES decryption key!" << std::endl; - return false; - } - - std::string decrypted(decoded.size(), '\0'); - unsigned char *input_data = reinterpret_cast(&decoded[0]); - unsigned char *output_data = reinterpret_cast(&decrypted[0]); - - for (size_t i = 0; i + block_size <= decoded.size(); i += block_size) { - AES_ecb_encrypt(input_data + i, output_data + i, &decrypt_key, AES_DECRYPT); - } - // 去除填充的\0 - size_t last_non_null_pos = decrypted.find_last_not_of('\0'); - if (last_non_null_pos != std::string::npos) { - decrypted.erase(last_non_null_pos + 1); // 删除从最后一个非零字符后的所有填充字符 - } - ori_key = decrypted; - - return true; - -} - -std::string KeyManagerS::base64_encode(const unsigned char *data, size_t length) { - // 计算编码后的长度 (每3字节编码成4字节,所以需要根据长度调整) - size_t encode_length = 4 * ((length + 2) / 3); - std::string encoded; - encoded.resize(encode_length); - - int actual_size = EVP_EncodeBlock(reinterpret_cast(&encoded[0]), data, length); - - if (actual_size < 0) { - throw std::runtime_error("Base64 encoding failed"); - } - - return encoded; -} - -std::string KeyManagerS::base64_decode(const std::string &encoded) { - size_t decode_length = encoded.size() * 3 / 4; - - // 在解码时,OpenSSL 会根据 Base64 编码内容自动填充 \0 - std::string decoded; - decoded.resize(decode_length); - - int actual_size = EVP_DecodeBlock(reinterpret_cast(&decoded[0]), - reinterpret_cast(encoded.c_str()), - encoded.size()); - - if (actual_size < 0) { - throw std::runtime_error("Base64 decoding failed"); - } - decoded.resize(actual_size); - return decoded; -} - -void KeyManagerS::setDekOnlyForOre(const std::string &dek) { - _dek_only_for_ore.push(dek); -} - -char *KeyManagerS::getDekOnlyForOre() { - auto s = _dek_only_for_ore.front(); - char *res = new char[s.length() + 1]; - std::strcpy(res, s.c_str()); - return res; -} - -void KeyManagerS::clearDekOnlyForOre() { - _dek_only_for_ore.pop(); -} - -//手动轮转函数 -bool KeyManagerS::rotateCmkNow(const std::string &user_name) { - if (!hasCmk(user_name)) { - std::cerr << "No CMK found for user: " << user_name << std::endl; - return false; - } - - //获取old_cmk信息 - int old_cmk_id = _data["index"][user_name]; - json old_cmk = _data["cmk"][std::to_string(old_cmk_id)]; - int rotate_period = old_cmk["rotate_period"]; - std::string old_cmk_data = old_cmk["cmk_data"]; - - //解密old_cmk - decryptKey(old_cmk_data); - - //取DEK信息并解密 - bool hasDEK = false; - //检查是否有DEK - connectionRotationSelectDek(user_name, old_cmk_data, _dek_tmp, hasDEK); - - - //修改旧cmk信息 - old_cmk["is_rotated"] = true; - old_cmk["is_primary_version"] = false; - - //保存修改后信息 - _data["cmk"][std::to_string(old_cmk_id)] = old_cmk; - - //创建新cmk - CMK new_cmk; - if (createCmk(user_name, rotate_period, new_cmk)) { - if (hasDEK) { - //重加密DEK - connectionRotationUpdataDek(user_name, new_cmk._cmk_data, _dek_tmp); - } else { - std::cout << "The user has no DEK now, skipping DEK update." << std::endl; - } - - //new_cmk._next_rotate_time = now + 30 * 24 * 60 * 60; // 30天后 - storeCmk(new_cmk, true); - return true; - } - return false; -} - -// 读取持久化的自动轮转状态 -void KeyManagerS::loadAutoRotateStatus() { - std::ifstream file(_cmk_auto_rotate_status_path, std::ios::in); - if (file.is_open()) { - json cmk_rotate_status = json::parse(file); - file.close(); - for (auto &entry : cmk_rotate_status.items()) { - cmk_auto_rotate_status[entry.key()] = entry.value()["status"]; - cmk_auto_rotate_pids[entry.key()] = entry.value()["pid"]; - } - } -} - -// 保存自动轮转状态到文件 -void KeyManagerS::saveAutoRotateStatus() { - json cmk_rotate_status; - for (auto &entry : cmk_auto_rotate_status) { - cmk_rotate_status[entry.first] = { - {"status", entry.second}, - {"pid", cmk_auto_rotate_pids[entry.first]} - }; - } - std::ofstream outFile(_cmk_auto_rotate_status_path); - if (outFile.is_open()) { - outFile << cmk_rotate_status.dump(4); - outFile.close(); - } -} - -// 进程函数,用于自动轮转CMK -void KeyManagerS::autoRotateProcess(const std::string &user_name) { - signal(SIGTTOU, SIG_IGN); // 忽略挂起信号 - signal(SIGTTIN, SIG_IGN); - - int check_period = 10; // 检查间隔天数 - int check_period_hours = check_period * 24; - std::time_t check_time = std::time(nullptr); - - // 使用互斥锁保护进程 - static std::mutex check_mutex; - - while (true) { - std::lock_guard lock(check_mutex); - - std::time_t now = std::time(nullptr); - tm *localtime = std::localtime(&now); - - //0点整检查 - if (localtime->tm_hour == 0 && localtime->tm_min == 0 && localtime->tm_sec == 0) { - if (std::difftime(now, check_time) >= check_period * 24 * 60 * 60) { - std::cout << "Checking CMK automatical rotation for user: " << user_name << " (PID: " << getpid() << ")" << std::endl; - - // 读取CMK信息开始检查 - std::ifstream file(_path, std::ios::in); - if (file.is_open()) { - json data = json::parse(file); - file.close(); - - int cmk_id = data["index"][user_name]; - json cmk = data["cmk"][std::to_string(cmk_id)]; - int rotate_period = cmk["rotate_period"]; - std::time_t create_time = cmk["create_time"]; - - // 计算时间差 - std::time_t time_diff = std::difftime(now, create_time); - - // 如果时间差大于或等于轮转周期,则进行轮转 - if (time_diff >= rotate_period * 24 * 60 * 60) { - std::cout << "Rotating CMK automatically for user: " << user_name << std::endl; - rotateCmkNow(user_name); - // 轮转时,等待3秒以避免高频检查 - std::this_thread::sleep_for(std::chrono::seconds(3)); - } - } - check_time = std::time(nullptr); - //防止查询阻塞 - std::this_thread::sleep_for(std::chrono::seconds(3)); - } - } - } -} - -//处理自动轮转命令 -bool KeyManagerS::handleAutoRotateCmd(std::string *auto_rotate_action, const std::string &user_name) { - std::string action = auto_rotate_action->c_str(); - //开启自动轮转 - if (action == "on") { - // 检查是否已经存在自动轮转进程 - if (cmk_auto_rotate_status[user_name] == true) { - std::cout << "CMK_auto_rotate is already enabled for user: " << user_name << std::endl; - return true; - } - - // 创建新的后台进程 - pid_t pid = fork(); - if (pid == 0) { - // 子进程 - setsid();//脱离终端控制 - std::cout << "The background process for CMK_auto_rotate starts, and the PID is " << getpid() << "." << std::endl; - autoRotateProcess(user_name); - exit(0); - return true; - } else if (pid > 0) { - // 父进程 - cmk_auto_rotate_pids[user_name] = pid; - cmk_auto_rotate_status[user_name] = true; - saveAutoRotateStatus();//保存状态 - std::cout << "CMK_auto_rotate enabled for user: " << user_name << std::endl; - return true; - } else { - std::cerr << "Failed to create CMK_auto_rotate process for user: " << user_name << std::endl; - return false; - } - } - //关闭自动轮转 - else if (action == "off") { - // 关闭自动轮转进程 - if (cmk_auto_rotate_status[user_name] == true) { - pid_t pid = cmk_auto_rotate_pids[user_name]; - if (kill(pid, SIGTERM) == 0) { - cmk_auto_rotate_status[user_name] = false; - saveAutoRotateStatus(); - std::cout << "The background process for CMK_auto_rotate (PID: " << pid << ") stops." << std::endl; - std::cout << "CMK_auto_rotate is disabled now for user: " << user_name << std::endl; - return true; - } else { - std::cerr << "Failed to terminate CMK_auto-rotate process for user: " << user_name << std::endl; - return false; - } - } - //还未开启过或已关闭自动轮转进程 - else { - std::cout << "CMK_auto_rotate is already disabled for user: " << user_name << std::endl; - return true; - } - } - // 查询自动轮转状态 - else if (action == "status") { - if (cmk_auto_rotate_status[user_name] == true) { - std::cout << "CMK_auto_rotate is enabled for user: " << user_name << std::endl; - } else { - std::cout << "CMK_auto_rotate is disabled for user: " << user_name << std::endl; - } - return true; - } - else { - std::cerr << "Invalid operation for CMK_auto_rotate command." << std::endl; - return false; - } -} - -//根据用户名获取CMK自动轮转状态 -bool KeyManagerS::getCmkAutoRotateStatusByUsername(const std::string &user_name) { - if (user_name.empty()) { - return false; - } - if (!hasCmk(user_name)) { - return false; - } - return cmk_auto_rotate_status[user_name]; -} - -bool KeyManagerS::describeCmk(const std::string &user_name, json &result, bool decrypt) { - if (!hasCmk(user_name)) { - return false; - } - - int key_id = _data["index"][user_name]; - if (!_data["cmk"].contains(std::to_string(key_id))) { - return false; - } - - result = _data["cmk"][std::to_string(key_id)]; - - if (decrypt) { - std::string cmk_data = result["cmk_data"]; - decryptKey(cmk_data); - result["cmk_data_plain"] = cmk_data; - } - - return true; -} - -void KeyManagerS::setDekTableLevelForUpdate(const std::string &dek) { - _info.dek_table_level_for_update = dek; -} - -void KeyManagerS::getDekTableLevelForUpdate(std::string &dek) { - dek = _info.dek_table_level_for_update; -} - -void KeyManagerS::setDekStoreTmpForUpdate(const std::string &col_name, const std::string &dek_tmp) { - _info.dek_store_tmp_for_update[col_name] = dek_tmp; -} - -void KeyManagerS::getDekStoreTmpForUpdate(const std::string &col_name, std::string &dek_tmp) { - if(_info.dek_store_tmp_for_update.find(col_name) != _info.dek_store_tmp_for_update.end()){ - dek_tmp = _info.dek_store_tmp_for_update[col_name]; - }else{ - dek_tmp = _info.dek_table_level_for_update; - } -} - -std::string KeyManagerS::getCurrentCmk() { - return _cmk; -} - -void KeyManagerS::getAllDekStoreTmpForUpdate(std::unordered_map &column_deks){ - column_deks = _info.dek_store_tmp_for_update; -} - -bool KeyManagerS::isRotateCmd(){ - return _info.dek_table_level_for_update != "" || _info.dek_store_tmp_for_update.size() != 0; -} - -KeyManagerS::KeyManagerS(const std::string &file_path, const std::string &key_path, const std::string &cmk_auto_rotate_status_path) { - _path = file_path; - _key_path = key_path; - _cmk_auto_rotate_status_path = cmk_auto_rotate_status_path; -} - -KeyManagerS::~KeyManagerS() { - save(); -} - -static thread_local std::unique_ptr cmk_mapper; - -void cmk_mapperInit(const char *file_path, const char *key_path, const char *cmk_auto_rotate_status_path) { - cmk_mapper.reset(new KeyManagerS(file_path, key_path, cmk_auto_rotate_status_path)); - cmk_mapper->init(); - cmk_mapper->loadAutoRotateStatus(); -} - -bool cmk_mapperHasCmk(const std::string &user_name) { - if (cmk_mapper->hasCmk(user_name)) { - return true; - } -} - -bool cmk_mapperCreateCmk(const std::string &user_name, int rotate_period, CMK &new_cmk) { - if (cmk_mapper->createCmk(user_name, rotate_period, new_cmk)) { - return true; - } - return false; -} - -bool cmk_mapperDeleteCmk(const std::string &user_name) { - if (cmk_mapper->deleteCmk(user_name)) { - return true; - } - return false; -} - -bool cmk_mapperStoreCmk(CMK &cmk) { - if (cmk_mapper->storeCmk(cmk)) { - return true; - } - return false; -} - -bool cmk_mapperGetCmkByUsername(const std::string &user_name, std::string &new_cmk) { - if (cmk_mapper->getCmkByUsername(user_name, new_cmk)) { - return true; - } - return false; -} - -void cmk_mapperSetCurrentCmk(std::string &cur_cmk) { - cmk_mapper->setCurrentCmk(cur_cmk); -} - -void cmk_mapperSetInfoUser(const std::string &user_name) { - cmk_mapper->setInfoUser(user_name); -} - -void cmk_mapperSetInfoDb(const std::string &db_name) { - cmk_mapper->setInfoDb(db_name); -} - -void cmk_mapperSetInfoTable(const std::string &table_name) { - cmk_mapper->setInfoTable(table_name); -} - -void cmk_mapperSetInfoCol(const std::string &col_name) { - cmk_mapper->setInfoCol(col_name); -} - -void cmk_mapperSetInfoDekTmp(const std::string &col_name, const std::string &dek_tmp) { - cmk_mapper->setInfoDekTmp(col_name, dek_tmp); -} - -void cmk_mapperGetDekByCol(const std::string &col_name, std::string &dek_tmp) { - cmk_mapper->getDekByCol(col_name, dek_tmp); -} - -void cmk_mapperClearDek() { - cmk_mapper->clearDek(); -} - -void cmk_mapperClearDekForUpdate(){ - cmk_mapper->clearDekForUpdate(); -} - -void cmk_mapperEncryptDek(std::string &ori_key, const std::string &cmk) { - cmk_mapper->encryptDek(ori_key, cmk); -} - -void cmk_mapperDecryptDek(std::string &ori_key, const std::string &cmk) { - cmk_mapper->decryptDek(ori_key, cmk); -} - -std::string cmk_mapperGetInfoUser() { - return cmk_mapper->getInfoUser(); -} - -std::string cmk_mapperGetInfoDb() { - return cmk_mapper->getInfoDb(); -} - -std::string cmk_mapperGetInfoTable() { - return cmk_mapper->getInfoTable(); -} - -std::string cmk_mapperGetInfoCol() { - return cmk_mapper->getInfoCol(); -} - -bool cmk_mapperCreateDek(std::string &col_dek, const std::string &column_name) { - return cmk_mapper->createDek(col_dek, column_name); -} - -bool cmk_mapperNewConnectionTest() { - -} - -void cmk_mapperSetDekOnlyForOre(const std::string &dek) { - cmk_mapper->setDekOnlyForOre(dek); -} - -char *cmk_mapperGetDekOnlyForOre() { - return cmk_mapper->getDekOnlyForOre(); -} - -void cmk_mapperClearDekOnlyForOre() { - cmk_mapper->clearDekOnlyForOre(); -} - -void cmk_mapperSetDekTableLevel(const std::string &dek) { - cmk_mapper->setDekTableLevel(dek); -} - -void cmk_mapperGetDekTableLevel(std::string &dek) { - cmk_mapper->getDekTableLevel(dek); -} - -//(封装)CMK手动轮转 -bool cmk_mapperRotateCmkNow(const std::string &user_name) { - cmk_mapper->rotateCmkNow(user_name); -} - -//(封装)自动轮转命令处理 -bool cmk_mapperHandleAutoRotateCmd(std::string *auto_rotate_action, const std::string &user_name) { - cmk_mapper->handleAutoRotateCmd(auto_rotate_action, user_name); -} - -//(封装)根据用户名获取自动轮转状态 -bool cmk_mapperGetCmkAutoRotateStatusByUsername(const std::string &user_name) { - if (cmk_mapper->getCmkAutoRotateStatusByUsername(user_name)) { - return true; - } - return false; -} - -bool cmk_mapperDescribeCmk(const std::string &user_name, json &result, bool decrypt) { - if (cmk_mapper->describeCmk(user_name, result, decrypt)) { - return true; - } - return false; -} - -void cmk_mapperSetDekTableLevelForUpdate(const std::string &dek) { - cmk_mapper->setDekTableLevelForUpdate(dek); -} - -void cmk_mapperGetDekTableLevelForUpdate(std::string &dek) { - cmk_mapper->getDekTableLevelForUpdate(dek); -} - -void cmk_mapperSetDekStoreTmpForUpdate(const std::string &col_name, const std::string &dek_tmp) { - cmk_mapper->setDekStoreTmpForUpdate(col_name, dek_tmp); -} - -void cmk_mapperGetDekStoreTmpForUpdate(const std::string &col_name, std::string &dek_tmp) { - cmk_mapper->getDekStoreTmpForUpdate(col_name, dek_tmp); -} - -std::string cmk_mapperGetCurrentCmk(){ - return cmk_mapper->getCurrentCmk(); -} - -void cmk_mapperGetAllDekStoreTmpForUpdate(std::unordered_map &column_deks){ - cmk_mapper->getAllDekStoreTmpForUpdate(column_deks); -} - -bool cmk_mapperIsRotateCmd(){ - cmk_mapper->isRotateCmd(); -} - -std::vector KeyManagerS::sha256(const std::string& input) { - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - SHA256_Update(&sha256, input.c_str(), input.length()); - SHA256_Final(hash, &sha256); - return std::vector(hash, hash + SHA256_DIGEST_LENGTH); -} - -std::string KeyManagerS::deriveKey(const std::string& master_key, const std::string& column_name) { - // 使用列名生成盐值 - std::string salt = generateSalt(column_name); - - // 加入时间戳(ms) - auto now = std::chrono::system_clock::now(); - auto now_ms = std::chrono::duration_cast(now.time_since_epoch()); - - // 组合主密钥、盐值和时间戳 - std::stringstream combined; - combined << master_key << salt << "_" << now_ms.count(); - - // 使用SHA-256进行密钥派生 - auto derived = sha256(combined.str()); - - // 将派生的密钥转换为可打印字符串 - std::stringstream ss; - for(unsigned char byte : derived) { - if(byte >= 32 && byte <= 126) { // 只使用可打印字符 - ss << static_cast(byte); - } else { - ss << static_cast((byte % (126-32+1)) + 32); // 映射到可打印字符范围 - } - } - - // 确保输出长度为16字节 - std::string result = ss.str().substr(0, 16); - return result; -} - -std::string KeyManagerS::generateSalt(const std::string& column_name) { - // 使用列名作为盐值的基础 - std::string base = "KMS_SALT_COL_"; - if (column_name.empty()) { - // 如果列名为空,说明是表级密钥 - base += "TABLE_KEY"; - } else { - base += column_name; - } - return base; -} \ No newline at end of file diff --git a/src/KMS/KeyManagementService.hpp.bk b/src/KMS/KeyManagementService.hpp.bk deleted file mode 100755 index c1bc324..0000000 --- a/src/KMS/KeyManagementService.hpp.bk +++ /dev/null @@ -1,346 +0,0 @@ -// -// Created by 曲晓阳 on 24-11-18. -// -#ifndef KMS_KEYMANAGEMENTSERVICE_HPP -#define KMS_KEYMANAGEMENTSERVICE_HPP - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include "json.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#define AES_BLOCK_SIZE 16 - -using json = nlohmann::json; - -// 密钥类型 -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 col_name; - std::unordered_map dek_store_tmp; - std::unordered_map dek_store_tmp_for_update; - std::string dek_table_level_tmp; - std::string dek_table_level_for_update; -} DbInfo; - -class KeyManagerS { -private: - json _data; //解析出的json数据 - std::string _path; //cmk信息,json文件位置 - std::string _key_path; //加密cmk所用密钥的位置 - std::string _cmk; //当前用户的cmk(以sql为单位) - DbInfo _info; - std::queue _dek_only_for_ore; - - std::map _dek_tmp; //用于临时存储解密后DEK - - std::string deriveKey(const std::string& master_key, const std::string& column_name); - std::vector sha256(const std::string& input); - std::string generateSalt(const std::string& column_name); - bool createDerivedDek(std::string& dek, const std::string& column_name); - - std::string _cmk_auto_rotate_status_path; //CMK自动轮转状态存储文件路径 - - //用于存储CMK自动轮转的进程 ID 和状态 - std::map cmk_auto_rotate_pids; - std::map cmk_auto_rotate_status; - -public: - KeyManagerS(const std::string &file_path, const std::string &key_path, const std::string &cmk_auto_rotate_status_path); - - ~KeyManagerS(); - - bool init(); - - std::vector readBinaryFile(const std::string &path); - - std::vector xorBuffers(const std::vector &a, const std::vector &b); - - std::vector hmac_sha256(const std::vector &key, - const std::vector &message); - - std::vector getSystemIDHash16(); - - void getRootKey(unsigned char *key, size_t len); - - bool setPath(const char *path); - - bool setKeyPath(const char *key_path); - - void setInfoUser(const std::string &user_name); - - void setInfoDb(const std::string &db_name); - - void setInfoTable(const std::string &table_name); - - void setInfoCol(const std::string &col_name); - - void setInfoDekTmp(const std::string &col_name, const std::string &dek_tmp); - - void clearDek(); - - void clearDekForUpdate(); - - std::string getInfoUser(); - - std::string getInfoDb(); - - std::string getInfoTable(); - - std::string getInfoCol(); - - void getDekByCol(const std::string &col_name, std::string &dek_tmp); - - bool createDek(std::string &col_dek, const std::string &column_name); - - bool storeCmk(CMK &cmk, bool rotate); - - bool save(); - - bool hasCmk(const std::string &user_name) const; - - bool createCmk(const std::string &user_name, int rotate_period, CMK &new_cmk, KeyStruct ks = RAW, - AlgorithmType alg = AES128); - - bool deleteCmk(const std::string &user_name); - - bool getRandomCmk(std::string &_cmk_data, AlgorithmType alg, int &length); - - bool getRandomDek(std::string &_dek_data); - - void setCurrentCmk(std::string &cur_cmk); - - void _rand(std::string &rand, int length_in_bytes); - - //TODO:在合适的地方加入加密和解密CMK - //加密CMK - bool encryptKey(std::string &ori_key); - - bool encryptDek(std::string &ori_key, const std::string &cmk); - - bool decryptDek(std::string &ori_key, const std::string &cmk); - - //解密CMK - bool decryptKey(std::string &ori_key); - - bool getCmkByUsername(const std::string &user_name, std::string &new_cmk); - - std::string base64_encode(const unsigned char *data, size_t length); - - std::string base64_decode(const std::string &encoded); - - void setDekOnlyForOre(const std::string &dek); - - void clearDekOnlyForOre(); - - char *getDekOnlyForOre(); - - void setDekTableLevel(const std::string &dek); - - void getDekTableLevel(std::string &dek); - - //手动轮转函数 - bool rotateCmkNow(const std::string &user_name); - - //加载CMK自动轮转状态 - void loadAutoRotateStatus(); - - //保存CMK自动轮转状态 - void saveAutoRotateStatus(); - - //CMK自动轮转进程函数 - void autoRotateProcess(const std::string &user_name); - - //CMK自动轮转命令处理 - bool handleAutoRotateCmd(std::string *auto_rotate_action, const std::string &user_name); - - //根据用户名获取CMK自动轮转状态 - bool getCmkAutoRotateStatusByUsername(const std::string &user_name); - - bool describeCmk(const std::string &user_name, json &result, bool decrypt); - - void setDekTableLevelForUpdate(const std::string &dek); - - void getDekTableLevelForUpdate(std::string &dek); - - void setDekStoreTmpForUpdate(const std::string &col_name, const std::string &dek_tmp); - - void getDekStoreTmpForUpdate(const std::string &col_name, std::string &dek_tmp); - - std::string getCurrentCmk(); - - void getAllDekStoreTmpForUpdate(std::unordered_map &column_deks); - - bool isRotateCmd(); -}; - -void cmk_mapperInit(const char *file_path, const char *key_path, const char *cmk_auto_rotate_status_path); - -bool cmk_mapperHasCmk(const std::string &user_name); - -bool cmk_mapperCreateCmk(const std::string &user_name, int rotate_period, CMK &new_cmk); - -bool cmk_mapperDeleteCmk(const std::string &user_name); - -bool cmk_mapperStoreCmk(CMK &cmk); - -bool cmk_mapperGetCmkByUsername(const std::string &user_name, std::string &new_cmk); - -void cmk_mapperSetCurrentCmk(std::string &cur_cmk); - -void cmk_mapperSetInfoUser(const std::string &user_name); - -void cmk_mapperSetInfoDb(const std::string &db_name); - -void cmk_mapperSetInfoTable(const std::string &table_name); - -void cmk_mapperSetInfoCol(const std::string &col_name); - -void cmk_mapperSetInfoDekTmp(const std::string &col_name, const std::string &dek_tmp); - -void cmk_mapperGetDekByCol(const std::string &col_name, std::string &dek_tmp); - -void cmk_mapperClearDek(); - -void cmk_mapperClearDekForUpdate(); - -void cmk_mapperEncryptDek(std::string &ori_key, const std::string &cmk); - -void cmk_mapperDecryptDek(std::string &ori_key, const std::string &cmk); - -std::string cmk_mapperGetInfoUser(); - -std::string cmk_mapperGetInfoDb(); - -std::string cmk_mapperGetInfoTable(); - -std::string cmk_mapperGetInfoCol(); - -bool cmk_mapperCreateDek(std::string &col_dek, const std::string &column_name); - -bool cmk_mapperNewConnectionTest(); - -void cmk_mapperSetDekOnlyForOre(const std::string &dek); - -void cmk_mapperClearDekOnlyForOre(); - -char *cmk_mapperGetDekOnlyForOre(); - -void cmk_mapperSetDekTableLevel(const std::string &dek); - -void cmk_mapperGetDekTableLevel(std::string &dek); - -//(封装)手动轮转 -bool cmk_mapperRotateCmkNow(const std::string &user_name); - -//(封装)CMK自动轮转命令处理 -bool cmk_mapperHandleAutoRotateCmd(std::string *auto_rotate_action, const std::string &user_name); - -//(封装)根据用户名获取CMK自动轮转状态 -bool cmk_mapperGetCmkAutoRotateStatusByUsername(const std::string &user_name); - -bool cmk_mapperDescribeCmk(const std::string &user_name, json &result, bool decrypt); - -void cmk_mapperSetDekTableLevelForUpdate(const std::string &dek); - -void cmk_mapperGetDekTableLevelForUpdate(std::string &dek); - -void cmk_mapperSetDekStoreTmpForUpdate(const std::string &col_name, const std::string &dek_tmp); - -void cmk_mapperGetDekStoreTmpForUpdate(const std::string &col_name, std::string &dek_tmp); - -std::string cmk_mapperGetCurrentCmk(); - -void cmk_mapperGetAllDekStoreTmpForUpdate(std::unordered_map &column_deks); - -bool cmk_mapperIsRotateCmd(); - -#endif //KMS_KEYMANAGEMENTSERVICE_HPP \ No newline at end of file diff --git a/src/KMS/PGconnectForDEK.cpp.bk b/src/KMS/PGconnectForDEK.cpp.bk deleted file mode 100755 index 908dffe..0000000 --- a/src/KMS/PGconnectForDEK.cpp.bk +++ /dev/null @@ -1,1089 +0,0 @@ -#include "kms/PGconnectForDEK.h" - - -RotateCommandResult parseRotateCommand(const std::string& command,const std::string &user_name,const std::string &db_name) { - RotateCommandResult result; - result.valid = false; - - std::string current_cmk; - //得到当前用户的cmk - cmk_mapperGetCmkByUsername(user_name, current_cmk); - //存储当前cmk - cmk_mapperSetCurrentCmk(current_cmk); - cmk_mapperSetInfoUser(user_name); - cmk_mapperSetInfoDb(db_name); - - // 创建命令的大写副本用于不区分大小写的匹配,但保留原始命令用于提取名称 - std::string upperCommand = command; - for (char& c : upperCommand) { - c = toupper(c); - } - - // 新的命令格式正则表达式 - std::regex tkPattern(R"(^\s*ROTATE\s+DEK\s+NOW\s+`?(\w+)`?\s+-TK\s*;?\s*$)", std::regex::icase); - std::regex ckPattern(R"(^\s*ROTATE\s+DEK\s+NOW\s+`?(\w+)`?\s+-CK\s+([\w\s,]+)\s*;?\s*$)", std::regex::icase); - std::regex allPattern(R"(^\s*ROTATE\s+DEK\s+NOW\s+`?(\w+)`?\s+-ALL\s*;?\s*$)", std::regex::icase); - - std::smatch matches; - - // 匹配表密钥轮换 (--TK) - /** - * 只轮换表密钥 - */ - if (std::regex_search(command, matches, tkPattern)) { - result.valid = true; - result.type = ROTATE_TABLE; - result.tableName = matches[1].str(); // 保留原始大小写 - return result; - } - - // 匹配列密钥轮换 (--CK) - /** - * 轮换选中列密钥 - */ - if (std::regex_search(command, matches, ckPattern)) { - result.valid = true; - result.type = ROTATE_COLUMNS; - result.tableName = matches[1].str(); // 保留原始大小写 - - // 解析列名列表 - std::string columnsStr = matches[2].str(); // 保留原始大小写 - - // 移除所有空格 - std::string cleanColumnsStr; - for (char c : columnsStr) { - if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { - cleanColumnsStr += c; - } - } - - // 使用逗号分割列名 - size_t pos = 0; - std::string token; - while ((pos = cleanColumnsStr.find(',')) != std::string::npos) { - token = cleanColumnsStr.substr(0, pos); - - if (!token.empty()) { - result.cols_set.insert(token); // 保留原始大小写 - } - cleanColumnsStr.erase(0, pos + 1); - } - - // 添加最后一个列名 - if (!cleanColumnsStr.empty()) { - result.cols_set.insert(cleanColumnsStr); // 保留原始大小写 - } - - // 至少要有一列 - if (result.cols_set.empty()) { - result.valid = false; - result.errorMessage = "列密钥轮换需要至少指定一个列名"; - } - - return result; - } - - // 匹配全部轮换 (--ALL) - /** - * 轮换全部 - */ - if (std::regex_search(command, matches, allPattern)) { - result.valid = true; - result.type = ROTATE_ALL; - result.tableName = matches[1].str(); // 保留原始大小写 - return result; - } - - // 如果没有匹配任何模式 - result.errorMessage = "无效的DEK轮换命令格式"; - return result; -} - -// 使用示例函数 -void printRotateCommandResult(const RotateCommandResult& result) { - if (!result.valid) { - std::cout << "无效命令: " << result.errorMessage << std::endl; - return; - } - - std::cout << "检测到有效命令!" << std::endl; - std::cout << "表名: " << result.tableName << std::endl; - - switch (result.type) { - case ROTATE_ALL: - std::cout << "轮换类型: ALL (表和所有列)" << std::endl; - break; - case ROTATE_TABLE: - std::cout << "轮换类型: TABLE (仅表密钥)" << std::endl; - break; - case ROTATE_COLUMNS: - std::cout << "轮换类型: COLUMNS (仅指定列)" << std::endl; - std::cout << "要轮换的列: "; - for (auto it = result.cols_set.begin();it != result.cols_set.end(); ++ it) { - std::cout << *it; - if (it != result.cols_set.begin()) { - std::cout << ", "; - } - } - std::cout << std::endl; - break; - } -} - -void connectionDelete() { - // 数据库连接信息 - const char *conninfo = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - // 构建删除查询 - std::string query = "DELETE FROM dek_store WHERE "; - query.append("username = '").append(cmk_mapperGetInfoUser()).append("' AND ") - .append("db = '").append(cmk_mapperGetInfoDb()).append("' AND ") - .append("t = '").append(cmk_mapperGetInfoTable()).append("'"); - - query.append(";"); - std::cout << query << std::endl; - const char *query_c = query.c_str(); - - PGresult *res = PQexec(conn, query_c); - // 检查查询状态 - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - fprintf(stderr, "Delete query execution failed: %s\n", PQerrorMessage(conn)); - PQclear(res); - } else { - PQclear(res); // 释放查询结果 - } - - PQfinish(conn); // 关闭数据库连接 -} - -void connectionUpdateDek(RotateCommandResult &cmd) { - // 预先操作 - connectionUpdateDek_Init(cmd); - if(!cmd.errorMessage.empty()) { - std::cout << cmd.errorMessage << std::endl; - return; - } - connectionUpdateDek_Update(cmd); - if(!cmd.errorMessage.empty()) { - std::cout << cmd.errorMessage << std::endl; - return; - } - connectionUpdateDek_Final(cmd); - if(!cmd.errorMessage.empty()) { - std::cout << cmd.errorMessage << std::endl; - return; - } -} - -/** - * 连接数据库 - * 从 map.json 中提取表的所有列为columns - * 从 dek_store 表中提取所有密钥,通过映射得到原列名,记录在 cmd.enc_cols_set 中。 - * - * 根据 cmd.type 有三种处理 - * 1. ROTATE_ALL: 轮换所有列,那么 cmd.cols_set = all_columns - * 2. ROTATE_TABLE: 轮换表级密钥,那么 cmd.cols_set = columns - cmd.enc_colsset - * 3. ROTATE_COLUMNS: 轮换指定列密钥,那么 cmd.cols_set = col1, col2, ... - * - * 后续通过cmd.cols 构造查询和更新 - */ -void connectionUpdateDek_Init(RotateCommandResult &cmd) { - // 数据库连接信息 - const char *conninfo = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) { - cmd.errorMessage = "Connection to database failed;\n"; - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - std::string file_path = "/etc/encryptsql/map.json"; - json j = read_json_from_file(file_path); - - std::set all_columns = get_all_columns(cmd.tableName, j); - cmd.col_map = get_column_mapping(cmd.tableName,j); - - // 移除非密文列 - std::cout << "表 " + cmd.tableName + " 的非密文列有: " ; - for (auto it = all_columns.begin(); it != all_columns.end(); ) { - const auto& col = *it; - if (cmd.col_map[col] == col) { - // 移除非密文列 - it = all_columns.erase(it); // erase 会返回下一个元素的迭代器 - } else { - // 获得该列的类型 - cmd.col_type[col] = get_column_type(cmd.tableName, col, j); - ++it; // 只有在没有删除时才增加迭代器 - std::cout << col << ":" << cmd.col_type[col] << " "; - } - } - std::cout << std::endl; - - // 获取enc_table_name - cmd.enc_tableName = getMappedName(T_STRING_TABLE, cmd.tableName.c_str(), NULL); - std::string username = cmk_mapperGetInfoUser(); - std::string db_name = cmk_mapperGetInfoDb(); - - // 执行查询 - std::string query1 = "SELECT c, dek FROM dek_store WHERE t = '" + cmd.enc_tableName + "';"; - PGresult *res1 = PQexec(conn, query1.c_str()); - - // 检查查询状态 - if (PQresultStatus(res1) != PGRES_TUPLES_OK) { - cmd.errorMessage = "Query execution failed: " + query1 + "\n"; - fprintf(stderr, "Query execution failed: %s\n", PQerrorMessage(conn)); - PQclear(res1); - PQfinish(conn); - return; - } - - // 获取查询结果的行数 - int nrows = PQntuples(res1); - - // 获取CMK - std::string cmk = cmk_mapperGetCurrentCmk(); - - // 遍历 - for (int i = 0; i < nrows; i++) { // 遍历每一行 - std::string col_name(PQgetvalue(res1, i, 0)); // 列名 - std::string dek(PQgetvalue(res1, i, 1)); // 密钥 - std::string dek_for_update; // 更新的密钥 - - // 解密密钥 - cmk_mapperDecryptDek(dek, cmk); // 解密密钥 - - // 判断 如果是 NULL 则为表级密钥 && (轮换表级||轮换全部) -> 需要轮换表密钥 - if (PQgetisnull(res1, i, 0)) { // 如果列名是NULL,表示这是表级密钥 - // 创建新密钥 - if (cmk_mapperCreateDek(dek_for_update, "")) { // 表级密钥使用空列名 - cmk_mapperDecryptDek(dek_for_update, cmk); - } else { - fprintf(stderr, "rotate dek failed: can't create new dek.\n"); - } - - if(cmd.type == ROTATE_TABLE || cmd.type == ROTATE_ALL) { - cmk_mapperSetDekTableLevelForUpdate(dek_for_update); - }else{ - cmk_mapperSetDekTableLevelForUpdate(dek); - } - }else{ - // 从密文列名col_name获取到明文列名如(col1_AES),然后作截断得到 col1 - std::string plain = cmd.col_map[col_name]; - plain = plain.substr(0,plain.rfind('_')); - - // 创建新密钥,使用加密后的列名 - if (cmk_mapperCreateDek(dek_for_update, col_name)) { // 使用加密后的列名 - cmk_mapperDecryptDek(dek_for_update, cmk); - } else { - fprintf(stderr, "rotate dek failed: can't create new dek.\n"); - } - - if(cmd.type == ROTATE_TABLE){ // 轮换表级密钥 - all_columns.erase(plain); - cmk_mapperSetDekStoreTmpForUpdate(col_name, dek); // 这些列使用旧密钥 - } else if(cmd.type == ROTATE_ALL){ // 轮换所有密钥 - cmd.enc_cols_set.insert(col_name); // 存储密文列名 - cmk_mapperSetDekStoreTmpForUpdate(col_name, dek_for_update); // dek_store中的所有密钥都要轮换 - } else if(cmd.type == ROTATE_COLUMNS){ // 轮换指定列密钥 - if(cmd.cols_set.find(plain) != cmd.cols_set.end()){ // 判断dek_store中的列是否在命令中,是的话用新密钥,不是则用旧密钥 - cmd.enc_cols_set.insert(col_name); // 存储密文列名 - cmk_mapperSetDekStoreTmpForUpdate(col_name,dek_for_update); - }else{ - cmk_mapperSetDekStoreTmpForUpdate(col_name,dek); - } - } - } - } - - // cmd.cols 命令中的列名(明文)cmd.enc_colsset 命令中的列名(密文) - if(cmd.type == ROTATE_ALL || cmd.type == ROTATE_TABLE){ - cmd.cols_set = all_columns; - }else if(cmd.type == ROTATE_COLUMNS){ - // skip - // todo 加一个 如果不是合理的密钥就报错的机制 - } - - std::cout << "需要轮换的列: "; - for(auto col: cmd.cols_set){ - std::cout << col << " "; - } - std::cout << std::endl; - - PQfinish(conn); -} - -/** - * 连接数据库 - * cmd.cols 构造查询 - * cmd.cols 构造更新 (Update的逻辑会在有dekForUpdate的情况下选取dekForUpdate,所以这里无需切换)。 - */ -void connectionUpdateDek_Update(RotateCommandResult &cmd) { - // 数据库连接信息 - const char *conninfo = "dbname=postgres user=postgres hostaddr=127.0.0.1 port=5432"; - PGconn *conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) { - cmd.errorMessage = "Connection to database failed;\n"; - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - std::string table_name = cmd.tableName; - - // 开始事务 - PQexec(conn, "BEGIN"); - - // 1. 开启密态功能 - std::string enc_on = "enc on;"; - PGresult *res_enc = PQexec(conn, enc_on.c_str()); - if (PQresultStatus(res_enc) != PGRES_TUPLES_OK) { - cmd.errorMessage = "Enable encryption failed: " + enc_on + "\n"; - fprintf(stderr, "Enable encryption failed: %s\n", PQerrorMessage(conn)); - PQclear(res_enc); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - std::cout << enc_on << std::endl; - PQclear(res_enc); - - // 2. 获取表的总行数和最大rotate_id - std::string count_query = "SELECT COUNT(*), MAX(rotate_id) FROM " + table_name + ";"; - PGresult *res_count = PQexec(conn, count_query.c_str()); - - if (PQresultStatus(res_count) != PGRES_TUPLES_OK) { - cmd.errorMessage = "Query execution failed: " + count_query + "\n"; - fprintf(stderr, "Count query failed: %s\n", PQerrorMessage(conn)); - PQclear(res_count); - PQfinish(conn); - return; - } - - int total_rows = atoi(PQgetvalue(res_count, 0, 0)); - int max_id = atoi(PQgetvalue(res_count, 0, 1)); - PQclear(res_count); - - std::cout << "表 " << table_name << " 共有 " << total_rows << " 行数据, 最大ID为 " << max_id << std::endl; - - // 如果表为空,直接返回 - if (total_rows == 0) { - std::cout << "表为空,无需更新" << std::endl; - PQfinish(conn); - return; - } - - // 构建需要查询和更新的列字符串 - std::string columns_str; - for (auto it = cmd.cols_set.begin(); it != cmd.cols_set.end(); ++it){ - if (it != cmd.cols_set.begin()) { - columns_str += ", "; - } - columns_str += *it; - } - - // 批处理大小 - const int BATCH_SIZE = 1000; - int current_id = 0; - int processed_rows = 0; - - // 分批处理数据 - while (processed_rows < total_rows) { - // 查询一批数据 - std::string select_query = "SELECT rotate_id, " + columns_str + - " FROM " + table_name + - " WHERE rotate_id > " + std::to_string(current_id) + - " ORDER BY rotate_id LIMIT " + std::to_string(BATCH_SIZE) + ";"; - - std::cout << "执行查询: " << select_query << std::endl; - - PGresult *res_select = PQexec(conn, select_query.c_str()); - if (PQresultStatus(res_select) != PGRES_TUPLES_OK) { - cmd.errorMessage = "Query execution failed: " + select_query + "\n"; - fprintf(stderr, "SELECT query failed: %s\n", PQerrorMessage(conn)); - PQclear(res_select); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - - int batch_rows = PQntuples(res_select); - if (batch_rows == 0) { - break; - } - - std::cout << "本批次处理 " << batch_rows << " 行数据" << std::endl; - - // 逐行更新数据 - for (int i = 0; i < batch_rows; ++i) { - int row_id = atoi(PQgetvalue(res_select, i, 0)); - current_id = row_id; // 更新当前处理的ID - - // 构建更新语句 - 对每一列都使用原值更新,触发密钥轮换 - std::string update_query = "UPDATE " + table_name + " SET "; - - size_t j = 0; - for(auto it = cmd.cols_set.begin(); it != cmd.cols_set.end(); ++it,++ j) { - std::string col_value = PQgetvalue(res_select, i, j+1 ); // - std::string colname = *it; - - // 检查是否为NULL - if (PQgetisnull(res_select, i, j+1 )) { - update_query += colname + " = NULL"; - } else { - // 获取列的类型信息 - std::string col_type = cmd.col_type[colname]; - - // 根据PostgreSQL类型OID判断列类型 - bool is_text = (col_type == "text"); - - if (!is_text) { - // 数值类型不加引号 - update_query += colname + " = " + col_value; - } else { - update_query += colname + " = '" + col_value + "'"; - } - } - - if (j < cmd.cols_set.size() - 1) { - update_query += ", "; - } - } - - update_query += " WHERE rotate_id = " + std::to_string(row_id) + ";"; - - // 执行更新 - PGresult *res_update = PQexec(conn, update_query.c_str()); - if (PQresultStatus(res_update) != PGRES_COMMAND_OK) { - fprintf(stderr, "UPDATE query failed for row %d: %s\n", row_id, PQerrorMessage(conn)); - PQclear(res_update); - PQclear(res_select); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - PQclear(res_update); - } - - processed_rows += batch_rows; - std::cout << "已处理 " << processed_rows << " / " << total_rows << " 行数据" << std::endl; - - PQclear(res_select); - - // 提交事务 - PGresult *res_commit = PQexec(conn, "COMMIT"); - if (PQresultStatus(res_commit) != PGRES_COMMAND_OK) { - fprintf(stderr, "COMMIT transaction failed: %s\n", PQerrorMessage(conn)); - PQclear(res_commit); - PQfinish(conn); - return; - } - PQclear(res_commit); - } - - PQfinish(conn); -} - - -/** - * 连接数据库 - * 开始事务 - * 更新数据库中的表级和列级 DEK 记录 - * 提交事务 - * 清理临时资源 - */ -void connectionUpdateDek_Final(RotateCommandResult &cmd) { - // 数据库连接信息 - const char *conninfo = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn = PQconnectdb(conninfo); - if (PQstatus(conn) != CONNECTION_OK) { - cmd.errorMessage = "Connection to database failed;\n"; - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return; - } - - // 开始事务 - PGresult *res_begin = PQexec(conn, "BEGIN"); - if (PQresultStatus(res_begin) != PGRES_COMMAND_OK) { - fprintf(stderr, "BEGIN transaction failed: %s\n", PQerrorMessage(conn)); - PQclear(res_begin); - PQfinish(conn); - return; - } - PQclear(res_begin); - - // 获取待更新的表级密钥 - std::string table_dek_for_update; - cmk_mapperGetDekTableLevelForUpdate(table_dek_for_update); - - // 获取CMK - std::string cmk = cmk_mapperGetCurrentCmk(); - - // 如果有表级密钥需要更新 - if (cmd.type != ROTATE_COLUMNS && !table_dek_for_update.empty()) { - // 加密表级密钥 - cmk_mapperEncryptDek(table_dek_for_update, cmk); - if (table_dek_for_update.empty()) { - fprintf(stderr, "Encrypt table DEK failed\n"); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - - // 更新表级密钥 - std::string update_table_dek = "UPDATE dek_store SET dek = '" + table_dek_for_update + - "' WHERE t = '" + cmd.enc_tableName + "' AND c IS NULL;"; - - PGresult *res_update_table = PQexec(conn, update_table_dek.c_str()); - if (PQresultStatus(res_update_table) != PGRES_COMMAND_OK) { - fprintf(stderr, "Update table DEK failed: %s\n", PQerrorMessage(conn)); - PQclear(res_update_table); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - PQclear(res_update_table); - - std::cout << "表级密钥更新成功" << std::endl; - } - - if(!cmd.cols_set.empty() && cmd.type != ROTATE_TABLE){ - // 获取所有待更新的列级密钥 - std::unordered_map column_deks; - cmk_mapperGetAllDekStoreTmpForUpdate(column_deks); - - // 更新列级密钥 - for(const auto& enc_col_name: cmd.enc_cols_set){ - std::string dek = column_deks[enc_col_name]; - - if (dek.empty()) { - fprintf(stderr, "Encrypt column DEK failed for column %s\n", enc_col_name.c_str()); - continue; - } - - // 加密列级密钥 - cmk_mapperEncryptDek(dek, cmk); - - // 更新列级密钥 - std::string update_col_dek = "UPDATE dek_store SET dek = '" + dek + - "' WHERE t = '" + cmd.enc_tableName + - "' AND c = '" + enc_col_name + "';"; - - PGresult *res_update_col = PQexec(conn, update_col_dek.c_str()); - if (PQresultStatus(res_update_col) != PGRES_COMMAND_OK) { - fprintf(stderr, "Update column DEK failed for column %s: %s\n", - enc_col_name.c_str(), PQerrorMessage(conn)); - PQclear(res_update_col); - continue; - } - PQclear(res_update_col); - - - std::cout << "列 " << enc_col_name << " 密钥更新成功" << std::endl; - } - } - - - // 提交事务 - PGresult *res_commit = PQexec(conn, "COMMIT"); - if (PQresultStatus(res_commit) != PGRES_COMMAND_OK) { - fprintf(stderr, "COMMIT transaction failed: %s\n", PQerrorMessage(conn)); - PQclear(res_commit); - PQexec(conn, "ROLLBACK"); - PQfinish(conn); - return; - } - PQclear(res_commit); - - std::cout << "密钥轮换完成" << std::endl; - - PQfinish(conn); -} - -void connectionInsertTest() { - // 数据库连接信息 - const char *conninfo1 = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn1 = PQconnectdb(conninfo1); - if (PQstatus(conn1) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn1)); - PQfinish(conn1); - } - - std::string table_dek; - // 获取CMK - std::string cmk = cmk_mapperGetCurrentCmk(); - // cmk_mapperGetCmkByUsername(cmk_mapperGetInfoUser(), cmk); - if (cmk_mapperCreateDek(table_dek, "")) { // 表级密钥使用空列名 - // cmk_mapperEncryptDek(table_dek, cmk); // 加密表级密钥,create里写了加密所以不需要 - std::string query1 = "insert into dek_store values"; - std::string tuple1 = "("; - tuple1.append("'").append(cmk_mapperGetInfoUser()).append("',") - .append("'").append(cmk_mapperGetInfoDb()).append("',") - .append("'").append(cmk_mapperGetInfoTable()).append("',") - .append("NULL,") - .append("'").append(table_dek).append("')"); - - // 获取列信息并插入列级密钥 - std::string tmp1 = cmk_mapperGetInfoCol(); - if (!tmp1.empty()) { - tuple1.append(","); - } - query1.append(tuple1); - - // 处理所有列密钥 - while (!tmp1.empty()) { - std::string col_dek; - if (cmk_mapperCreateDek(col_dek, tmp1)) { // 使用当前列名作为参数 - // cmk_mapperEncryptDek(col_dek, cmk); // 加密列级密钥 - std::string tuple_col = "("; - tuple_col.append("'").append(cmk_mapperGetInfoUser()).append("',") - .append("'").append(cmk_mapperGetInfoDb()).append("',") - .append("'").append(cmk_mapperGetInfoTable()).append("',") - .append("'").append(tmp1).append("',") - .append("'").append(col_dek).append("')"); - - tmp1 = cmk_mapperGetInfoCol(); - if (!tmp1.empty()) { - tuple_col.append(","); - } - query1.append(tuple_col); - } - } - query1.append(";"); - std::cout << query1 << std::endl; - const char *query1_c = query1.c_str(); - - // 执行查询 - PGresult *res1 = PQexec(conn1, query1_c); - // 检查查询状态 - if (PQresultStatus(res1) != PGRES_COMMAND_OK) { - fprintf(stderr, "Query execution failed: %s\n", PQerrorMessage(conn1)); - PQclear(res1); - } else { - PQclear(res1); // 释放查询结果 - } - } - PQfinish(conn1); // 关闭数据库连接 -} - - -void connectionSelectTest() { - const char *conninfo1 = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn1 = PQconnectdb(conninfo1); - if (PQstatus(conn1) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn1)); - PQfinish(conn1); - } - // 执行查询 - std::string query1 = "SELECT * FROM dek_store WHERE t = \'" + cmk_mapperGetInfoTable() + "\';"; - PGresult *res1 = PQexec(conn1, query1.c_str()); - // 检查查询状态 - if (PQresultStatus(res1) != PGRES_TUPLES_OK) { - fprintf(stderr, "Query execution failed: %s\n", PQerrorMessage(conn1)); - PQclear(res1); - PQfinish(conn1); - } - int nrows = PQntuples(res1); // 获取查询结果的行数 - int ncols = PQnfields(res1); // 获取查询结果的列数 - for (int i = 0; i < nrows; i++) { // 遍历每一行 - for (int j = 0; j < ncols; j++) { // 遍历每一列 - char *value = PQgetvalue(res1, i, j); // 获取第 i 行,第 j 列的值 - std::cout << value << "\t"; - } - std::cout << std::endl; // 换行表示下一行 - } - PQclear(res1); // 释放查询结果 - PQfinish(conn1); // 关闭数据库连接 -} - -void connectionSelect() { - const char *conninfo1 = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn1 = PQconnectdb(conninfo1); - if (PQstatus(conn1) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn1)); - PQfinish(conn1); - return; - } - - // 执行查询 - std::string table_name = cmk_mapperGetInfoTable(); - std::string query1 = "SELECT c, dek FROM dek_store WHERE t = '" + table_name + "';"; - PGresult *res1 = PQexec(conn1, query1.c_str()); - - // 检查查询状态 - if (PQresultStatus(res1) != PGRES_TUPLES_OK) { - fprintf(stderr, "Query execution failed: %s\n", PQerrorMessage(conn1)); - PQclear(res1); - PQfinish(conn1); - return; - } - - // 获取查询结果的行数 - int nrows = PQntuples(res1); - - // 获取CMK - std::string cmk = cmk_mapperGetCurrentCmk(); - // cmk_mapperGetCmkByUsername(cmk_mapperGetInfoUser(), cmk); - - for (int i = 0; i < nrows; i++) { // 遍历每一行 - std::string col_name(PQgetvalue(res1, i, 0)); // 列名 - std::string dek(PQgetvalue(res1, i, 1)); // 对应的密钥 - - // 解密密钥 - cmk_mapperDecryptDek(dek, cmk); - - if (PQgetisnull(res1, i, 0)) { // 如果列名是NULL,表示这是表级密钥 - cmk_mapperSetDekTableLevel(dek); - // dek_for_decrypt = dek; - } else { // 否则是列级密钥 - cmk_mapperSetInfoDekTmp(col_name, dek); - } - } - - PQclear(res1); // 释放查询结果 - PQfinish(conn1); // 关闭数据库连接 -} - -//轮转后从表中取出DEK并解密 -void connectionRotationSelectDek(const std::string &user_name, const std::string &old_cmk, std::map &_dek_tmp, bool &hasDEK) { - const char *conninfo1 = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn1 = PQconnectdb(conninfo1); - if (PQstatus(conn1) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn1)); - PQfinish(conn1); - } - // 执行查询 - std::string query1 = "SELECT t, c, dek FROM dek_store WHERE username = '" + user_name + "';"; - PGresult *res1 = PQexec(conn1, query1.c_str()); - // 检查查询状态 - if (PQresultStatus(res1) != PGRES_TUPLES_OK) { - fprintf(stderr, "Query execution failed: %s\n", PQerrorMessage(conn1)); - PQclear(res1); - PQfinish(conn1); - } - - int nrows = PQntuples(res1); // 获取查询结果的行数 - - for (int i = 0; i < nrows; i++) { // 遍历每一行 - std::string table_name(PQgetvalue(res1, i, 0)); //表名 - std::string col_name = PQgetisnull(res1, i, 1) ? "" : PQgetvalue(res1, i, 1); //列名 - std::string dek(PQgetvalue(res1, i, 2)); //密文dek - - cmk_mapperDecryptDek(dek, old_cmk); //解密dek - - // 使用表名和列名组合作为键 - std::string key = table_name + (col_name.empty() ? "" : ":" + col_name); - _dek_tmp[key] = dek; //将解密dek信息和表名映射关系存入临时结构 - std::cout << "Table: " << table_name << ", Column: " << (col_name.empty() ? "TABLE_KEY" : col_name) - << ", Decrypted DEK: " << dek << std::endl; - } - - if (!_dek_tmp.empty()) { - hasDEK = true; - } - - PQclear(res1); // 释放查询结果 - PQfinish(conn1); // 关闭数据库连接 -} - -//轮转后完成DEK重加密并更新存储 -void connectionRotationUpdataDek(const std::string &user_name, const std::string &new_cmk, std::map &_dek_tmp) { - const char *conninfo1 = "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432"; - PGconn *conn1 = PQconnectdb(conninfo1); - if (PQstatus(conn1) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn1)); - PQfinish(conn1); - } - - // 遍历临时存储结构,重加密dek - for (auto &entry : _dek_tmp) { - std::string key = entry.first; - std::string dek = entry.second; - - // 解析key获取表名和列名 - size_t pos = key.find(":"); - std::string table_name = pos == std::string::npos ? key : key.substr(0, pos); - std::string col_name = pos == std::string::npos ? "" : key.substr(pos + 1); - - //重加密 - cmk_mapperEncryptDek(dek, new_cmk); - - //更新数据库 - std::string update_query; - if(col_name.empty()) { - update_query = "UPDATE dek_store SET dek = '" + dek + "' WHERE username = '" + user_name + - "' AND t = '" + table_name + "' AND c IS NULL;"; - } else { - update_query = "UPDATE dek_store SET dek = '" + dek + "' WHERE username = '" + user_name + - "' AND t = '" + table_name + "' AND c = '" + col_name + "';"; - } - - PGresult *res = PQexec(conn1, update_query.c_str()); - - if (PQresultStatus(res) != PGRES_COMMAND_OK) { - fprintf(stderr, "Update execution failed: %s\n", PQerrorMessage(conn1)); - PQclear(res); - } else { - PQclear(res); - } - } - std::cout << "Successfully update all DEKs of \"" << user_name << "\"." << std::endl; - PQfinish(conn1); -} - -// 读取 JSON 文件 -json read_json_from_file(const std::string& file_path) { - std::ifstream file(file_path); - if (!file.is_open()) { - std::cerr << "无法打开文件:" << file_path << std::endl; - exit(1); - } - - json j; - file >> j; - return j; -} - -// 获取表中所有列 -std::vector get_columns(const std::string& table_name, const json& j) { - std::vector columns; - try { - // 获取指定表名的列信息 - auto columns_info = j["schema"]["public"][table_name]["columns"]; - for (const auto& col : columns_info) { - columns.push_back(col); - } - } catch (const std::exception& e) { - std::cerr << "获取列时发生错误:" << e.what() << std::endl; - } - return columns; -} - -// 获取表中所有列 -std::set get_all_columns(const std::string& table_name, const json& j) { - std::set cols; - try { - // 定位到 schema.public.{table_name}.columns - auto cols_array = j.at("schema").at("public").at(table_name).at("columns"); - for (const auto& col : cols_array) { - cols.insert(col.get()); - } - } catch (const std::exception& e) { - std::cerr << "获取所有列名时发生错误:" << e.what() << std::endl; - } - return cols; -} - -// 获取所有密文列名 ↔ 明文列名 之间的映射,存储在一个 std::map 中 -std::unordered_map get_column_mapping(const std::string& table_name, const json& j) { - std::unordered_map mapping; - try { - // 定位到 schema.public.{table_name}.map - auto map_info = j.at("schema").at("public").at(table_name).at("map"); - for (auto it = map_info.begin(); it != map_info.end(); ++it) { - // key: 列名1(可能是加密后的列名或明文标识) - // value: 列名2(对应的另一端) - mapping[it.key()] = it.value().get(); - } - } catch (const std::exception& e) { - std::cerr << "获取列映射时发生错误:" << e.what() << std::endl; - } - return mapping; -} - -// 获取列的数据类型 -std::string get_column_type(const std::string& table_name, const std::string& column_name, const json& j) { - try { - // 获取表的信息 - auto table_info = j["schema"]["public"][table_name]; - - // 检查列是否存在 - if (table_info.contains(column_name)) { - // 返回列的类型 - if (table_info[column_name].contains("type")) { - return table_info[column_name]["type"]; - } - } - } catch (const std::exception& e) { - std::cerr << "获取列类型时发生错误:" << e.what() << std::endl; - } - return ""; -} - -/** - * 执行数据库操作的辅助函数 - * @param sql SQL语句 - * @param errorMsg 错误描述(用于日志) - * @return 0表示成功,-1表示失败 - */ -int executeSQL(const char *sql, const char *errorMsg) { - PGconn *conn = PQconnectdb(DB_CONNINFO); - PGresult *res = NULL; - int result = -1; - - if (PQstatus(conn) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return -1; - } - - res = PQexec(conn, sql); - - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - result = 0; - printf("Database operation succeeded: %s\n", errorMsg); - } else { - fprintf(stderr, "Database operation failed (%s): %s\n", errorMsg, PQerrorMessage(conn)); - fprintf(stderr, "SQL: %s\n", sql); - } - - PQclear(res); - PQfinish(conn); - return result; -} - -/** - * 检查表是否存在 - * @param tableName 表名 - * @return 1表示存在,0表示不存在,-1表示查询失败 - */ -int tableExists(const char *tableName) { - PGconn *conn = PQconnectdb(DB_CONNINFO); - PGresult *res = NULL; - int result = -1; - char query[256]; - - if (PQstatus(conn) != CONNECTION_OK) { - fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn)); - PQfinish(conn); - return -1; - } - - snprintf(query, sizeof(query), - "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = '%s')", - tableName); - - res = PQexec(conn, query); - - if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) > 0) { - const char *exists = PQgetvalue(res, 0, 0); - result = (strcmp(exists, "t") == 0) ? 1 : 0; - } else { - fprintf(stderr, "Failed to check table existence: %s\n", PQerrorMessage(conn)); - } - - PQclear(res); - PQfinish(conn); - return result; -} - -/** - * 备份dek_store表 - * @return 0表示成功,-1表示失败 - */ -int backupDekStore() { - char sql[512]; - int result = 0; - - // 检查原表是否存在 - int originalExists = tableExists(ORIGINAL_TABLE_NAME); - if (originalExists < 0) { - fprintf(stderr, "Failed to check if original table exists\n"); - return -1; - } - - if (originalExists == 0) { - printf("Original table %s does not exist, skipping database backup\n", ORIGINAL_TABLE_NAME); - return 0; - } - - // 删除可能存在的备份表 - snprintf(sql, sizeof(sql), "DROP TABLE IF EXISTS %s", BACKUP_TABLE_NAME); - if (executeSQL(sql, "drop existing backup table") != 0) { - return -1; - } - - // 创建备份表并复制数据 - snprintf(sql, sizeof(sql), - "CREATE TABLE %s AS SELECT * FROM %s", - BACKUP_TABLE_NAME, ORIGINAL_TABLE_NAME); - if (executeSQL(sql, "create backup table") != 0) { - return -1; - } - - printf("Database table %s backed up successfully to %s\n", ORIGINAL_TABLE_NAME, BACKUP_TABLE_NAME); - return 0; -} - -/** - * 删除dek_store备份表 - * @return 0表示成功,-1表示失败 - */ -int deleteDekStoreBackup() { - char sql[256]; - - // 检查备份表是否存在 - int backupExists = tableExists(BACKUP_TABLE_NAME); - if (backupExists < 0) { - fprintf(stderr, "Failed to check if backup table exists\n"); - return -1; - } - - if (backupExists == 0) { - printf("Backup table %s does not exist\n", BACKUP_TABLE_NAME); - return 0; - } - - // 删除备份表 - snprintf(sql, sizeof(sql), "DROP TABLE %s", BACKUP_TABLE_NAME); - if (executeSQL(sql, "delete backup table") != 0) { - return -1; - } - - printf("Database backup table %s deleted successfully\n", BACKUP_TABLE_NAME); - return 0; -} - -/** - * 从备份恢复dek_store表 - * @return 0表示成功,-1表示失败 - */ -int restoreDekStore() { - char sql[512]; - - // 检查备份表是否存在 - int backupExists = tableExists(BACKUP_TABLE_NAME); - if (backupExists < 0) { - fprintf(stderr, "Failed to check if backup table exists\n"); - return -1; - } - - if (backupExists == 0) { - printf("No backup table %s found for rollback\n", BACKUP_TABLE_NAME); - return 0; - } - - // 删除当前表(如果存在) - snprintf(sql, sizeof(sql), "DROP TABLE IF EXISTS %s", ORIGINAL_TABLE_NAME); - if (executeSQL(sql, "drop current table for restore") != 0) { - return -1; - } - - // 重命名备份表为原表名 - snprintf(sql, sizeof(sql), - "ALTER TABLE %s RENAME TO %s", - BACKUP_TABLE_NAME, ORIGINAL_TABLE_NAME); - if (executeSQL(sql, "restore table from backup") != 0) { - return -1; - } - - printf("Database table %s restored from backup successfully\n", ORIGINAL_TABLE_NAME); - return 0; -} \ No newline at end of file diff --git a/src/KMS/PGconnectForDEK.h.bk b/src/KMS/PGconnectForDEK.h.bk deleted file mode 100755 index e65eb04..0000000 --- a/src/KMS/PGconnectForDEK.h.bk +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef CRYPTOKEY_SERVICE_H -#define CRYPTOKEY_SERVICE_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "postgres.h" // 与 #include 冲突 -//为了解决和libintl.h冲突的问题undef以下4个 -#undef gettext -#undef dgettext -#undef ngettext -#undef dngettext - -#include "utils/palloc.h" -#include "utils/memutils.h" - -#include "nodes/nodes.h" -#include "nodes/parsenodes.h" -#include "nodes/value.h" - -#include "base64.h" - -#include -#ifdef __cplusplus -} -#endif - -#include "encryptsql/fieldmap.h" -#include "kms/KeyManagementService.hpp" -#include -#include -#include -#include -#include -#include "libpq-fe.h" // 改为使用引号包含 - -#include "crypto/crypto.h" -#include "crypto/openssl.h" -#include "encryptsql.h" - - -// 因为缺头文件所以直接复制过来了,肯定有很多用不上的 -#include -#include -#include - -// 数据库连接信息 -#define DB_CONNINFO "dbname=dekmaster user=dekmaster password=secure_password hostaddr=127.0.0.1 port=5432" -#define BACKUP_TABLE_NAME "dek_store_backup" -#define ORIGINAL_TABLE_NAME "dek_store" - -// 定义轮换类型枚举 -enum RotationType { - ROTATE_ALL, // 轮换表级和所有列级密钥 - ROTATE_TABLE, // 只轮换表级密钥 - ROTATE_COLUMNS // 只轮换指定列的密钥 -}; - -// 轮换命令解析结果结构 -struct RotateCommandResult { - bool valid; // 命令是否有效 - RotationType type; // 轮换类型 - std::string tableName; // 表名 - std::string enc_tableName; // 加密表名 - - std::set cols_set; // 命令涉及的列名列表 用于快速检索轮换命令中是否有这个列 - std::unordered_set enc_cols_set; // 需要更新的密钥的密文列名 - - std::unordered_map col_map; // 明文列名 和 密文列名的映射 - std::unordered_map col_type; // 列的类型 - std::string errorMessage; // 错误信息 -}; - -RotateCommandResult parseRotateCommand(const std::string& command,const std::string &user_name,const std::string &db_name); - -// test -void printRotateCommandResult(const RotateCommandResult& result); - -void connectionDelete(); - -void connectionUpdateDek(RotateCommandResult &result); - -void connectionUpdateDek_Init(RotateCommandResult &result); - -void connectionUpdateDek_Update(RotateCommandResult& result); - -void connectionUpdateDek_Final(RotateCommandResult& result); - -void connectionInsertTest(); - -void connectionSelectTest(); - -void connectionSelect(); - -using json = nlohmann::json; - -// 读取 JSON 文件 -json read_json_from_file(const std::string& file_path); - -// 获取表中所有列 -std::vector get_columns(const std::string& table_name, const json& j); - -// 获取表中所有列 -std::set get_all_columns(const std::string& table_name, const json& j); - -// 获取表中列的映射关系 -std::unordered_map get_column_mapping(const std::string& table_name, const json& j); - -// 获取列的数据类型 -std::string get_column_type(const std::string& table_name, const std::string& column_name, const json& j); - - -static int executeSQL(const char *sql, const char *errorMsg); - -static int tableExists(const char *tableName); - -int backupDekStore(); - -int deleteDekStoreBackup(); - -int restoreDekStore(); - - -#endif // CRYPTOKEY_SERVICE_H \ No newline at end of file diff --git a/src/KMS/kms_core_local.cpp b/src/KMS/kms_core_local.cpp index b4f1171..46839fd 100755 --- a/src/KMS/kms_core_local.cpp +++ b/src/KMS/kms_core_local.cpp @@ -38,12 +38,11 @@ extern "C" #include "encryptsql.h" -// 因为缺头文件所以直接复制过来了,肯定有很多用不上的 #include #include #include - +#include "en_config.h" #include "kms/kms_core_local.hpp" #include "kms/kms_factory.hpp" @@ -89,9 +88,9 @@ std::vector LocalKmsCore::getSystemIDHash16() { } void LocalKmsCore::getRootKey(unsigned char *key, size_t len) { - auto A = readBinaryFile("/new_enc/kms_root/frag_a"); - auto B = readBinaryFile("/new_enc/kms_root/frag_b"); - auto C = readBinaryFile("/new_enc/kms_root/frag_c"); + auto A = readBinaryFile(ROOT_KEY_GEN_PATH "/frag_a"); + auto B = readBinaryFile(ROOT_KEY_GEN_PATH "/frag_b"); + auto C = readBinaryFile(ROOT_KEY_GEN_PATH "/frag_c"); if (A.size() != B.size() || A.size() != C.size() || A.size() != 16) throw std::runtime_error("All key fragments must be 16 bytes."); @@ -655,6 +654,8 @@ bool LocalKmsCore::encryptData(std::string &ori_key) { std::string base64_encrypted = base64_encode(reinterpret_cast(encrypted.c_str()), encrypted.size()); ori_key = base64_encrypted; + + return true; } bool LocalKmsCore::decryptData(std::string &ori_key) { diff --git a/src/KMS/kms_interface.cpp b/src/KMS/kms_interface.cpp index 7ec96cc..3510611 100755 --- a/src/KMS/kms_interface.cpp +++ b/src/KMS/kms_interface.cpp @@ -72,4 +72,4 @@ bool KMSInterface::decryptData(std::string& dek) { bool KMSInterface::createDek(std::string &col_dek, const std::string &column_name){ return instance_ && instance_->createDek(col_dek, column_name); -} +} \ No newline at end of file diff --git a/src/KMS/main.cpp b/src/KMS/main.cpp new file mode 100644 index 0000000..8992cb5 --- /dev/null +++ b/src/KMS/main.cpp @@ -0,0 +1,198 @@ +#include "kms/kms_interface.hpp" +#include "kms/kms_core_local.hpp" +#include "en_config.h" +#include +#include +#include +#include +#include + + +using namespace std; + +// 默认数据库名 +const string DEFAULT_DBNAME = "default_db"; + +void print_usage() { + cout << "Usage: KMS [args...] [--time]\n"; + cout << "Commands:\n"; + cout << " hasCmk \n"; + cout << " createCmk \n"; + cout << " deleteCmk \n"; + cout << " describeCmk [decrypt]\n"; + cout << " rotateCmkNow \n"; + cout << " CMK_auto_rotate on/off/status\n"; + cout << " encryptData \n"; + cout << " decryptData \n"; + cout << " createDek \n"; +} + +bool init_and_get_instance(const string& username) { + LocalKmsCore::registerLocalKms(); + + LocalKmsConfig config( + CMK_FILE_PATH, + CMK_KEY_PATH, + CMK_ROTATE_STATUS_PATH, + username.c_str(), + DEFAULT_DBNAME.c_str() + ); + + if (!KMSInterface::initialize(config)) { + cerr << "ERROR: KMS initialization failed\n"; + return false; + } + + if (!KMSInterface::getInstance()) { + cerr << "ERROR: KMS instance not available\n"; + return false; + } + + return true; +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + print_usage(); + return 1; + } + + // ======== 解析参数,处理 --time ========= + bool measure_time = false; + vector args; + args.reserve(argc); + + for (int i = 1; i < argc; ++i) { + if (string(argv[i]) == "--time") { + measure_time = true; + } else { + args.push_back(argv[i]); // 保留非 --time 参数 + } + } + + if (args.size() < 2) { + print_usage(); + return 1; + } + + string cmd = args[0]; + string username = args[1]; + + if (cmd == "--help" || cmd == "-h") { + print_usage(); + return 0; + } + + // ======== 初始化 KMS ========= + if (!init_and_get_instance(username)) { + return 1; + } + + bool ok = false; + string result; + + // ======== 计时开始 ========= + auto start = std::chrono::high_resolution_clock::now(); + + // ========= KMS 命令处理 ========= + if (cmd == "hasCmk") { + ok = KMSInterface::hasCmk(username); + cout << (ok ? "true" : "false") << "\n"; + } + else if (cmd == "createCmk" && args.size() == 3) { + int rotate_period = stoi(args[2]); + ok = KMSInterface::createCmk(username, rotate_period); + cout << (ok ? "OK" : "ERROR") << "\n"; + } + else if (cmd == "deleteCmk") { + ok = KMSInterface::deleteCmk(username); + cout << (ok ? "OK" : "ERROR") << "\n"; + } + else if (cmd == "describeCmk") { + bool decrypt = (args.size() == 3 && args[2] == "decrypt"); + ok = KMSInterface::describeCmk(username, result, decrypt); + cout << (ok ? result : "ERROR") << "\n"; + } + else if (cmd == "rotateCmkNow") { + ok = KMSInterface::rotateCmkNow(username); + cout << (ok ? "OK" : "ERROR") << "\n"; + } + else if (cmd == "CMK_auto_rotate" && args.size() == 3) { + string action = args[2]; + ok = KMSInterface::handleAutoRotateCmd(&action, username); + cout << (ok ? action : "ERROR") << "\n"; + } + else if (cmd == "encryptData" && args.size() == 3) { + string input = args[2]; + ifstream infile(input); + if (infile.good()) { + string output_file = input + ".enc"; + ofstream outfile(output_file); + string line; + while (getline(infile, line)) { + if (line.empty()) continue; + string line_result = line; + ok = KMSInterface::encryptData(line_result); + outfile << (ok ? line_result : "ERROR") << "\n"; + } + cout << "Encrypted result written to: " << output_file << "\n"; + } else { + string str_result = input; + ok = KMSInterface::encryptData(str_result); + cout << (ok ? str_result : "ERROR") << "\n"; + } + } + else if (cmd == "decryptData" && args.size() == 3) { + string input = args[2]; + ifstream infile(input); + if (infile.good()) { + string output_file = input + ".dec"; + ofstream outfile(output_file); + string line; + while (getline(infile, line)) { + string line_result = line; + ok = KMSInterface::decryptData(line_result); + outfile << (ok ? line_result : "ERROR") << "\n"; + } + cout << "Decryption results written to " << output_file << "\n"; + } else { + string str_result = input; + ok = KMSInterface::decryptData(str_result); + cout << (ok ? str_result : "ERROR") << "\n"; + } + } + else if (cmd == "createDek" && args.size() == 3) { + string input = args[2]; + ifstream infile(input); + if (infile.good()) { + string output_file = input + ".dek"; + ofstream outfile(output_file); + string line; + while (getline(infile, line)) { + if (line.empty()) continue; + string col_dek; + ok = KMSInterface::createDek(col_dek, line); + outfile << line << " : " << (ok ? col_dek : "ERROR") << "\n"; + } + cout << "DEK creation results written to " << output_file << "\n"; + } else { + string col_dek; + ok = KMSInterface::createDek(col_dek, input); + cout << (ok ? (input + " : " + col_dek) : "ERROR") << "\n"; + } + } + else { + print_usage(); + return 1; + } + + // ======== 计时结束 ========= + auto end = std::chrono::high_resolution_clock::now(); + auto duration = chrono::duration_cast(end - start); + + if (measure_time) { + cout << "[Time used]: " << duration.count() << " us\n"; + } + + return ok ? 0 : 1; +} diff --git a/src/KMSAdapter/dek_interface.cpp b/src/KMSAdapter/dek_interface.cpp index a2f3096..f3428f1 100755 --- a/src/KMSAdapter/dek_interface.cpp +++ b/src/KMSAdapter/dek_interface.cpp @@ -9,12 +9,7 @@ RotateCommandResult parseRotateCommand(const std::string& command,const std::str result.valid = false; std::string current_cmk; - //得到当前用户的cmk - // cmk_mapperGetCmkByUsername(user_name, current_cmk); - //存储当前cmk - // cmk_mapperSetCurrentCmk(current_cmk); - // cmk_mapperSetInfoUser(user_name); - // cmk_mapperSetInfoDb(db_name); + DekInterface::setInfoUser(user_name); DekInterface::setInfoDb(db_name); @@ -147,9 +142,6 @@ void connectionDelete() { // 构建删除查询 std::string query = "DELETE FROM dek_store WHERE "; - // query.append("username = '").append(cmk_mapperGetInfoUser()).append("' AND ") - // .append("db = '").append(cmk_mapperGetInfoDb()).append("' AND ") - // .append("t = '").append(cmk_mapperGetInfoTable()).append("'"); query.append("username = '").append(DekInterface::getInfoUser()).append("' AND ") .append("db = '").append(DekInterface::getInfoDb()).append("' AND ") .append("t = '").append(DekInterface::getInfoTable()).append("'"); @@ -273,8 +265,6 @@ void connectionUpdateDek_Init(RotateCommandResult &cmd) { // 判断 如果是 NULL 则为表级密钥 && (轮换表级||轮换全部) -> 需要轮换表密钥 if (PQgetisnull(res1, i, 0)) { // 如果列名是NULL,表示这是表级密钥 // 创建新密钥 - // if (cmk_mapperCreateDek(dek_for_update, "")) { // 表级密钥使用空列名 - // cmk_mapperDecryptDek(dek_for_update, cmk); if (KMSInterface::createDek(dek_for_update, "")) { // 表级密钥使用空列名, 也可以DekAPI::getInfoTable()) KMSInterface::decryptData(dek_for_update); } else { @@ -282,10 +272,8 @@ void connectionUpdateDek_Init(RotateCommandResult &cmd) { } if(cmd.type == ROTATE_TABLE || cmd.type == ROTATE_ALL) { - // cmk_mapperSetDekTableLevelForUpdate(dek_for_update); DekInterface::setDekTableLevelForUpdate(dek_for_update); }else{ - // cmk_mapperSetDekTableLevelForUpdate(dek); DekInterface::setDekTableLevelForUpdate(dek); } }else{ @@ -294,8 +282,6 @@ void connectionUpdateDek_Init(RotateCommandResult &cmd) { plain = plain.substr(0,plain.rfind('_')); // 创建新密钥,使用加密后的列名 - // if (cmk_mapperCreateDek(dek_for_update, col_name)) { // 使用加密后的列名 - // cmk_mapperDecryptDek(dek_for_update, cmk); if (KMSInterface::createDek(dek_for_update, col_name)) { // 使用加密后的列名 KMSInterface::decryptData(dek_for_update); } else { @@ -304,19 +290,15 @@ void connectionUpdateDek_Init(RotateCommandResult &cmd) { if(cmd.type == ROTATE_TABLE){ // 轮换表级密钥 all_columns.erase(plain); - // cmk_mapperSetDekStoreTmpForUpdate(col_name, dek); // 这些列使用旧密钥 DekInterface::setDekColLevelForUpdate(col_name, dek); } else if(cmd.type == ROTATE_ALL){ // 轮换所有密钥 cmd.enc_cols_set.insert(col_name); // 存储密文列名 - // cmk_mapperSetDekStoreTmpForUpdate(col_name, dek_for_update); // dek_store中的所有密钥都要轮换 DekInterface::setDekColLevelForUpdate(col_name, dek_for_update); } else if(cmd.type == ROTATE_COLUMNS){ // 轮换指定列密钥 if(cmd.cols_set.find(plain) != cmd.cols_set.end()){ // 判断dek_store中的列是否在命令中,是的话用新密钥,不是则用旧密钥 cmd.enc_cols_set.insert(col_name); // 存储密文列名 - // cmk_mapperSetDekStoreTmpForUpdate(col_name,dek_for_update); DekInterface::setDekColLevelForUpdate(col_name, dek_for_update); }else{ - // cmk_mapperSetDekStoreTmpForUpdate(col_name,dek); DekInterface::setDekColLevelForUpdate(col_name, dek); } } @@ -542,16 +524,13 @@ void connectionUpdateDek_Final(RotateCommandResult &cmd) { // 获取待更新的表级密钥 std::string table_dek_for_update; - // cmk_mapperGetDekTableLevelForUpdate(table_dek_for_update); DekInterface::getDekTableLevelForUpdate(table_dek_for_update); // 获取CMK - // std::string cmk = cmk_mapperGetCurrentCmk(); // 如果有表级密钥需要更新 if (cmd.type != ROTATE_COLUMNS && !table_dek_for_update.empty()) { // 加密表级密钥 - // cmk_mapperEncryptDek(table_dek_for_update, cmk); KMSInterface::encryptData(table_dek_for_update); if (table_dek_for_update.empty()) { fprintf(stderr, "Encrypt table DEK failed\n"); @@ -580,7 +559,6 @@ void connectionUpdateDek_Final(RotateCommandResult &cmd) { if(!cmd.cols_set.empty() && cmd.type != ROTATE_TABLE){ // 获取所有待更新的列级密钥 std::unordered_map column_deks; - // cmk_mapperGetAllDekStoreTmpForUpdate(column_deks); DekInterface::getAllDekColLevelForUpdate(column_deks); // 更新列级密钥 @@ -642,19 +620,9 @@ void connectionInsertTest() { } std::string table_dek; - // 获取CMK - // std::string cmk = cmk_mapperGetCurrentCmk(); - // cmk_mapperGetCmkByUsername(cmk_mapperGetInfoUser(), cmk); - // if (cmk_mapperCreateDek(table_dek, "")) { // 表级密钥使用空列名 if (KMSInterface::createDek(table_dek, "")) { // 表级密钥使用空列名 - // cmk_mapperEncryptDek(table_dek, cmk); // 加密表级密钥,create里写了加密所以不需要 std::string query1 = "insert into dek_store values"; std::string tuple1 = "("; - // tuple1.append("'").append(cmk_mapperGetInfoUser()).append("',") - // .append("'").append(cmk_mapperGetInfoDb()).append("',") - // .append("'").append(cmk_mapperGetInfoTable()).append("',") - // .append("NULL,") - // .append("'").append(table_dek).append("')"); tuple1.append("'").append(DekInterface::getInfoUser()).append("',") .append("'").append(DekInterface::getInfoDb()).append("',") @@ -672,15 +640,8 @@ void connectionInsertTest() { // 处理所有列密钥 while (!tmp1.empty()) { std::string col_dek; - // if (cmk_mapperCreateDek(col_dek, tmp1)) { // 使用当前列名作为参数 if(KMSInterface::createDek(col_dek, tmp1)) { - // cmk_mapperEncryptDek(col_dek, cmk); // 加密列级密钥 std::string tuple_col = "("; - // tuple_col.append("'").append(cmk_mapperGetInfoUser()).append("',") - // .append("'").append(cmk_mapperGetInfoDb()).append("',") - // .append("'").append(cmk_mapperGetInfoTable()).append("',") - // .append("'").append(tmp1).append("',") - // .append("'").append(col_dek).append("')"); tuple_col.append("'").append(DekInterface::getInfoUser()).append("',") .append("'").append(DekInterface::getInfoDb()).append("',") .append("'").append(DekInterface::getInfoTable()).append("',") @@ -768,23 +729,17 @@ void connectionSelect() { int nrows = PQntuples(res1); // 获取CMK - // std::string cmk = cmk_mapperGetCurrentCmk(); - // cmk_mapperGetCmkByUsername(cmk_mapperGetInfoUser(), cmk); for (int i = 0; i < nrows; i++) { // 遍历每一行 std::string col_name(PQgetvalue(res1, i, 0)); // 列名 std::string dek(PQgetvalue(res1, i, 1)); // 对应的密钥 // 解密密钥 - // cmk_mapperDecryptDek(dek, cmk); KMSInterface::decryptData(dek); if (PQgetisnull(res1, i, 0)) { // 如果列名是NULL,表示这是表级密钥 - // cmk_mapperSetDekTableLevel(dek); DekInterface::setDekTableLevel(dek); - // dek_for_decrypt = dek; } else { // 否则是列级密钥 - // cmk_mapperSetInfoDekTmp(col_name, dek); DekInterface::setDekColLevel(col_name, dek); } } diff --git a/src/crypto/cryptolib/libudf/decider/udfDispatch.cpp b/src/crypto/cryptolib/libudf/decider/udfDispatch.cpp index 82278b5..6b77388 100755 --- a/src/crypto/cryptolib/libudf/decider/udfDispatch.cpp +++ b/src/crypto/cryptolib/libudf/decider/udfDispatch.cpp @@ -25,6 +25,7 @@ using namespace util; #ifndef NDEBUG // DEBUG #include +#include "en_config.h" extern "C" { @@ -36,7 +37,7 @@ class CalledCounter { public: CalledCounter() { char buf[64]; - sprintf(buf, "/etc/encryptsql/UDFcalled_by%d.count", (int) getpid()); + sprintf(buf, ENCRYPTSQL_CONFIG_DIR "/UDFcalled_by%d.count", (int) getpid()); ofstream fout(buf); fout.close(); diff --git a/src/encryptsql/encryptstmt.cpp b/src/encryptsql/encryptstmt.cpp index 9cb4cb7..c33a8c0 100755 --- a/src/encryptsql/encryptstmt.cpp +++ b/src/encryptsql/encryptstmt.cpp @@ -40,7 +40,7 @@ extern "C" #include "crypto/openssl.h" #include "encryptsql.h" - +#include "en_config.h" #include "kms/kms_interface.hpp" #include "kmsAdapter/dek_interface.hpp" #include "KeyDistribution/non_enc_client/client_interface.h" @@ -49,8 +49,8 @@ namespace { bool SendDekViaTls(const std::string& dek_plain) { kd::client::ClientConfig cfg; - cfg.server_host = "127.0.0.1"; // 或者 "localhost" - cfg.server_port = "9443"; // 只要服务器宿主端监听同一个端口即可 + cfg.server_host = DK_SERVER_HOST; // 或者 "localhost" + cfg.server_port = DK_SERVER_PORT; // 只要服务器宿主端监听同一个端口即可 cfg.dek.assign(dek_plain.begin(), dek_plain.end()); kd::client::ClientResult result; @@ -65,14 +65,6 @@ bool SendDekViaTls(const std::string& dek_plain) } } // anonymous namespace - - -// 文件路径定义 -#define MAP_FILE_PATH "/etc/encryptsql/map.json" -#define KMS_FILE_PATH "/new_enc/kms_test/output.json" -#define MAP_BACKUP_PATH "/etc/encryptsql/map.json.backup" -#define KMS_BACKUP_PATH "/new_enc/kms_test/output.json.backup" - extern thread_local std::string dek_for_decrypt; static List *encryptValuesLists(List *valuesLists, List *cols, EncryptInfo *info); @@ -1950,18 +1942,18 @@ cleanup: * 开始事务 * 在事务开始时调用,为原文件和数据库表创建备份副本 */ -#ifdef USE_BACKUP_ENCRYPT +#ifdef ENCRYPTSQL_USE_RECOVERY static void create_backup(bool is_transaction) { int mapResult = 0, kmsResult = 0, dbResult = 0; - const char* map_path = MAP_FILE_PATH; + const char* map_path = MAP_JSON_PATH; const char* map_backup; - if(is_transaction) map_backup = MAP_BACKUP_PATH".t"; - else map_backup = MAP_BACKUP_PATH; - const char* kms_path = KMS_FILE_PATH; + if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t"; + else map_backup = MAP_JSON_BACKUP_PATH; + const char* kms_path = CMK_FILE_PATH; const char* kms_backup; - if(is_transaction) kms_backup = KMS_BACKUP_PATH".t"; - else kms_backup = KMS_BACKUP_PATH; + if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t"; + else kms_backup = CMK_FILE_BACKUP_PATH; char* msg; // 备份映射文件 @@ -1977,7 +1969,7 @@ static void create_backup(bool is_transaction) { } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 备份密钥文件 @@ -1993,21 +1985,21 @@ static void create_backup(bool is_transaction) { } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 备份数据库表 - // dbResult = backupDekStore(); dbResult = DekInterface::backupDekStore(); #ifndef NDEBUG - // 如果任一备份失败,记录错误但不阻止事务继续 - if (mapResult != 0 || kmsResult != 0 || dbResult != 0) { - fprintf(stderr, "Warning: Some backups failed, transaction may not be fully recoverable\n"); - } else { - printf("All backups completed successfully\n"); - } + // // 如果任一备份失败,记录错误但不阻止事务继续 + // if (mapResult != 0 || kmsResult != 0 || dbResult != 0) { + // fprintf(stderr, "Warning: Some backups failed, transaction may not be fully recoverable\n"); + // } else { + // printf("All backups completed successfully\n"); + // } #endif + } /** @@ -2024,14 +2016,14 @@ void delete_backup(bool is_transaction) { } int mapResult = 0, kmsResult = 0, dbResult = 0; - const char* map_path = MAP_FILE_PATH; + const char* map_path = MAP_JSON_PATH; const char* map_backup; - if(is_transaction) map_backup = MAP_BACKUP_PATH".t"; - else map_backup = MAP_BACKUP_PATH; - const char* kms_path = KMS_FILE_PATH; + if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t"; + else map_backup = MAP_JSON_BACKUP_PATH; + const char* kms_path = CMK_FILE_PATH; const char* kms_backup; - if(is_transaction) kms_backup = KMS_BACKUP_PATH".t"; - else kms_backup = KMS_BACKUP_PATH; + if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t"; + else kms_backup = CMK_FILE_BACKUP_PATH; char* msg; // 删除映射文件备份 @@ -2048,7 +2040,7 @@ void delete_backup(bool is_transaction) { } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 删除密钥文件备份 @@ -2065,19 +2057,18 @@ void delete_backup(bool is_transaction) { } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 删除数据库备份表 - // dbResult = deleteDekStoreBackup(); dbResult = DekInterface::deleteDekStoreBackup(); #ifndef NDEBUG - if (mapResult == 0 && kmsResult == 0 && dbResult == 0) { - printf("Transaction committed successfully - all backups cleaned up\n"); - } else { - fprintf(stderr, "Warning: Failed to clean up some backup files or database tables\n"); - } + // if (mapResult == 0 && kmsResult == 0 && dbResult == 0) { + // printf("Transaction committed successfully - all backups cleaned up\n"); + // } else { + // fprintf(stderr, "Warning: Failed to clean up some backup files or database tables\n"); + // } #endif } @@ -2089,14 +2080,14 @@ void delete_backup(bool is_transaction) { void recovery_backup(bool is_transaction) { int mapResult = 0, kmsResult = 0, dbResult = 0; - const char* map_path = MAP_FILE_PATH; + const char* map_path = MAP_JSON_PATH; const char* map_backup; - if(is_transaction) map_backup = MAP_BACKUP_PATH".t"; - else map_backup = MAP_BACKUP_PATH; - const char* kms_path = KMS_FILE_PATH; + if(is_transaction) map_backup = MAP_JSON_BACKUP_PATH".t"; + else map_backup = MAP_JSON_BACKUP_PATH; + const char* kms_path = CMK_FILE_PATH; const char* kms_backup; - if(is_transaction) kms_backup = KMS_BACKUP_PATH".t"; - else kms_backup = KMS_BACKUP_PATH; + if(is_transaction) kms_backup = CMK_FILE_BACKUP_PATH".t"; + else kms_backup = CMK_FILE_BACKUP_PATH; char* msg; // 恢复映射文件 @@ -2115,7 +2106,7 @@ void recovery_backup(bool is_transaction) { msg = "No map backup file found for rollback\n"; } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 恢复密钥文件 @@ -2135,19 +2126,18 @@ void recovery_backup(bool is_transaction) { } #ifndef NDEBUG - std::cout << msg << std::endl; + // std::cout << msg << std::endl; #endif // 恢复数据库表 - // dbResult = restoreDekStore(); dbResult = DekInterface::restoreDekStore(); #ifndef NDEBUG - if (mapResult == 0 && kmsResult == 0 && dbResult == 0) { - printf("Transaction rolled back successfully - all data restored\n"); - } else { - fprintf(stderr, "Error: Failed to completely rollback transaction\n"); - } + // if (mapResult == 0 && kmsResult == 0 && dbResult == 0) { + // printf("Transaction rolled back successfully - all data restored\n"); + // } else { + // fprintf(stderr, "Error: Failed to completely rollback transaction\n"); + // } #endif } diff --git a/src/encryptsql/main.cpp b/src/encryptsql/main.cpp index 989ee2d..8803c2e 100755 --- a/src/encryptsql/main.cpp +++ b/src/encryptsql/main.cpp @@ -39,17 +39,18 @@ extern "C" // #include "kms/KeyManagementService.hpp" // #include "kms/PGconnectForDEK.h" +#include "en_config.h" #include "kms/kms_interface.hpp" #include "kms/kms_core_local.hpp" #include "kmsAdapter/dek_interface.hpp" -#ifndef MAPPERPATH -#define MAPPERPATH "/etc/encryptsql/map.json" -#endif -#define CMKFILEPATH "/new_enc/kms_test/output.json" -#define CMKKEYPATH "/new_enc/kms_test/domainkey" -// 持久化文件路径 -#define CMK_AUTO_ROTATE_STATUS_PATH "/new_enc/kms_test/CMK_auto_rotate_status.json" +// #ifndef MAPPERPATH +// #define MAPPERPATH "/etc/encryptsql/map.json" +// #endif +// #define CMKFILEPATH "/new_enc/kms_test/output.json" +// #define CMKKEYPATH "/new_enc/kms_test/domainkey" +// // 持久化文件路径 +// #define CMK_AUTO_ROTATE_STATUS_PATH "/new_enc/kms_test/CMK_auto_rotate_status.json" extern void LogInfo(const char *fmt, ...); @@ -223,21 +224,29 @@ encryptOneSql(const char *sql, char **err_msg, const char *user_name, const char ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); //初始化映射表 - mapperInit(MAPPERPATH); + mapperInit(MAP_JSON_PATH); + //注册kms LocalKmsCore::registerLocalKms(); - - //初始化CMK - // cmk_mapperInit(CMKFILEPATH, CMKKEYPATH, CMK_AUTO_ROTATE_STATUS_PATH); - LocalKmsConfig config(CMKFILEPATH, CMKKEYPATH, CMK_AUTO_ROTATE_STATUS_PATH, user_name, db_name); + LocalKmsConfig config(CMK_FILE_PATH, CMK_KEY_PATH, CMK_ROTATE_STATUS_PATH, user_name, db_name); KMSInterface::initialize(config); - + +#if 0 + HuaweiKmsCore::registerHuaweiKms(); + HuaweiKmsConfig hwConfig( + "HPUAI1XPW4U0CPJCSE7C", // AK + "qSOZjbqKxffaqFm3FG7KrqV4MtAKYgsAVACB0ZLs", // SK + "d8aadaf24bde4314bf2789fb87f4ad83", // projectId + "cn-north-4", // region + "", // endpoint (可选) + "my-app-key" // keyAlias (可选) + ); + KMSInterface::initialize(hwConfig); +#endif + //初始化DEK DekInterface::initialize(user_name, db_name); - // InitializeKeyDistribution(); // 启动 DEK 接收服务 - // std::atexit(ShutdownKeyDistribution); - #ifdef USE_LRU // HECache.setName("Client HE"); // for RandNum(id) diff --git a/src/utils/LogBase.cpp b/src/utils/LogBase.cpp index 3913496..eddbdd7 100755 --- a/src/utils/LogBase.cpp +++ b/src/utils/LogBase.cpp @@ -1,5 +1,6 @@ #include "LogBase.h" #include "config.h" + #include namespace util { @@ -19,7 +20,7 @@ namespace util { m_enabled[log::timer] = false; int pid = getpid(); char logPath[64] = {0}; - sprintf(logPath, "/etc/encryptsql/encryptsql.%d.log", pid); + sprintf(logPath, ENCRYPTSQL_CONFIG_DIR "/encryptsql.%d.log", pid); this->appender = new log4cpp::FileAppender("fileAppender", logPath, false); auto pLayout = new log4cpp::PatternLayout(); diff --git a/src/utils/TimeCounter.h b/src/utils/TimeCounter.h index 3ba374b..f032a36 100755 --- a/src/utils/TimeCounter.h +++ b/src/utils/TimeCounter.h @@ -2,6 +2,7 @@ #pragma once #include "Timer.h" +#include "en_config.h" #include #include @@ -115,8 +116,8 @@ public: #endif char path1[64] = {0}; char path2[64] = {0}; - sprintf(path1, "/etc/encryptsql/counter_%d.log", pid); - sprintf(path2, "/etc/encryptsql/counter_%d.json", pid); + sprintf(path1, ENCRYPTSQL_CONFIG_DIR "/counter_%d.log", pid); + sprintf(path2, ENCRYPTSQL_CONFIG_DIR "/counter_%d.json", pid); FILE *fp = fopen(path1, "w"); FILE *jsonFp = fopen(path2, "w"); if (!fp || !jsonFp) { diff --git a/src/utils/en_config.h b/src/utils/en_config.h new file mode 100644 index 0000000..abec66a --- /dev/null +++ b/src/utils/en_config.h @@ -0,0 +1,28 @@ +#ifndef ENCRYPTSQL_CONFIG_H +#define ENCRYPTSQL_CONFIG_H + +// 安装路径(由 -DENCRYPTSQL_INSTALL_DIR=... 指定) +#define ENCRYPTSQL_INSTALL_DIR "/usr/local/postgresql" +#define ENCRYPTSQL_CONFIG_DIR "/etc/encryptsql" +#define DK_SERVER_HOST "127.0.0.1" +#define DK_SERVER_PORT "9443" + +#define CREATEUDF_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/createudf.sql" +#define MASK_FUNCS_SQL_PATH ENCRYPTSQL_INSTALL_DIR "/mask_funcs.sql" + +#define MAP_JSON_PATH ENCRYPTSQL_CONFIG_DIR "/map.json" +#define MAP_JSON_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/map.json.backup" + +#define CMK_FILE_PATH ENCRYPTSQL_CONFIG_DIR "/output.json" +#define CMK_FILE_BACKUP_PATH ENCRYPTSQL_CONFIG_DIR "/output.json.backup" + +#define CMK_KEY_PATH ENCRYPTSQL_CONFIG_DIR "/domainkey" +#define CMK_ROTATE_STATUS_PATH ENCRYPTSQL_CONFIG_DIR "/CMK_auto_rotate_status.json" + +#define ROOT_KEY_GEN_PATH ENCRYPTSQL_CONFIG_DIR "/kms_root" + +#define BACKUP_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/backup" +#define RESTORE_BIN_PATH ENCRYPTSQL_INSTALL_DIR "/bin/restore" + + +#endif /* ENCRYPTSQL_CONFIG_H */ diff --git a/src/utils/settings.h b/src/utils/settings.h index ab3abe7..3a11354 100755 --- a/src/utils/settings.h +++ b/src/utils/settings.h @@ -1,13 +1,16 @@ #pragma once +#include "en_config.h" + // 明文的数据类型, 依据不同的数据类型选择加密方案。 #define MAX_PLAIN_STRING_TYPE 4 #define NOEXIST "NNnoexistNN" // table or column not found in mapper -constexpr char CONFIG_PATH[] = "/etc/encryptsql/config.json"; +// constexpr char CONFIG_PATH[] = "/etc/encryptsql/config.json"; +constexpr char CONFIG_PATH[] = ENCRYPTSQL_CONFIG_DIR "/config.json"; constexpr double Float_Scale = 10000.0; -constexpr char ENCLAVE_FILENAME[] = "/etc/encryptsql/enclave.signed.so"; +constexpr char ENCLAVE_FILENAME[] = ENCRYPTSQL_CONFIG_DIR "/enclave.signed.so"; // crypto.h things #define DEFALUT_ENCRYPT_CIPHER CIPHER_AES // select target默认的加密列