From e93572f0019eff8063fb9ba287eb2f4e71f071e1 Mon Sep 17 00:00:00 2001 From: a158 Date: Mon, 16 Mar 2026 17:50:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0usersig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- src/tencent_sdk_trtc.cpp | 10 ++- src/tencent_sdk_trtc.h | 16 +++++ src/usersig.cpp | 134 +++++++++++++++++++++++++++++++++++++++ src/usersig.h | 22 +++++++ 5 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/usersig.cpp create mode 100644 src/usersig.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f2d034..d708aab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,8 @@ foreach(header IN LISTS HEADER_FILES) endforeach() set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + # 安装复制 set(CMAKE_INSTALL_ALWAYS_COPY TRUE) diff --git a/src/tencent_sdk_trtc.cpp b/src/tencent_sdk_trtc.cpp index 9526745..d17e095 100644 --- a/src/tencent_sdk_trtc.cpp +++ b/src/tencent_sdk_trtc.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "usersig.h" using namespace TencentCloud; using namespace TencentCloud::Trtc::V20190722; using namespace TencentCloud::Trtc::V20190722::Model; @@ -72,11 +73,18 @@ std::pair module::tencent_sdk_trtc::dismissRoomByStrRoomId(con // 输出json格式的字符串回包 return std::make_pair(true, resp.ToJsonString()); } + +std::string module::tencent_sdk_trtc::getUserSig(long long sdkappid,const std::string& secret_key,const std::string& user_id,int expire_time) +{ + std::string sig = GenerateUserSig(user_id, sdkappid, secret_key, expire_time); + return sig; +} void module::tencent_sdk_trtc::regist(sol::state* lua) { lua->new_usertype("fw_tencent_sdk_trtc", "new", sol::constructors(), - "dismissRoomByStrRoomId", &module::tencent_sdk_trtc::dismissRoomByStrRoomId + "dismissRoomByStrRoomId", &module::tencent_sdk_trtc::dismissRoomByStrRoomId, + "getUserSig", &module::tencent_sdk_trtc::getUserSig ); } diff --git a/src/tencent_sdk_trtc.h b/src/tencent_sdk_trtc.h index d6a71e9..e19b922 100644 --- a/src/tencent_sdk_trtc.h +++ b/src/tencent_sdk_trtc.h @@ -24,6 +24,22 @@ namespace module long long sdkappid, const std::string& room_id ); + + + /** + * @brief 获取用户签名 + * @param sdkappid SDKAPPID + * @param secret_key 密钥 + * @param user_id 用户ID + * @param expire_time 过期时间 + * @return 用户签名 + */ + std::string getUserSig( + long long sdkappid, + const std::string& secret_key, + const std::string& user_id, + int expire_time + ); private: virtual void regist_global(const char* name, sol::state* lua); virtual void delete_global() { delete this; } diff --git a/src/usersig.cpp b/src/usersig.cpp new file mode 100644 index 0000000..5d6638e --- /dev/null +++ b/src/usersig.cpp @@ -0,0 +1,134 @@ +#include "usersig.h" + +#include +#include +#include +#include + +#include +#include +#include + + +// 简单的 Base64 实现 +const std::string BASE64_CHARS = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +std::string base64Encode(const unsigned char* data, size_t len) { + std::string ret; + ret.reserve(((len + 2) / 3) * 4); + + unsigned int val = 0; + int valb = -6; + for (size_t i = 0; i < len; ++i) { + val = (val << 8) + data[i]; + valb += 8; + while (valb >= 0) { + ret.push_back(BASE64_CHARS[(val >> valb) & 0x3F]); + valb -= 6; + } + } + if (valb > -6) { + ret.push_back(BASE64_CHARS[((val << 8) >> (valb + 8)) & 0x3F]); + } + while (ret.size() % 4) { + ret.push_back('='); + } + return ret; +} + +// '+' -> '*', '/' -> '-', '=' -> '_' +std::string base64ToUrlSafe(std::string s) { + for (char& c : s) { + if (c == '+') c = '*'; + else if (c == '/') c = '-'; + else if (c == '=') c = '_'; + } + return s; +} + +// 使用 OpenSSL 计算 HMAC-SHA256 +std::string hmacSHA256(const std::string& key, const std::string& msg) { + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_len = 0; + + if (!HMAC(EVP_sha256(), + key.data(), static_cast(key.size()), + reinterpret_cast(msg.data()), + msg.size(), + md, &md_len)) { + throw std::runtime_error("HMAC(EVP_sha256) 计算失败"); + } + + return std::string(reinterpret_cast(md), md_len); +} + +// 使用 zlib 压缩 +std::string zlibCompress(const std::string& input) { + if (input.empty()) return std::string(); + + uLong srcLen = static_cast(input.size()); + uLong destLen = compressBound(srcLen); + std::vector out(destLen); + + int ret = compress2(out.data(), &destLen, + reinterpret_cast(input.data()), + srcLen, Z_BEST_SPEED); + if (ret != Z_OK) { + throw std::runtime_error("zlib compress2 失败, ret = " + std::to_string(ret)); + } + + return std::string(reinterpret_cast(out.data()), destLen); +} + + +std::string GenerateUserSig(const std::string& user_id, + int sdk_app_id, + const std::string& secret_key, + std::uint32_t expire) { + if (sdk_app_id <= 0) { + throw std::invalid_argument("sdk_app_id 无效"); + } + if (secret_key.empty()) { + throw std::invalid_argument("secret_key 不能为空"); + } + + std::uint32_t curr_time = static_cast(std::time(nullptr)); + + // 1. 生成需要 HMAC 的原始字符串 + std::ostringstream ss; + ss << "TLS.identifier:" << user_id << "\n" + << "TLS.sdkappid:" << sdk_app_id << "\n" + << "TLS.time:" << curr_time << "\n" + << "TLS.expire:" << expire << "\n"; + std::string content_to_sign = ss.str(); + + // 2. 计算 HMAC-SHA256 并做标准 Base64 + std::string hmac_res = hmacSHA256(secret_key, content_to_sign); + std::string sig = base64Encode( + reinterpret_cast(hmac_res.data()), + hmac_res.size()); + + // 3. 拼接 JSON + std::ostringstream json; + json << "{" + << "\"TLS.ver\":\"2.0\"," + << "\"TLS.identifier\":\"" << user_id << "\"," + << "\"TLS.sdkappid\":" << sdk_app_id << "," + << "\"TLS.expire\":" << expire << "," + << "\"TLS.time\":" << curr_time << "," + << "\"TLS.sig\":\"" << sig << "\"" + << "}"; + std::string json_str = json.str(); + + // 4. 压缩 + Base64 + URL 安全替换 + std::string compressed = zlibCompress(json_str); + std::string b64 = base64Encode( + reinterpret_cast(compressed.data()), + compressed.size()); + std::string url_safe = base64ToUrlSafe(b64); + + return url_safe; +} \ No newline at end of file diff --git a/src/usersig.h b/src/usersig.h new file mode 100644 index 0000000..b56eb29 --- /dev/null +++ b/src/usersig.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +// 生成 TRTC UserSig(TLS-SigAPIv2) +// 参数: +// - user_id : 用户 ID,对应 TLS.identifier +// - sdk_app_id : 控制台创建的 TRTC 应用 SDKAppID +// - secret_key : 控制台获取的密钥 SecretKey +// - expire : 过期时间(秒),例如 7 * 24 * 60 * 60 +// +// 返回: +// - 用于 TRTC 鉴权的 UserSig 字符串 +// +// 说明: +// - 该函数仅做算法封装,不做任何网络/IO 操作 +// - 推荐在服务端调用本函数生成 UserSig,再下发到客户端 +std::string GenerateUserSig(const std::string& user_id, + int sdk_app_id, + const std::string& secret_key, + std::uint32_t expire);