diff --git a/Base/HttpSession.cpp b/Base/HttpSession.cpp index 30b3816..2dbfa0c 100644 --- a/Base/HttpSession.cpp +++ b/Base/HttpSession.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -75,15 +75,15 @@ void HttpSession::onRead(const boost::beast::error_code &error, std::size_t) { } auto &request = m_parser->get(); - auto path = boost::urls::parse_path(request.target()); + auto path = boost::urls::parse_origin_form(request.target()); if (!path) { - LOG(error) << request.target() << "failed, error: " << path.error().message(); + LOG(error) << request.target() << " failed, error: " << path.error().message(); errorReply(request, http::status::bad_request, "Illegal request-target"); return; } auto router = m_router.lock(); boost::urls::matches matches; - auto handler = router->find(*path, matches); + auto handler = router->find(path->encoded_segments(), matches); if (handler) { try { (*handler)(*this, request, matches); diff --git a/Server/Application.cpp b/Server/Application.cpp index 0e8aa7a..26ce2dc 100644 --- a/Server/Application.cpp +++ b/Server/Application.cpp @@ -51,6 +51,13 @@ Application::Application() : m_d{new ApplicationPrivate()} { m_database->open(m_settings->sqlitePath()); m_sessionStore = Singleton::construct(*m_ioContext->ioContext()); + // clang-format off + m_messageManager->subscribe([this](std::string_view url, RequestHandler handler) { + LOG(info)<<"register url: "<router->insert(url, handler); + }); + // clang-format on + m_corporationContext = Singleton::construct(*m_ioContext->ioContext()); m_corporationContext->start(); diff --git a/WeChat/CMakeLists.txt b/WeChat/CMakeLists.txt index 0300fdf..45bb023 100644 --- a/WeChat/CMakeLists.txt +++ b/WeChat/CMakeLists.txt @@ -1,8 +1,10 @@ add_library(WeChat Corporation/Context.h Corporation/Context.cpp + Corporation/WXBizMsgCrypt.h Corporation/WXBizMsgCrypt.cpp ) target_link_libraries(WeChat PUBLIC Base PUBLIC Kylin::Core + PUBLIC OpenSSL::Crypto ) \ No newline at end of file diff --git a/WeChat/Corporation/Context.cpp b/WeChat/Corporation/Context.cpp index 0576073..c476d01 100644 --- a/WeChat/Corporation/Context.cpp +++ b/WeChat/Corporation/Context.cpp @@ -1,14 +1,18 @@ #include "Context.h" +#include "Base/HttpSession.h" #include "Base/Messages.h" #include "Core/Logger.h" #include "Core/MessageManager.h" #include "Http/Utility.h" +#include "WXBizMsgCrypt.h" #include #include +#include #include #include #include #include +#include namespace WeChat { namespace Corporation { @@ -127,13 +131,43 @@ void Context::updateAccessToken() { void Context::registerMoneyNote() { // 接口说明: https://developer.work.weixin.qq.com/document/10514 + // https://amass.fun/api/v1/wx/moneynote + // /api/v1/wx/moneynote?msg_signature=1096371bf526609f8aaacc247b3bebf2fbe15969×tamp=1749021023&nonce=1748464240&echostr=1jccl4g1jk%2FMqIHQ445D9yOikKpcKkYOCMCLxqPSpKBtkMuKAuLGe8c6dbsTN5LZmRy0a45mxGvpqntvb3Vvxg%3D%3D using namespace Core; using namespace Older; using namespace boost::urls; + using namespace boost::beast; auto manager = Singleton::instance(); - manager->publish( - "/api/v1/wx/moneynote", - [this](HttpSession &session, const HttpRequest &request, const matches &matches) { LOG(info) << request.target(); }); + // clang-format off + manager->publish("/api/v1/wx/moneynote", [this](HttpSession &session, const HttpRequest &request, const matches &matches) { + auto path = boost::urls::parse_origin_form(request.target()); + auto params = path->params(); + auto msg_signature = params.find("msg_signature"); + auto timestamp = params.find("timestamp"); + auto nonce = params.find("nonce"); + + constexpr auto token = "BqnhzhsRqIJXO5k"; + constexpr auto encodingAESKey = "XMZ74tSRRe9MtEsEc9ihBTmvXxOisDrrFsukmcoPJR4"; + constexpr auto corpid = "ww1a786851749bdadc"; + std::string reply; + Tencent::WXBizMsgCrypt wxcpt(token, encodingAESKey, corpid); + if (request.method() == http::verb::get) { + auto echostr = params.find("echostr"); + wxcpt.VerifyURL((*msg_signature).value, (*timestamp).value, (*nonce).value, (*echostr).value, reply); + } else { + LOG(info) << "received: " << request.body(); + } + + LOG(info) << "reply: " << reply; + http::response s{boost::beast::http::status::ok, request.version()}; + s.set(http::field::server, BOOST_BEAST_VERSION_STRING); + s.set(http::field::content_type, "application/json;charset=UTF-8"); + s.keep_alive(request.keep_alive()); + s.body() = reply; + s.prepare_payload(); + session.reply(std::move(s)); + }); + // clang-format on } } // namespace Corporation diff --git a/WeChat/Corporation/WXBizMsgCrypt.cpp b/WeChat/Corporation/WXBizMsgCrypt.cpp new file mode 100644 index 0000000..c6b13f4 --- /dev/null +++ b/WeChat/Corporation/WXBizMsgCrypt.cpp @@ -0,0 +1,404 @@ + +#include "WXBizMsgCrypt.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "openssl/aes.h" +#include "openssl/evp.h" +#include "openssl/sha.h" + +#define FREE_PTR(ptr) \ + if (NULL != (ptr)) { \ + free(ptr); \ + (ptr) = NULL; \ + } + +#define DELETE_PTR(ptr) \ + if (NULL != (ptr)) { \ + delete (ptr); \ + (ptr) = NULL; \ + } + +namespace Tencent { + +int WXBizMsgCrypt::VerifyURL(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sEchoStr, std::string &sReplyEchoStr) { + if (0 != ValidateSignature(sMsgSignature, sTimeStamp, sNonce, sEchoStr)) { + return WXBizMsgCrypt_ValidateSignature_Error; + } + + // 1.decode base64 + std::string sAesData; + if (0 != DecodeBase64(sEchoStr, sAesData)) { + return WXBizMsgCrypt_DecodeBase64_Error; + } + + // 2.decode aes + std::string sAesKey; + std::string sNoEncryptData; + if (0 != GenAesKeyFromEncodingKey(m_sEncodingAESKey, sAesKey)) { + return WXBizMsgCrypt_IllegalAesKey; + } + if (0 != AES_CBCDecrypt(sAesData, sAesKey, &sNoEncryptData)) { + return WXBizMsgCrypt_DecryptAES_Error; + } + + // 3. remove kRandEncryptStrLen str + if (sNoEncryptData.size() <= (kRandEncryptStrLen + kMsgLen)) { + return WXBizMsgCrypt_IllegalBuffer; + } + uint32_t iNetLen = *((const uint32_t *)(sNoEncryptData.c_str() + kRandEncryptStrLen)); + uint32_t iMsgLen = ntohl(iNetLen); + if (sNoEncryptData.size() < (kRandEncryptStrLen + kMsgLen + iMsgLen)) { + return WXBizMsgCrypt_IllegalBuffer; + } + sReplyEchoStr = sNoEncryptData.substr(kRandEncryptStrLen + kMsgLen, iMsgLen); + + // 4. validate Corpid + std::string sReceiveId = sNoEncryptData.substr(kRandEncryptStrLen + kMsgLen + iMsgLen); + if (sReceiveId != m_sReceiveId) { + return WXBizMsgCrypt_ValidateCorpid_Error; + } + + return WXBizMsgCrypt_OK; +} + +int WXBizMsgCrypt::DecryptMsg(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sPostData, std::string &sMsg) { + // 1.validate xml format + boost::property_tree::ptree ptree; + std::istringstream iss(sPostData); + boost::property_tree::read_xml(iss, ptree); + std::string sEncryptMsg = ptree.get("Encrypt"); + + // 2.validate signature + if (0 != ValidateSignature(sMsgSignature, sTimeStamp, sNonce, sEncryptMsg)) { + return WXBizMsgCrypt_ValidateSignature_Error; + } + + // 3.decode base64 + std::string sAesData; + if (0 != DecodeBase64(sEncryptMsg, sAesData)) { + return WXBizMsgCrypt_DecodeBase64_Error; + } + + // 4.decode aes + std::string sAesKey; + std::string sNoEncryptData; + if (0 != GenAesKeyFromEncodingKey(m_sEncodingAESKey, sAesKey)) { + return WXBizMsgCrypt_IllegalAesKey; + } + if (0 != AES_CBCDecrypt(sAesData, sAesKey, &sNoEncryptData)) { + return WXBizMsgCrypt_DecryptAES_Error; + } + + // 5. remove kRandEncryptStrLen str + if (sNoEncryptData.size() <= (kRandEncryptStrLen + kMsgLen)) { + return WXBizMsgCrypt_IllegalBuffer; + } + uint32_t iNetLen = *((const uint32_t *)(sNoEncryptData.c_str() + kRandEncryptStrLen)); + uint32_t iMsgLen = ntohl(iNetLen); + if (sNoEncryptData.size() < (kRandEncryptStrLen + kMsgLen + iMsgLen)) { + return WXBizMsgCrypt_IllegalBuffer; + } + sMsg = sNoEncryptData.substr(kRandEncryptStrLen + kMsgLen, iMsgLen); + + // 6. validate corpid + std::string sReceiveId = sNoEncryptData.substr(kRandEncryptStrLen + kMsgLen + iMsgLen); + if (sReceiveId != m_sReceiveId) { + return WXBizMsgCrypt_ValidateCorpid_Error; + } + + return WXBizMsgCrypt_OK; +} + +int WXBizMsgCrypt::EncryptMsg(const std::string &sReplyMsg, const std::string &sTimeStamp, const std::string &sNonce, + std::string &sEncryptMsg) { + if (0 == sReplyMsg.size()) { + return WXBizMsgCrypt_ParseXml_Error; + } + + // 1.add rand str ,len, corpid + std::string sNeedEncrypt; + GenNeedEncryptData(sReplyMsg, sNeedEncrypt); + + // 2. AES Encrypt + std::string sAesData; + std::string sAesKey; + if (0 != GenAesKeyFromEncodingKey(m_sEncodingAESKey, sAesKey)) { + return WXBizMsgCrypt_IllegalAesKey; + } + if (0 != AES_CBCEncrypt(sNeedEncrypt, sAesKey, &sAesData)) { + return WXBizMsgCrypt_EncryptAES_Error; + } + + // 3. base64Encode + std::string sBase64Data; + if (0 != EncodeBase64(sAesData, sBase64Data)) { + return WXBizMsgCrypt_EncodeBase64_Error; + } + + // 4. compute signature + std::string sSignature; + if (0 != ComputeSignature(m_sToken, sTimeStamp, sNonce, sBase64Data, sSignature)) { + return WXBizMsgCrypt_ComputeSignature_Error; + } + + // 5. Gen xml + if (0 != GenReturnXml(sBase64Data, sSignature, sTimeStamp, sNonce, sEncryptMsg)) { + return WXBizMsgCrypt_GenReturnXml_Error; + } + return WXBizMsgCrypt_OK; +} + +int WXBizMsgCrypt::AES_CBCEncrypt(const std::string &objSource, const std::string &objKey, std::string *poResult) { + return AES_CBCEncrypt(objSource.data(), objSource.size(), objKey.data(), objKey.size(), poResult); +} + +int WXBizMsgCrypt::AES_CBCEncrypt(const char *sSource, const uint32_t iSize, const char *sKey, uint32_t iKeySize, + std::string *poResult) { + if (!sSource || !sKey || !poResult || iSize <= 0) { + return -1; + } + + poResult->clear(); + + int padding = kAesKeySize - iSize % kAesKeySize; + + char *tmp = (char *)malloc(iSize + padding); + if (NULL == tmp) { + return -1; + } + memcpy(tmp, sSource, iSize); + memset(tmp + iSize, padding, padding); + + unsigned char *out = (unsigned char *)malloc(iSize + padding); + if (NULL == out) { + FREE_PTR(tmp); + return -1; + } + + unsigned char key[kAesKeySize] = {0}; + unsigned char iv[kAesIVSize] = {0}; + memcpy(key, sKey, iKeySize > kAesKeySize ? kAesKeySize : iKeySize); + memcpy(iv, key, sizeof(iv) < sizeof(key) ? sizeof(iv) : sizeof(key)); + + AES_KEY aesKey; + AES_set_encrypt_key(key, 8 * kAesKeySize, &aesKey); + AES_cbc_encrypt((unsigned char *)tmp, out, iSize + padding, &aesKey, iv, AES_ENCRYPT); + poResult->append((char *)out, iSize + padding); + + FREE_PTR(tmp); + FREE_PTR(out); + return 0; +} + +int WXBizMsgCrypt::AES_CBCDecrypt(const std::string &objSource, const std::string &objKey, std::string *poResult) { + return AES_CBCDecrypt(objSource.data(), objSource.size(), objKey.data(), objKey.size(), poResult); +} + +int WXBizMsgCrypt::AES_CBCDecrypt(const char *sSource, const uint32_t iSize, const char *sKey, uint32_t iKeySize, + std::string *poResult) { + if (!sSource || !sKey || iSize < kAesKeySize || iSize % kAesKeySize != 0 || !poResult) { + return -1; + } + + poResult->clear(); + + unsigned char *out = (unsigned char *)malloc(iSize); + if (NULL == out) { + return -1; + } + + unsigned char key[kAesKeySize] = {0}; + unsigned char iv[kAesIVSize] = {0}; + memcpy(key, sKey, iKeySize > kAesKeySize ? kAesKeySize : iKeySize); + memcpy(iv, key, sizeof(iv) < sizeof(key) ? sizeof(iv) : sizeof(key)); + + int iReturnValue = 0; + AES_KEY aesKey; + AES_set_decrypt_key(key, 8 * kAesKeySize, &aesKey); + AES_cbc_encrypt((unsigned char *)sSource, out, iSize, &aesKey, iv, AES_DECRYPT); + if (out[iSize - 1] > 0 && out[iSize - 1] <= kAesKeySize && (iSize - out[iSize - 1]) > 0) { + poResult->append((char *)out, iSize - out[iSize - 1]); + } else { + iReturnValue = -1; + } + + FREE_PTR(out); + return iReturnValue; +} + +int WXBizMsgCrypt::EncodeBase64(const std::string sSrc, std::string &sTarget) { + if (0 == sSrc.size() || kMaxBase64Size < sSrc.size()) { + return -1; + } + + uint32_t iBlockNum = sSrc.size() / 3; + if (iBlockNum * 3 != sSrc.size()) { + iBlockNum++; + } + uint32_t iOutBufSize = iBlockNum * 4 + 1; + + char *pcOutBuf = (char *)malloc(iOutBufSize); + if (NULL == pcOutBuf) { + return -1; + } + int iReturn = 0; + int ret = EVP_EncodeBlock((unsigned char *)pcOutBuf, (const unsigned char *)sSrc.c_str(), sSrc.size()); + if (ret > 0 && ret < (int)iOutBufSize) { + sTarget.assign(pcOutBuf, ret); + } else { + iReturn = -1; + } + + FREE_PTR(pcOutBuf); + return iReturn; +} + +int WXBizMsgCrypt::DecodeBase64(const std::string sSrc, std::string &sTarget) { + if (0 == sSrc.size() || kMaxBase64Size < sSrc.size()) { + return -1; + } + + // 计算末尾=号个数 + int iEqualNum = 0; + for (int n = sSrc.size() - 1; n >= 0; --n) { + if (sSrc.c_str()[n] == '=') { + iEqualNum++; + } else { + break; + } + } + + int iOutBufSize = sSrc.size(); + char *pcOutBuf = (char *)malloc(iOutBufSize); + if (NULL == pcOutBuf) { + return -1; + } + + int iRet = 0; + int iTargetSize = 0; + iTargetSize = EVP_DecodeBlock((unsigned char *)pcOutBuf, (const unsigned char *)sSrc.c_str(), sSrc.size()); + if (iTargetSize > iEqualNum && iTargetSize < iOutBufSize) { + sTarget.assign(pcOutBuf, iTargetSize - iEqualNum); + } else { + iRet = -1; + } + + FREE_PTR(pcOutBuf); + return iRet; +} + +int WXBizMsgCrypt::ComputeSignature(const std::string sToken, const std::string sTimeStamp, const std::string &sNonce, + const std::string &sMessage, std::string &sSignature) { + if (0 == sToken.size() || 0 == sNonce.size() || 0 == sMessage.size() || 0 == sTimeStamp.size()) { + return -1; + } + + // sort + std::vector vecStr; + vecStr.push_back(sToken); + vecStr.push_back(sTimeStamp); + vecStr.push_back(sNonce); + vecStr.push_back(sMessage); + std::sort(vecStr.begin(), vecStr.end()); + std::string sStr = vecStr[0] + vecStr[1] + vecStr[2] + vecStr[3]; + + // compute + unsigned char output[SHA_DIGEST_LENGTH] = {0}; + if (NULL == SHA1((const unsigned char *)sStr.c_str(), sStr.size(), output)) { + return -1; + } + + // to hex + sSignature.clear(); + char tmpChar[8] = {0}; + for (int i = 0; i < SHA_DIGEST_LENGTH; i++) { + snprintf(tmpChar, sizeof(tmpChar), "%02x", 0xff & output[i]); + sSignature.append(tmpChar); + } + return 0; +} + +int WXBizMsgCrypt::ValidateSignature(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sEncryptMsg) { + std::string sSignature; + if (0 != ComputeSignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sSignature)) { + return -1; + } + + if (sMsgSignature != sSignature) { + return -1; + } + + return 0; +} + +int WXBizMsgCrypt::GenAesKeyFromEncodingKey(const std::string &sEncodingKey, std::string &sAesKey) { + if (kEncodingKeySize != sEncodingKey.size()) { + return -1; + } + + std::string sBase64 = sEncodingKey + "="; + int ret = DecodeBase64(sBase64, sAesKey); + if (0 != ret || kAesKeySize != sAesKey.size()) { + return -1; + } + + return 0; +} + +void WXBizMsgCrypt::GenRandStr(std::string &sRandStr, uint32_t len) { + uint32_t idx = 0; + srand((unsigned)time(NULL)); + char tempChar = 0; + sRandStr.clear(); + + while (idx < len) { + tempChar = rand() % 128; + if (isprint(tempChar)) { + sRandStr.append(1, tempChar); + ++idx; + } + } +} + +void WXBizMsgCrypt::GenNeedEncryptData(const std::string &sReplyMsg, std::string &sNeedEncrypt) { + // random(16B)+ msg_len(4B) + msg + $corpid + std::string sRandStr; + GenRandStr(sRandStr, kRandEncryptStrLen); + uint32_t iXmlSize = sReplyMsg.size(); + uint32_t iNSize = htonl(iXmlSize); + std::string sSize; + sSize.assign((const char *)&iNSize, sizeof(iNSize)); + + sNeedEncrypt.erase(); + sNeedEncrypt = sRandStr; + sNeedEncrypt += sSize; + sNeedEncrypt += sReplyMsg; + sNeedEncrypt += m_sReceiveId; +} + +int WXBizMsgCrypt::GenReturnXml(const std::string &sEncryptMsg, const std::string &sSignature, const std::string &sTimeStamp, + const std::string &sNonce, std::string &sResult) { + boost::property_tree::ptree ptree; + ptree.put("Encrypt", sEncryptMsg); + ptree.put("MsgSignature", sSignature); + ptree.put("TimeStamp", sTimeStamp); + ptree.put("Nonce", sNonce); + std::ostringstream oss; + boost::property_tree::write_xml(oss, ptree); + + sResult = oss.str(); + return 0; +} + +} // namespace Tencent diff --git a/WeChat/Corporation/WXBizMsgCrypt.h b/WeChat/Corporation/WXBizMsgCrypt.h new file mode 100644 index 0000000..fda9192 --- /dev/null +++ b/WeChat/Corporation/WXBizMsgCrypt.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include + +namespace Tencent { + +static const unsigned int kAesKeySize = 32; +static const unsigned int kAesIVSize = 16; +static const unsigned int kEncodingKeySize = 43; +static const unsigned int kRandEncryptStrLen = 16; +static const unsigned int kMsgLen = 4; +static const unsigned int kMaxBase64Size = 1000000000; +enum WXBizMsgCryptErrorCode { + WXBizMsgCrypt_OK = 0, + WXBizMsgCrypt_ValidateSignature_Error = -40001, + WXBizMsgCrypt_ParseXml_Error = -40002, + WXBizMsgCrypt_ComputeSignature_Error = -40003, + WXBizMsgCrypt_IllegalAesKey = -40004, + WXBizMsgCrypt_ValidateCorpid_Error = -40005, + WXBizMsgCrypt_EncryptAES_Error = -40006, + WXBizMsgCrypt_DecryptAES_Error = -40007, + WXBizMsgCrypt_IllegalBuffer = -40008, + WXBizMsgCrypt_EncodeBase64_Error = -40009, + WXBizMsgCrypt_DecodeBase64_Error = -40010, + WXBizMsgCrypt_GenReturnXml_Error = -40011, +}; + +class WXBizMsgCrypt { +public: + // 构造函数 + // @param sToken: 企业微信后台,开发者设置的Token + // @param sEncodingAESKey: 企业微信后台,开发者设置的EncodingAESKey + // @param sReceiveId: 不同场景含义不同,详见文档 + WXBizMsgCrypt(const std::string &sToken, const std::string &sEncodingAESKey, const std::string &sReceiveId) + : m_sToken(sToken), m_sEncodingAESKey(sEncodingAESKey), m_sReceiveId(sReceiveId) { + } + // 验证URL + // @param sMsgSignature: 签名串,对应URL参数的msg_signature + // @param sTimeStamp: 时间戳,对应URL参数的timestamp + // @param sNonce: 随机串,对应URL参数的nonce + // @param sEchoStr: 随机串,对应URL参数的echostr + // @param sReplyEchoStr: 解密之后的echostr,当return返回0时有效 + // @return:成功0,失败返回对应的错误码 + int VerifyURL(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sEchoStr, std::string &sReplyEchoStr); + + // 检验消息的真实性,并且获取解密后的明文 + // @param sMsgSignature: 签名串,对应URL参数的msg_signature + // @param sTimeStamp: 时间戳,对应URL参数的timestamp + // @param sNonce: 随机串,对应URL参数的nonce + // @param sPostData: 密文,对应POST请求的数据 + // @param sMsg: 解密后的原文,当return返回0时有效 + // @return: 成功0,失败返回对应的错误码 + int DecryptMsg(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sPostData, std::string &sMsg); + + // 将企业微信回复用户的消息加密打包 + // @param sReplyMsg:企业微信待回复用户的消息,xml格式的字符串 + // @param sTimeStamp: 时间戳,可以自己生成,也可以用URL参数的timestamp + // @param sNonce: 随机串,可以自己生成,也可以用URL参数的nonce + // @param sEncryptMsg: 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串, + // 当return返回0时有效 + // return:成功0,失败返回对应的错误码 + int EncryptMsg(const std::string &sReplyMsg, const std::string &sTimeStamp, const std::string &sNonce, + std::string &sEncryptMsg); + +private: + std::string m_sToken; + std::string m_sEncodingAESKey; + std::string m_sReceiveId; + +private: + // AES CBC + int AES_CBCEncrypt(const char *sSource, const uint32_t iSize, const char *sKey, unsigned int iKeySize, std::string *poResult); + + int AES_CBCEncrypt(const std::string &objSource, const std::string &objKey, std::string *poResult); + + int AES_CBCDecrypt(const char *sSource, const uint32_t iSize, const char *sKey, uint32_t iKeySize, std::string *poResult); + + int AES_CBCDecrypt(const std::string &objSource, const std::string &objKey, std::string *poResult); + + // base64 + int EncodeBase64(const std::string sSrc, std::string &sTarget); + + int DecodeBase64(const std::string sSrc, std::string &sTarget); + + // genkey + int GenAesKeyFromEncodingKey(const std::string &sEncodingKey, std::string &sAesKey); + + // signature + int ComputeSignature(const std::string sToken, const std::string sTimeStamp, const std::string &sNonce, + const std::string &sMessage, std::string &sSignature); + + int ValidateSignature(const std::string &sMsgSignature, const std::string &sTimeStamp, const std::string &sNonce, + const std::string &sEncryptMsg); + + // get , set data + void GenRandStr(std::string &sRandStr, uint32_t len); + + void GenNeedEncryptData(const std::string &sReplyMsg, std::string &sNeedEncrypt); + + int GenReturnXml(const std::string &sEncryptMsg, const std::string &sSignature, const std::string &sTimeStamp, + const std::string &sNonce, std::string &sResult); +}; + +} // namespace Tencent diff --git a/resources/build.sh b/resources/build.sh index e096fa6..54f75b8 100755 --- a/resources/build.sh +++ b/resources/build.sh @@ -19,7 +19,7 @@ function cmake_scan() { ${cmake_exe} -G Ninja -S ${base_path} -B ${build_path} \ -DCMAKE_BUILD_TYPE=Debug \ -DMbedTLS_DIR=${libraries_root}/mbedtls-3.6.3.1/lib/cmake/MbedTLS \ - -Dnng_DIR=${libraries_root}/nng-1.10.1/lib/cmake/nng \ + -Dnng_DIR=${libraries_root}/nng-1.11/lib/cmake/nng \ -DBOOST_ROOT=${libraries_root}/boost_1_88_0 } @@ -52,4 +52,4 @@ function main() { main $@ -# docker run -it -d --name ubuntu -v ~/Projects:/home/amass/Projects registry.cn-shenzhen.aliyuncs.com/amass_toolset/ubuntu_dev:24.04-qt6.9.0 +# docker run -it -d --name ubuntu --hostname Ubuntu -v ~/Projects:/home/amass/Projects registry.cn-shenzhen.aliyuncs.com/amass_toolset/ubuntu_dev:24.04-qt6.9.1