diff --git a/.vscode/settings.json b/.vscode/settings.json index 69bc411..e02710f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,7 +30,8 @@ "cmake.configureArgs": [ "-Wno-dev", "-DCMAKE_PREFIX_PATH:STRING=C:/dev/wxwigets", - "-DUSE_GUI=ON" + "-DUSE_GUI=ON", + "-DUSE_TRANSM_TEST=ON" ], "cmake.options.statusBarVisibility": "visible", "cmake.generator": "Ninja", diff --git a/CMakeLists.txt b/CMakeLists.txt index 278f0c9..36e0ccd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(transm VERSION 1.4.1 LANGUAGES CXX) +project(transm VERSION 1.4.2 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -57,6 +57,11 @@ add_subdirectory(client) add_subdirectory(filecomplete) add_subdirectory(tinyaes) +if (DEFINED USE_TRANSM_TEST) +message(STATUS "USE USE_TRANSM_TEST ${USE_TRANSM_TEST}") +add_subdirectory(test) +endif() + string(TIMESTAMP VERSION_BUILD_DATE "%Y-%m-%d %H:%M") execute_process( COMMAND git rev-parse --short HEAD diff --git a/client/client.cpp b/client/client.cpp index e2109db..4fe6153 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -338,7 +338,7 @@ bool CClient::cmd_sub_list(const std::string& param) return false; } - CMessageInfo msg_info; + CMessageInfo msg_info(own_id_); msg_info.uuid = uuid_; msg_info.str = msg; @@ -426,7 +426,7 @@ bool CClient::cmd_upload_files(const std::string& param) list_file_ = "auto_list"; std::shared_ptr buf = std::make_shared(); buf->type_ = TYPE_REQUEST_UPDATE_LIST; - CMessageInfo msg_info; + CMessageInfo msg_info(own_id_); msg_info.str = handel_ret; serialize(msg_info, &buf->data_, buf->len_); buf->tid_ = clients_[index]->id; @@ -472,7 +472,7 @@ bool CClient::down_one_file(int remote_id, const std::string& file, const std::s std::shared_ptr buf = std::make_shared(); buf->type_ = TYPE_OPEN_FILE; buf->tid_ = client->id; - CMessageInfo msg_info; + CMessageInfo msg_info(own_id_); msg_info.str = file; serialize(msg_info, &buf->data_, buf->len_); if (!send_frame(buf.get())) { @@ -649,7 +649,7 @@ bool CClient::cmd_sub_task(const std::string& param, bool is_send) } else { buf->type_ = TYPE_REQUEST_DOWN_UPDATE_LIST; } - CMessageInfo msg_info; + CMessageInfo msg_info(own_id_); msg_info.str = handel_ret; serialize(msg_info, &buf->data_, buf->len_); buf->tid_ = clients_[index]->id; @@ -757,7 +757,7 @@ bool CClient::cmd_ls(const std::string& param) const auto& sr = clients_[index]; std::shared_ptr buf = std::make_shared(); buf->type_ = TYPE_GET_DIRFILES; - CMessageInfo msg_info{}; + CMessageInfo msg_info(own_id_); msg_info.str = path; serialize(msg_info, &buf->data_, buf->len_); buf->tid_ = sr->id; @@ -949,7 +949,7 @@ void CClient::get_id() { auto* bf = new CFrameBuffer(); bf->type_ = TYPE_GET_ID; - CMessageInfo msg_info; + CMessageInfo msg_info(own_id_); msg_info.uuid = uuid_; serialize(msg_info, &bf->data_, bf->len_); send_frame(bf); @@ -970,7 +970,7 @@ void CClient::handle_frame(CFrameBuffer* buf) } case TYPE_GET_LIST: { clients_.clear(); - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetList deserialize failed.", __LINE__); break; @@ -1044,7 +1044,7 @@ void CClient::handle_frame(CFrameBuffer* buf) break; } case TYPE_GET_DIRFILES: { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetDirFiles deserialize failed.", __LINE__); break; @@ -1071,7 +1071,7 @@ void CClient::handle_frame(CFrameBuffer* buf) break; } case TYPE_GET_DIRFILES_FAILED: { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetDirFiles deserialize failed.", __LINE__); break; @@ -1080,7 +1080,7 @@ void CClient::handle_frame(CFrameBuffer* buf) break; } case TYPE_GET_DIRFILES_DONE: { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetDirFiles deserialize failed.", __LINE__); break; @@ -1107,7 +1107,7 @@ void CClient::handle_frame(CFrameBuffer* buf) } case TYPE_OPEN_FILE: { std::string keys{}; - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} OpenFile deserialize failed.", __LINE__); break; @@ -1172,7 +1172,7 @@ void CClient::handle_frame(CFrameBuffer* buf) break; } case TYPE_REQUEST_DOWN_UPDATE_LIST: { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetList deserialize failed.", __LINE__); break; @@ -1194,7 +1194,7 @@ void CClient::handle_frame(CFrameBuffer* buf) TLOGW("Update Busy......, Ignore {}", buf->fid_); buf->type_ = TYPE_BUSY_UPDATE_LIST; } else { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetList deserialize failed.", __LINE__); break; diff --git a/server/server.cpp b/server/server.cpp index 98ee398..ab58001 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -135,7 +135,7 @@ void CTcpServer::trans_data(CFrameBuffer* buf) switch (buf->type_) { case TYPE_GET_LIST: { TLOGI("[{}] GetList.", buf->fid_); - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); get_client_list(msg_info); serialize(msg_info, &buf->data_, buf->len_); if (fcli && !send_frame(fcli->socket_, buf)) { @@ -144,7 +144,7 @@ void CTcpServer::trans_data(CFrameBuffer* buf) break; } case TYPE_UP_LIST: { - CMessageInfo msg_info; + CMessageInfo msg_info(buf->fid_); if (!deserialize(buf->data_, buf->len_, msg_info)) { TLOGE("{} GetList deserialize failed.", __LINE__); break; @@ -303,7 +303,7 @@ void CTcpServer::th_client(const std::shared_ptr& socket, continue; } if (frame->type_ == TYPE_GET_ID) { - CMessageInfo msg_info; + CMessageInfo msg_info(""); if (!deserialize(frame->data_, frame->len_, msg_info)) { TLOGE("{} GetId deserialize failed.", __LINE__); delete frame; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..baec64a --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) + +project(test LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 17) + +add_executable(test main.cxx) +target_link_libraries(test PRIVATE tinyaes trans_util) \ No newline at end of file diff --git a/test/main.cxx b/test/main.cxx new file mode 100644 index 0000000..2a76367 --- /dev/null +++ b/test/main.cxx @@ -0,0 +1,21 @@ +#include +#include +#include + +int main() +{ + std::string key = "sss"; + uint8_t ik[32]{}; + hash(key.c_str(), ik); + + char* msg = new char[256]{}; + auto len = std::snprintf(msg + 12, 256, "%s", "hello world"); + std::cout << encrypt(ik, (uint8_t*)msg, len + 12) << std::endl; + + uint8_t ik2[32]{}; + hash(key.c_str(), ik2); + + std::cout << decrypt(ik2, (uint8_t*)msg, len + 12) << std::endl; + + return 0; +} \ No newline at end of file diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index 4213118..8ad138e 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -9,5 +9,5 @@ endif() set(SOURCES util.h util.cpp) add_library(trans_util STATIC ${SOURCES}) -target_link_libraries(trans_util PUBLIC ofen filecomplete) +target_link_libraries(trans_util PUBLIC ofen filecomplete tinyaes) target_include_directories(trans_util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/util/util.cpp b/util/util.cpp index c893ff6..2a27f80 100644 --- a/util/util.cpp +++ b/util/util.cpp @@ -1,12 +1,14 @@ #include "util.h" +#include #include #include #include +#include #include CTransProtocal::CTransProtocal() = default; - +constexpr uint8_t kz = 12; CTransProtocal::~CTransProtocal() = default; /* @@ -134,23 +136,23 @@ CFrameBuffer::~CFrameBuffer() void serialize(const CMessageInfo& msg_info, char** out_buf, int& len) { CMessageInfo info(msg_info); - info.cmd = localtou8(info.cmd); + info.id = localtou8(info.id); info.uuid = localtou8(info.uuid); info.str = localtou8(info.str); info.o = localtou8(info.o); // 计算总长度 - len = sizeof(int) * 4 + info.cmd.size() + info.uuid.size() + info.str.size() + info.o.size(); + len = sizeof(int) * 4 + info.id.size() + info.uuid.size() + info.str.size() + info.o.size() + kz; *out_buf = new char[len]; // 分配内存(调用方负责释放) - char* ptr = *out_buf; + char* ptr = *out_buf + kz; // 序列化 cmd - int cmd_size = static_cast(info.cmd.size()); - memcpy(ptr, &cmd_size, sizeof(int)); + int id_size = static_cast(info.id.size()); + memcpy(ptr, &id_size, sizeof(int)); ptr += sizeof(int); - memcpy(ptr, info.cmd.data(), cmd_size); - ptr += cmd_size; + memcpy(ptr, info.id.data(), id_size); + ptr += id_size; // 序列化 uuid int uuid_size = static_cast(info.uuid.size()); @@ -171,12 +173,28 @@ void serialize(const CMessageInfo& msg_info, char** out_buf, int& len) memcpy(ptr, &o_size, sizeof(int)); ptr += sizeof(int); memcpy(ptr, info.o.data(), o_size); + + uint8_t ik[32]{}; + hash(msg_info.id.c_str(), ik); + if (!encrypt(ik, (uint8_t*)(*out_buf), len)) { + return; + } } -bool deserialize(const char* data, int len, CMessageInfo& msg_info) +bool deserialize(char* data, int len, CMessageInfo& msg_info) { - CMessageInfo info; - const char* ptr = data; + if (len < kz) { + return false; + } + + uint8_t ik[32]{}; + hash(msg_info.id.c_str(), ik); + if (!decrypt(ik, (uint8_t*)(data), len)) { + return false; + } + + CMessageInfo info(msg_info.id); + char* ptr = data + kz; int remaining = len; // 反序列化 cmd @@ -184,17 +202,17 @@ bool deserialize(const char* data, int len, CMessageInfo& msg_info) return false; } - int cmd_size; - memcpy(&cmd_size, ptr, sizeof(int)); + int id_size; + memcpy(&id_size, ptr, sizeof(int)); ptr += sizeof(int); remaining -= sizeof(int); - if (remaining < cmd_size) { + if (remaining < id_size) { return false; } - info.cmd.assign(ptr, cmd_size); - ptr += cmd_size; - remaining -= cmd_size; + info.id.assign(ptr, id_size); + ptr += id_size; + remaining -= id_size; // 反序列化 uuid if (remaining < static_cast(sizeof(int))) { @@ -243,7 +261,7 @@ bool deserialize(const char* data, int len, CMessageInfo& msg_info) } info.o.assign(ptr, o_size); - info.cmd = u8tolocal(info.cmd); + info.id = u8tolocal(info.id); info.uuid = u8tolocal(info.uuid); info.str = u8tolocal(info.str); info.o = u8tolocal(info.o); @@ -270,12 +288,65 @@ std::string localtou8(const std::string& str) #endif } +void hash(const char* data, uint8_t k[32]) +{ + uint32_t h = 5381; + for (const char* p = data; *p; p++) { + h = ((h << 5) + h) + *p; // DJB2 + } + for (int i = 0; i < 32; i++) { + k[i] = (h >> (i % 4 * 8)) & 0xFF; + } +} + +void rdm(uint8_t* o, size_t size) +{ + std::random_device rd; + std::uniform_int_distribution dist(0, 255); + std::generate(o, o + size, [&]() { return dist(rd); }); +} + +bool encrypt(const uint8_t* k, uint8_t* m, size_t len) +{ + if (len < kz) { + return false; + } + + uint8_t nonce[kz]{}; + rdm(nonce, sizeof(nonce)); + memcpy(m, nonce, kz); + + struct AES_ctx ctx; + AES_init_ctx_iv(&ctx, k, nonce); + AES_CTR_xcrypt_buffer(&ctx, m + kz, len - kz); + return true; +} + +bool decrypt(const uint8_t* k, uint8_t* m, size_t len) +{ + if (len < kz) { + return false; + } + + uint8_t nonce[kz]{}; + memcpy(nonce, m, kz); + + struct AES_ctx ctx; + AES_init_ctx_iv(&ctx, k, nonce); + AES_CTR_xcrypt_buffer(&ctx, m + kz, len - kz); + return true; +} + +CMessageInfo::CMessageInfo(const std::string& id) : id(id) +{ +} + CMessageInfo::CMessageInfo(const CMessageInfo& info) { if (&info == this) { return; } - cmd = info.cmd; + id = info.id; uuid = info.uuid; str = info.str; o = info.o; @@ -286,7 +357,7 @@ CMessageInfo& CMessageInfo::operator=(const CMessageInfo& info) if (&info == this) { return *this; } - cmd = info.cmd; + id = info.id; uuid = info.uuid; str = info.str; o = info.o; diff --git a/util/util.h b/util/util.h index a11df9a..cfdbe7d 100644 --- a/util/util.h +++ b/util/util.h @@ -44,19 +44,23 @@ enum FrameType : int16_t { // 此结构体成员顺序不可变动,涉及到序列化反序列化。 struct CMessageInfo { - CMessageInfo() = default; + CMessageInfo(const std::string& id); CMessageInfo(const CMessageInfo& info); CMessageInfo& operator=(const CMessageInfo& info); - std::string cmd; + std::string id; std::string uuid; std::string str; std::string o; }; void serialize(const CMessageInfo& msg_info, char** out_buf, int& len); -bool deserialize(const char* data, int len, CMessageInfo& msg_info); +bool deserialize(char* data, int len, CMessageInfo& msg_info); std::string u8tolocal(const std::string& str); std::string localtou8(const std::string& str); +void hash(const char* data, uint8_t k[32]); +void rdm(uint8_t* o, size_t size); +bool encrypt(const uint8_t* k, uint8_t* m, size_t len); +bool decrypt(const uint8_t* k, uint8_t* m, size_t len); using namespace ofen; class CFrameBuffer