tc_tea.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. #include "util/tc_tea.h"
  2. #include <iostream>
  3. #include <sstream>
  4. #include <stdlib.h>
  5. #if TARGET_PLATFORM_LINUX
  6. #include <arpa/inet.h>
  7. #endif
  8. #if TARGET_PLATFORM_WINDOWS
  9. #pragma comment(lib,"ws2_32.lib")
  10. #endif
  11. namespace tars
  12. {
  13. #ifndef WORD32
  14. typedef unsigned int WORD32;
  15. #endif
  16. int oi_symmetry_encrypt2_len(int nInBufLen);
  17. void oi_symmetry_encrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen);
  18. bool oi_symmetry_decrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen);
  19. void TC_Tea::encrypt(const char *key, const char *sIn, size_t iLength, vector<char> &buffer)
  20. {
  21. size_t outlen = oi_symmetry_encrypt2_len(iLength);
  22. if (buffer.capacity() < outlen * 2)
  23. {
  24. buffer.resize(outlen * 2);
  25. }
  26. oi_symmetry_encrypt2(sIn, iLength, key, buffer.data(), &outlen);
  27. buffer.resize(outlen);
  28. }
  29. bool TC_Tea::decrypt(const char *key, const char *sIn, size_t iLength, vector<char> &buffer)
  30. {
  31. size_t outlen = iLength;
  32. if (buffer.capacity() < outlen * 2)
  33. {
  34. buffer.resize(outlen * 2);
  35. }
  36. buffer.resize(outlen * 2);
  37. if (!oi_symmetry_decrypt2(sIn, iLength, key, buffer.data(), &outlen))
  38. {
  39. return false;
  40. }
  41. buffer.resize(outlen);
  42. return true;
  43. }
  44. //////////////////////////////////////////////////////////////////////////////////////////
  45. ///
  46. const WORD32 DELTA = 0x9e3779b9;
  47. #define ROUNDS 16
  48. #define LOG_ROUNDS 4
  49. #define SALT_LEN 2
  50. #define ZERO_LEN 7
  51. /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
  52. void TeaEncryptECB(const char *pInBuf, const char *pKey, char *pOutBuf)
  53. {
  54. WORD32 y, z;
  55. WORD32 sum;
  56. WORD32 k[4];
  57. int i;
  58. /*plain-text is TCP/IP-endian;*/
  59. /*GetBlockBigEndian(in, y, z);*/
  60. y = ntohl(*((WORD32 *)pInBuf));
  61. z = ntohl(*((WORD32 *)(pInBuf + 4)));
  62. /*TCP/IP network byte order (which is big-endian).*/
  63. for (i = 0; i < 4; i++)
  64. {
  65. /*now key is TCP/IP-endian;*/
  66. k[i] = ntohl(*((WORD32 *)(pKey + i * 4)));
  67. }
  68. sum = 0;
  69. for (i = 0; i < ROUNDS; i++)
  70. {
  71. sum += DELTA;
  72. y += ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
  73. z += ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
  74. }
  75. *((WORD32 *)pOutBuf) = htonl(y);
  76. *((WORD32 *)(pOutBuf + 4)) = htonl(z);
  77. /*now encrypted buf is TCP/IP-endian;*/
  78. }
  79. /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
  80. void TeaDecryptECB(const char *pInBuf, const char *pKey, char *pOutBuf)
  81. {
  82. WORD32 y, z, sum;
  83. WORD32 k[4];
  84. int i;
  85. /*now encrypted buf is TCP/IP-endian;*/
  86. /*TCP/IP network byte order (which is big-endian).*/
  87. y = ntohl(*((WORD32 *)pInBuf));
  88. z = ntohl(*((WORD32 *)(pInBuf + 4)));
  89. for (i = 0; i < 4; i++)
  90. {
  91. /*key is TCP/IP-endian;*/
  92. k[i] = ntohl(*((WORD32 *)(pKey + i * 4)));
  93. }
  94. sum = DELTA << LOG_ROUNDS;
  95. for (i = 0; i < ROUNDS; i++)
  96. {
  97. z -= ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
  98. y -= ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
  99. sum -= DELTA;
  100. }
  101. *((WORD32 *)pOutBuf) = htonl(y);
  102. *((WORD32 *)(pOutBuf + 4)) = htonl(z);
  103. /*now plain-text is TCP/IP-endian;*/
  104. }
  105. /*pKey为16byte*/
  106. /*
  107. 输入:nInBufLen为需加密的明文部分(Body)长度;
  108. 输出:返回为加密后的长度(是8byte的倍数);
  109. */
  110. /*TEA加密算法,CBC模式*/
  111. /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
  112. int oi_symmetry_encrypt2_len(int nInBufLen)
  113. {
  114. int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zero的长度*/;
  115. int nPadlen;
  116. /*根据Body长度计算PadLen,最小必需长度必需为8byte的整数倍*/
  117. nPadSaltBodyZeroLen = nInBufLen/*Body长度*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/;
  118. if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/
  119. {
  120. /*模8余0需补0,余1补7,余2补6,...,余7补1*/
  121. nPadlen = 8 - nPadlen;
  122. }
  123. return nPadSaltBodyZeroLen + nPadlen;
  124. }
  125. /*pKey为16byte*/
  126. /*
  127. 输入:pInBuf为需加密的明文部分(Body),nInBufLen为pInBuf长度;
  128. 输出:pOutBuf为密文格式,pOutBufLen为pOutBuf的长度是8byte的倍数;
  129. */
  130. /*TEA加密算法,CBC模式*/
  131. /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
  132. void oi_symmetry_encrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen)
  133. {
  134. int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zero的长度*/;
  135. int nPadlen;
  136. char src_buf[8], iv_plain[8], *iv_crypt;
  137. int src_i, i, j;
  138. /*根据Body长度计算PadLen,最小必需长度必需为8byte的整数倍*/
  139. nPadSaltBodyZeroLen = nInBufLen/*Body长度*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/;
  140. if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/
  141. {
  142. /*模8余0需补0,余1补7,余2补6,...,余7补1*/
  143. nPadlen = 8 - nPadlen;
  144. }
  145. /*srand( (unsigned)time( NULL ) ); 初始化随机数*/
  146. /*加密第一块数据(8byte),取前面10byte*/
  147. src_buf[0] = (((char)rand()) & 0x0f8)/*最低三位存PadLen,清零*/ | (char)nPadlen;
  148. src_i = 1; /*src_i指向src_buf下一个位置*/
  149. while (nPadlen--) src_buf[src_i++] = (char)rand(); /*Padding*/
  150. /*come here, src_i must <= 8*/
  151. for (i = 0; i < 8; i++) iv_plain[i] = 0;
  152. iv_crypt = iv_plain; /*make zero iv*/
  153. *pOutBufLen = 0; /*init OutBufLen*/
  154. for (i = 1; i <= SALT_LEN;) /*Salt(2byte)*/
  155. {
  156. if (src_i < 8)
  157. {
  158. src_buf[src_i++] = (char)rand();
  159. i++; /*i inc in here*/
  160. }
  161. if (src_i == 8)
  162. {
  163. /*src_i==8*/
  164. for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
  165. src_buf[j] ^= iv_crypt[j];
  166. /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
  167. /*加密*/
  168. TeaEncryptECB(src_buf, pKey, pOutBuf);
  169. for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
  170. pOutBuf[j] ^= iv_plain[j];
  171. /*保存当前的iv_plain*/
  172. for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
  173. /*更新iv_crypt*/
  174. src_i = 0;
  175. iv_crypt = pOutBuf;
  176. *pOutBufLen += 8;
  177. pOutBuf += 8;
  178. }
  179. }
  180. /*src_i指向src_buf下一个位置*/
  181. while (nInBufLen)
  182. {
  183. if (src_i < 8)
  184. {
  185. src_buf[src_i++] = *(pInBuf++);
  186. nInBufLen--;
  187. }
  188. if (src_i == 8)
  189. {
  190. /*src_i==8*/
  191. for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
  192. src_buf[j] ^= iv_crypt[j];
  193. /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
  194. TeaEncryptECB(src_buf, pKey, pOutBuf);
  195. for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
  196. pOutBuf[j] ^= iv_plain[j];
  197. /*保存当前的iv_plain*/
  198. for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
  199. src_i = 0;
  200. iv_crypt = pOutBuf;
  201. *pOutBufLen += 8;
  202. pOutBuf += 8;
  203. }
  204. }
  205. /*src_i指向src_buf下一个位置*/
  206. for (i = 1; i <= ZERO_LEN;)
  207. {
  208. if (src_i < 8)
  209. {
  210. src_buf[src_i++] = 0;
  211. i++; /*i inc in here*/
  212. }
  213. if (src_i == 8)
  214. {
  215. /*src_i==8*/
  216. for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
  217. src_buf[j] ^= iv_crypt[j];
  218. /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
  219. TeaEncryptECB(src_buf, pKey, pOutBuf);
  220. for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
  221. pOutBuf[j] ^= iv_plain[j];
  222. /*保存当前的iv_plain*/
  223. for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
  224. src_i = 0;
  225. iv_crypt = pOutBuf;
  226. *pOutBufLen += 8;
  227. pOutBuf += 8;
  228. }
  229. }
  230. }
  231. /*pKey为16byte*/
  232. /*
  233. 输入:pInBuf为密文格式,nInBufLen为pInBuf的长度是8byte的倍数; *pOutBufLen为接收缓冲区的长度
  234. 特别注意*pOutBufLen应预置接收缓冲区的长度!
  235. 输出:pOutBuf为明文(Body),pOutBufLen为pOutBuf的长度,至少应预留nInBufLen-10;
  236. 返回值:如果格式正确返回true;
  237. */
  238. /*TEA解密算法,CBC模式*/
  239. /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
  240. bool oi_symmetry_decrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen)
  241. {
  242. int nPadLen, nPlainLen;
  243. char dest_buf[8], zero_buf[8];
  244. const char *iv_pre_crypt, *iv_cur_crypt;
  245. int dest_i, i, j;
  246. // const char *pInBufBoundary;
  247. int nBufPos;
  248. nBufPos = 0;
  249. if ((nInBufLen % 8) || (nInBufLen < 16)) return false;
  250. TeaDecryptECB(pInBuf, pKey, dest_buf);
  251. nPadLen = dest_buf[0] & 0x7/*只要最低三位*/;
  252. /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
  253. i = nInBufLen - 1/*PadLen(1byte)*/ - nPadLen - SALT_LEN - ZERO_LEN; /*明文长度*/
  254. if ((*pOutBufLen < (size_t)i) || (i < 0)) return false;
  255. *pOutBufLen = i;
  256. // pInBufBoundary = pInBuf + nInBufLen; /*输入缓冲区的边界,下面不能pInBuf>=pInBufBoundary*/
  257. for (i = 0; i < 8; i++) zero_buf[i] = 0;
  258. iv_pre_crypt = zero_buf;
  259. iv_cur_crypt = pInBuf; /*init iv*/
  260. pInBuf += 8;
  261. nBufPos += 8;
  262. dest_i = 1; /*dest_i指向dest_buf下一个位置*/
  263. /*把Padding滤掉*/
  264. dest_i += nPadLen;
  265. /*dest_i must <=8*/
  266. /*把Salt滤掉*/
  267. for (i = 1; i <= SALT_LEN;)
  268. {
  269. if (dest_i < 8)
  270. {
  271. dest_i++;
  272. i++;
  273. }
  274. else if (dest_i == 8)
  275. {
  276. /*解开一个新的加密块*/
  277. /*改变前一个加密块的指针*/
  278. iv_pre_crypt = iv_cur_crypt;
  279. iv_cur_crypt = pInBuf;
  280. /*异或前一块明文(在dest_buf[]中)*/
  281. for (j = 0; j < 8; j++)
  282. {
  283. if ((nBufPos + j) >= nInBufLen) return false;
  284. dest_buf[j] ^= pInBuf[j];
  285. }
  286. /*dest_i==8*/
  287. TeaDecryptECB(dest_buf, pKey, dest_buf);
  288. /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
  289. pInBuf += 8;
  290. nBufPos += 8;
  291. dest_i = 0; /*dest_i指向dest_buf下一个位置*/
  292. }
  293. }
  294. /*还原明文*/
  295. nPlainLen = *pOutBufLen;
  296. while (nPlainLen)
  297. {
  298. if (dest_i < 8)
  299. {
  300. *(pOutBuf++) = dest_buf[dest_i] ^ iv_pre_crypt[dest_i];
  301. dest_i++;
  302. nPlainLen--;
  303. }
  304. else if (dest_i == 8)
  305. {
  306. /*dest_i==8*/
  307. /*改变前一个加密块的指针*/
  308. iv_pre_crypt = iv_cur_crypt;
  309. iv_cur_crypt = pInBuf;
  310. /*解开一个新的加密块*/
  311. /*异或前一块明文(在dest_buf[]中)*/
  312. for (j = 0; j < 8; j++)
  313. {
  314. if ((nBufPos + j) >= nInBufLen) return false;
  315. dest_buf[j] ^= pInBuf[j];
  316. }
  317. TeaDecryptECB(dest_buf, pKey, dest_buf);
  318. /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
  319. pInBuf += 8;
  320. nBufPos += 8;
  321. dest_i = 0; /*dest_i指向dest_buf下一个位置*/
  322. }
  323. }
  324. /*校验Zero*/
  325. for (i = 1; i <= ZERO_LEN;)
  326. {
  327. if (dest_i < 8)
  328. {
  329. if (dest_buf[dest_i] ^ iv_pre_crypt[dest_i]) return false;
  330. dest_i++;
  331. i++;
  332. }
  333. else if (dest_i == 8)
  334. {
  335. /*改变前一个加密块的指针*/
  336. iv_pre_crypt = iv_cur_crypt;
  337. iv_cur_crypt = pInBuf;
  338. /*解开一个新的加密块*/
  339. /*异或前一块明文(在dest_buf[]中)*/
  340. for (j = 0; j < 8; j++)
  341. {
  342. if ((nBufPos + j) >= nInBufLen) return false;
  343. dest_buf[j] ^= pInBuf[j];
  344. }
  345. TeaDecryptECB(dest_buf, pKey, dest_buf);
  346. /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
  347. pInBuf += 8;
  348. nBufPos += 8;
  349. dest_i = 0; /*dest_i指向dest_buf下一个位置*/
  350. }
  351. }
  352. return true;
  353. }
  354. }