Package.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. // CommPackageImp.cpp: implementation of the CCommPackage class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "Package.h"
  5. #include <time.h>
  6. #include <assert.h>
  7. #include <memory>
  8. #include <winpr/crt.h>
  9. #ifdef WIN32
  10. #include "xzip.h"
  11. #include "xunzip.h"
  12. //当前未使用数据加密
  13. #endif // WIN32
  14. #include "openssl/md5.h"
  15. //#include "openssl/des.h"
  16. //2019年12月8日
  17. //#pragma comment(lib, "libeay32.lib")
  18. //////////////////////////////////////////////////////////////////////
  19. // Construction/Destruction
  20. //////////////////////////////////////////////////////////////////////
  21. DWORD CCommPackage::m_nLastReqTime(0);
  22. WORD CCommPackage::m_nLastReqSN(0);
  23. CCommPackage::CCommPackage(const BYTE sessionKey[16], const char *pServiceCode)
  24. {
  25. if (sessionKey != NULL)
  26. {
  27. memcpy(m_SessionKey, sessionKey, 16);
  28. // 前8个字节作为DesKey,后8个字节作为IVec
  29. DES_set_key_unchecked((BYTE(*)[8])&m_SessionKey, &m_DesKey);
  30. //memcpy(m_DesIVec, m_SessionKey+8, 8);
  31. m_bHasSessionKey = true;
  32. }
  33. else
  34. {
  35. memset(m_SessionKey, 0, 16);
  36. m_bHasSessionKey = false;
  37. }
  38. m_Header.m_nStructNum =0;
  39. m_Header.m_nPackageLen = sizeof(CPackageHeader);
  40. if (pServiceCode != NULL)
  41. {
  42. if (strlen(pServiceCode) >=8)
  43. memcpy(m_Header.m_arrServiceCode, pServiceCode, 8);
  44. else
  45. strcpy(m_Header.m_arrServiceCode, pServiceCode);
  46. }
  47. }
  48. CCommPackage::CCommPackage(CCommPackage *pkg)
  49. {
  50. m_bHasSessionKey = pkg->m_bHasSessionKey;
  51. if (m_bHasSessionKey)
  52. {
  53. memcpy(m_SessionKey, pkg->m_SessionKey, 16);
  54. // 前8个字节作为DesKey,后8个字节作为IVec
  55. DES_set_key_unchecked((BYTE(*)[8])&m_SessionKey, &m_DesKey);
  56. //memcpy(m_DesIVec, m_SessionKey+8, 8);
  57. }
  58. else
  59. {
  60. memset(m_SessionKey, 0, 16);
  61. }
  62. m_Header.m_nStructNum =0;
  63. m_Header.m_nPackageLen = sizeof(CPackageHeader);
  64. // 拷贝ServiceCode
  65. memcpy(m_Header.m_arrServiceCode, pkg->m_Header.m_arrServiceCode, 8);
  66. // 拷贝ReqTime和DSN
  67. m_Header.m_nReqTime = pkg->m_Header.m_nReqTime;
  68. m_Header.m_nSN = pkg->m_Header.m_nSN;
  69. }
  70. CCommPackage::~CCommPackage()
  71. {
  72. Clear();
  73. }
  74. void CCommPackage::Clear()
  75. {
  76. std::vector<CStructDef *>::iterator it;
  77. for(it = m_Structs.begin(); it != m_Structs.end(); it++)
  78. {
  79. if ((*it)->m_pData != NULL)
  80. delete[](*it)->m_pData;
  81. delete *it;
  82. }
  83. m_Structs.clear();
  84. memset(&m_Header, 0, sizeof(CPackageHeader));
  85. }
  86. void CCommPackage::AddStruct(const char *pStructName, bool bZip,
  87. bool bEncrypt, BYTE *pDataBuf, int nBufLen, int nArrayNum)
  88. {
  89. assert(m_Header.m_nPackageLen + nBufLen + CStructDef::GetStructDefLen() < 0xFFFF);
  90. CStructDef *pDef = new CStructDef();
  91. if (strlen(pStructName) <8)
  92. strcpy(pDef->m_arrName, pStructName);
  93. else
  94. memcpy(pDef->m_arrName, pStructName, 8);
  95. pDef->m_nArrayNum = nArrayNum;
  96. pDef->m_cEncCode = 'N';
  97. pDef->m_cZipCode = 'N';
  98. pDef->m_nSourceLen = nBufLen;
  99. pDef->m_nTargetLen = nBufLen;
  100. pDef->m_pData = new BYTE[nBufLen];
  101. memcpy(pDef->m_pData, pDataBuf, nBufLen);
  102. // 先压缩,后加密,提高压缩效率
  103. if (bZip)
  104. {
  105. // 压缩后最大长度不应大于源长度
  106. int nTempBufLen = pDef->m_nTargetLen;
  107. BYTE *pTempBuf = new BYTE[nTempBufLen];
  108. memset(pTempBuf, 0, nTempBufLen);
  109. if (ZipData(pDef->m_pData, pDef->m_nTargetLen, pTempBuf, &nTempBufLen))
  110. {
  111. delete[] pDef->m_pData;
  112. pDef->m_pData = pTempBuf;
  113. pDef->m_nTargetLen = nTempBufLen;
  114. pDef->m_cZipCode = 'Y';
  115. }
  116. else
  117. delete[] pTempBuf;
  118. }
  119. // 加密,加密后长度可能变长,变成8的倍数。需要在输出数据前加上4字节长度,指明加密前长度
  120. if (bEncrypt && m_bHasSessionKey)
  121. {
  122. // 加密后最大长度
  123. int nTempBufLen = pDef->m_nTargetLen + 12;
  124. BYTE *pTempBuf = new BYTE[nTempBufLen];
  125. memset(pTempBuf, 0, nTempBufLen);
  126. if (EncryptData(pDef->m_pData, pDef->m_nTargetLen, pTempBuf, &nTempBufLen))
  127. {
  128. delete[] pDef->m_pData;
  129. pDef->m_pData = pTempBuf;
  130. pDef->m_nTargetLen = nTempBufLen; // 加密后实际长度
  131. pDef->m_cEncCode = 'Y';
  132. }
  133. else
  134. {
  135. delete[] pTempBuf;
  136. }
  137. }
  138. // 保存到结构定义
  139. m_Structs.push_back(pDef);
  140. // 处理包头
  141. m_Header.m_nStructNum++;
  142. m_Header.m_nPackageLen += pDef->m_nTargetLen + CStructDef::GetStructDefLen();
  143. }
  144. void CCommPackage::SetErrMsg(DWORD dwSysCode, DWORD dwUserCode, const char *pErrMsg)
  145. {
  146. char buf[512];
  147. memset(buf, 0, sizeof(buf));
  148. CErrorReturn *pErrRet = (CErrorReturn*) buf;
  149. pErrRet->m_dwSysCode = dwSysCode;
  150. pErrRet->m_dwUserCode = dwUserCode;
  151. int nDataLen =8;
  152. if (strlen(pErrMsg) >= 256)
  153. {
  154. memcpy(pErrRet->m_arrErrMsg, pErrMsg, 256);
  155. nDataLen += 256;
  156. }
  157. else
  158. {
  159. strcpy(pErrRet->m_arrErrMsg, pErrMsg);
  160. nDataLen += strlen(pErrMsg);
  161. //nDataLen += 256; // 考虑与C#对接,故不使用变长字段
  162. }
  163. AddStruct("ERRORRET", false, false, (BYTE*)buf, nDataLen, 1);
  164. }
  165. bool CCommPackage::GetErrMsg(DWORD& dwSysCode, DWORD& dwUserCode, string& rErrMsg)
  166. {
  167. std::vector<CStructDef *>::iterator it;
  168. for(it = m_Structs.begin(); it != m_Structs.end(); it++)
  169. {
  170. if (memcmp((*it)->m_arrName, "ERRORRET", 8) ==0)
  171. break;
  172. }
  173. if (it == m_Structs.end())
  174. return false;
  175. assert((*it)->m_cEncCode == 'N');
  176. assert((*it)->m_cZipCode == 'N');
  177. CErrorReturn *pErrRet = (CErrorReturn*)(*it)->m_pData;
  178. dwSysCode = pErrRet->m_dwSysCode;
  179. dwUserCode = pErrRet->m_dwUserCode;
  180. int nErrMsgLen = (*it)->m_nSourceLen - 8;
  181. char buf[512];
  182. memset(buf, 0, sizeof(buf));
  183. memcpy(buf, pErrRet->m_arrErrMsg, nErrMsgLen);
  184. rErrMsg = buf;
  185. return true;
  186. }
  187. string CCommPackage::GetServiceCode()
  188. {
  189. if (m_Header.m_arrServiceCode[7] == 0)
  190. return m_Header.m_arrServiceCode;
  191. else
  192. {
  193. char buf[9];
  194. memset(buf, 0, sizeof(buf));
  195. memcpy(buf, m_Header.m_arrServiceCode, 8);
  196. return buf;
  197. }
  198. }
  199. int CCommPackage::GetStructLen(const char *pStructName)
  200. {
  201. int nCompLen = strlen(pStructName);
  202. if (nCompLen >8 )
  203. nCompLen = 8;
  204. std::vector<CStructDef *>::iterator it;
  205. for(it = m_Structs.begin(); it != m_Structs.end(); it++)
  206. {
  207. if (memcmp((*it)->m_arrName, pStructName, nCompLen) ==0)
  208. break;
  209. }
  210. if (it == m_Structs.end())
  211. return -1;
  212. return (*it)->m_nSourceLen;
  213. }
  214. bool CCommPackage::GetStructData(const char *pStructName, BYTE *pDataBuf, int *pBufLen, int *pArrayNum)
  215. {
  216. int nCompLen = strlen(pStructName);
  217. if (nCompLen >8 )
  218. nCompLen = 8;
  219. std::vector<CStructDef *>::iterator it;
  220. for(it = m_Structs.begin(); it != m_Structs.end(); it++)
  221. {
  222. if (memcmp((*it)->m_arrName, pStructName, nCompLen) ==0)
  223. break;
  224. }
  225. if (it == m_Structs.end())
  226. return false;
  227. *pArrayNum = (*it)->m_nArrayNum;
  228. int nCopyLen = (*it)->m_nSourceLen;
  229. if (nCopyLen > *pBufLen)
  230. nCopyLen = *pBufLen;
  231. *pBufLen = nCopyLen;
  232. memcpy(pDataBuf, (*it)->m_pData, nCopyLen);
  233. return true;
  234. }
  235. bool CCommPackage::ParseRecvData(BYTE *pData, int *pLen, string& strErrMsg)
  236. {
  237. if (*pLen < sizeof(CPackageHeader))
  238. {
  239. strErrMsg = "pack len < sizeof(CPackageHeader)";
  240. return false;
  241. }
  242. CPackageHeader *pHeader = (CPackageHeader *)pData;
  243. // 校验标志位
  244. if (pHeader->m_nFlag != 0xA5C3)
  245. {
  246. strErrMsg = "Header->m_nFlag != 0xA5C3";
  247. return false;
  248. }
  249. // 检查版本
  250. if (pHeader->m_nVersion != 1)
  251. {
  252. strErrMsg = "Header->m_nVersion != 1";
  253. return false;
  254. }
  255. // 检查Mac
  256. BYTE pkgMac[8];
  257. memcpy(pkgMac, pHeader->m_arrMac, 8);
  258. // 清空Mac,方便检验
  259. memset(pHeader->m_arrMac, 0, 8);
  260. BYTE genMac[8];
  261. if (GenerateMac(pData, *pLen, genMac))
  262. {
  263. // 比较两个Mac
  264. if (memcmp(pkgMac, genMac, 8) != 0)
  265. {
  266. strErrMsg = "mac check not pass";
  267. return false;
  268. }
  269. }
  270. // 保存包头信息
  271. memcpy(&m_Header, pHeader, sizeof(CPackageHeader));
  272. int nStructDefLen = CStructDef::GetStructDefLen();
  273. // 处理接口定义
  274. CStructDef *pIDef = (CStructDef *) (pData + sizeof(CPackageHeader));
  275. BYTE *pIData = pData + sizeof(CPackageHeader) + m_Header.m_nStructNum * nStructDefLen;
  276. bool bParseSuc = true;
  277. for(int i=0; i<m_Header.m_nStructNum; i++)
  278. {
  279. // 拷贝接口定义
  280. CStructDef *pDef = new CStructDef();
  281. memcpy(pDef, pIDef, nStructDefLen);
  282. // 拷贝接口数据
  283. int nBufLen = pDef->m_nTargetLen > pDef->m_nSourceLen ? pDef->m_nTargetLen : pDef->m_nSourceLen;
  284. pDef->m_pData = new BYTE[nBufLen];
  285. memset(pDef->m_pData, 0, nBufLen);
  286. memcpy(pDef->m_pData, pIData, pDef->m_nTargetLen);
  287. // 改变指针位置
  288. pIDef = (CStructDef *)(((BYTE *) pIDef) + nStructDefLen);
  289. pIData += pDef->m_nTargetLen;
  290. int nLastLength = pDef->m_nTargetLen;
  291. // 先解密
  292. if (pDef->m_cEncCode == 'Y')
  293. {
  294. assert(m_bHasSessionKey);
  295. // 解密后长度最大长度为源长度+12
  296. int nTempBufLen = pDef->m_nSourceLen + 12;
  297. BYTE *pTempBuf = new BYTE[nTempBufLen];
  298. memset(pTempBuf, 0, nTempBufLen);
  299. if (DecryptData(pDef->m_pData, pDef->m_nTargetLen, pTempBuf, &nTempBufLen))
  300. {
  301. assert(nTempBufLen <= pDef->m_nSourceLen);
  302. delete[] pDef->m_pData;
  303. pDef->m_pData = pTempBuf;
  304. nLastLength = nTempBufLen; // 解密后实际长度
  305. }
  306. else
  307. {
  308. strErrMsg = "decrypt data fail";
  309. delete[] pTempBuf;
  310. bParseSuc = false;
  311. }
  312. }
  313. // 解压
  314. if (bParseSuc && pDef->m_cZipCode == 'Y')
  315. {
  316. // 解压后最大长度不超过源长度
  317. int nTempBufLen = pDef->m_nSourceLen;
  318. BYTE *pTempBuf = new BYTE[nTempBufLen];
  319. memset(pTempBuf, 0, nTempBufLen);
  320. if (UnzipData(pDef->m_pData, nLastLength, pTempBuf, &nTempBufLen))
  321. {
  322. delete[] pDef->m_pData;
  323. pDef->m_pData = pTempBuf;
  324. nLastLength = nTempBufLen;
  325. }
  326. else
  327. {
  328. strErrMsg = "unzip data fail";
  329. delete[] pTempBuf;
  330. bParseSuc = false;
  331. }
  332. }
  333. // 保存接口
  334. m_Structs.push_back(pDef);
  335. if (nLastLength != pDef->m_nSourceLen)
  336. {
  337. memset(pDef->m_pData, 0, pDef->m_nSourceLen);
  338. strErrMsg = "parsed length != m_nSourceLen";
  339. bParseSuc = false;
  340. }
  341. }
  342. *pLen = m_Header.m_nPackageLen;
  343. return bParseSuc;
  344. }
  345. int CCommPackage::GetPackageLen()
  346. {
  347. return m_Header.m_nPackageLen;
  348. }
  349. string CCommPackage::GetPackageReqID()
  350. {
  351. char szBuf[128];
  352. memset(szBuf, 0, sizeof(szBuf));
  353. sprintf(szBuf, "%d:%d", m_Header.m_nReqTime, m_Header.m_nSN);
  354. return szBuf;
  355. }
  356. bool CCommPackage::GenerateSendData(BYTE *pData, int *pLen)
  357. {
  358. if (*pLen < m_Header.m_nPackageLen)
  359. return false;
  360. *pLen = m_Header.m_nPackageLen;
  361. // 生成发送时间
  362. if (m_Header.m_nReqTime ==0)
  363. {
  364. m_Header.m_nReqTime = time(NULL);
  365. // 生成序号
  366. if (m_Header.m_nReqTime == m_nLastReqTime)
  367. m_Header.m_nSN = ++m_nLastReqSN;
  368. else
  369. m_Header.m_nSN = m_nLastReqSN = 0;
  370. m_nLastReqTime = m_Header.m_nReqTime;
  371. }
  372. else
  373. {
  374. m_Header.m_nAnsTime = time(NULL);
  375. }
  376. // 拷贝包头
  377. BYTE *pHead = pData;
  378. memcpy(pHead, &m_Header, sizeof(CPackageHeader));
  379. // 拷贝接口
  380. pData += sizeof(CPackageHeader);
  381. BYTE *pIntData = pData + m_Header.m_nStructNum * CStructDef::GetStructDefLen();
  382. std::vector<CStructDef *>::iterator it;
  383. for(it = m_Structs.begin(); it != m_Structs.end(); it++)
  384. {
  385. CStructDef *pIntDef = (*it);
  386. memcpy(pData, pIntDef, CStructDef::GetStructDefLen());
  387. memcpy(pIntData, pIntDef->m_pData, pIntDef->m_nTargetLen);
  388. pData += CStructDef::GetStructDefLen();
  389. pIntData += pIntDef->m_nTargetLen;
  390. }
  391. // 生成Mac
  392. BYTE mac[8];
  393. memset(mac, 0, sizeof(mac));
  394. // 先将相应Mac位清0
  395. memset(((CPackageHeader *)pHead)->m_arrMac, 0, 8);
  396. if (! GenerateMac(pHead,*pLen, mac))
  397. return false;
  398. memcpy(((CPackageHeader *)pHead)->m_arrMac, mac, 8);
  399. return true;
  400. }
  401. bool CCommPackage::ZipData(BYTE *pSourceData, int nSourceLen, BYTE *pDestBuf, int *pDestLen)
  402. {
  403. #ifdef _WIN32
  404. HZIP hz = CreateZip(0, nSourceLen, ZIP_MEMORY);
  405. if (hz == 0)
  406. return false;
  407. if (ZipAdd(hz, "ZIPDATA", pSourceData, nSourceLen, ZIP_MEMORY) != ZR_OK)
  408. {
  409. CloseZip(hz);
  410. return false;
  411. }
  412. void* pZipBuf = NULL;
  413. DWORD nZipLen = 0;
  414. if (ZipGetMemory(hz, &pZipBuf, &nZipLen) != ZR_OK)
  415. {
  416. CloseZip(hz);
  417. return false;
  418. }
  419. // 如果压缩长度变大,放弃压缩
  420. if (nZipLen >= nSourceLen)
  421. {
  422. CloseZip(hz);
  423. return false;
  424. }
  425. // 拷贝压缩后内容
  426. int nCopyLen = nZipLen <= *pDestLen ? nZipLen : *pDestLen;
  427. *pDestLen = nCopyLen;
  428. memcpy(pDestBuf, pZipBuf, nCopyLen);
  429. CloseZip(hz);
  430. return true;
  431. #else
  432. return true;
  433. #endif // WIN32
  434. }
  435. bool CCommPackage::UnzipData(BYTE *pSourceData, int nSourceLen, BYTE *pDestBuf, int *pDestLen)
  436. {
  437. #ifdef _WIN32
  438. HZIP hz = OpenZip(pSourceData, nSourceLen, ZIP_MEMORY);
  439. if (hz == 0)
  440. return false;
  441. ZIPENTRY ze;
  442. memset(&ze, 0, sizeof(ze));
  443. if (GetZipItem(hz, 0, &ze) != ZR_OK)
  444. {
  445. CloseZip(hz);
  446. return false;
  447. }
  448. memset(pDestBuf, 0, *pDestLen);
  449. if (ze.unc_size < *pDestLen)
  450. *pDestLen = ze.unc_size;
  451. if (UnzipItem(hz, 0, pDestBuf, *pDestLen, ZIP_MEMORY) != ZR_MORE || *pDestLen != ze.unc_size)
  452. {
  453. CloseZip(hz);
  454. return false;
  455. }
  456. CloseZip(hz);
  457. return true;
  458. #else
  459. return true;
  460. #endif
  461. }
  462. bool CCommPackage::EncryptData(BYTE *pSourceData, int nSourceLen, BYTE *pDestBuf, int *pDestLen)
  463. {
  464. assert(m_bHasSessionKey);
  465. if (!m_bHasSessionKey)
  466. return false;
  467. int nMinBufLen = nSourceLen % 8 == 0 ? nSourceLen : (nSourceLen /8 +1) *8;
  468. nMinBufLen += 4; // 4字节头指定加密前长度
  469. if (nMinBufLen > *pDestLen)
  470. return false;
  471. *pDestLen = nMinBufLen;
  472. *(int*)pDestBuf = nSourceLen; // 保存加密前长度
  473. BYTE iv[8];
  474. memcpy(iv, m_SessionKey+8, 8);
  475. DES_ncbc_encrypt(pSourceData, pDestBuf+4, nSourceLen, &m_DesKey, &iv, DES_ENCRYPT);
  476. return true;
  477. }
  478. bool CCommPackage::DecryptData(BYTE *pSourceData, int nSourceLen, BYTE *pDestBuf, int *pDestLen)
  479. {
  480. assert(m_bHasSessionKey);
  481. if (!m_bHasSessionKey)
  482. return false;
  483. // 取出解密后长度
  484. int nActLen = *(int*)pSourceData;
  485. if (nActLen > *pDestLen)
  486. return false;
  487. nSourceLen -= 4;
  488. int nMinBufLen = nSourceLen % 8 == 0 ? nSourceLen : (nSourceLen /8 +1) *8;
  489. if (nMinBufLen > *pDestLen)
  490. return false;
  491. *pDestLen = nActLen;
  492. BYTE iv[8];
  493. memcpy(iv, m_SessionKey+8, 8);
  494. DES_ncbc_encrypt(pSourceData+4, pDestBuf, nSourceLen, &m_DesKey, &iv, DES_DECRYPT);
  495. return true;
  496. }
  497. // Mac算法约定。为了减低校验码运算复杂度,使用整包进行Hash运算然后取低8位再进行加密运算的方式。
  498. // 如果当前没有协商传输密钥,直接使用Hash低8位表示
  499. bool CCommPackage::GenerateMac(BYTE *pData, int nLen, BYTE mac[8])
  500. {
  501. BYTE md5[16];
  502. memset(md5, 0, 16);
  503. MD5Hash(pData, nLen, md5);
  504. // 加密前8位
  505. BYTE buf[16];
  506. memset(buf, 0, sizeof(buf));
  507. int nBufLen = 16;
  508. if (m_bHasSessionKey)
  509. {
  510. EncryptData(md5, 8, buf, &nBufLen);
  511. memcpy(mac, buf+4, 8);
  512. return true;
  513. }
  514. else
  515. {
  516. memcpy(mac, md5, 8);
  517. return true;
  518. }
  519. }