123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- #include "util/tc_tea.h"
- #include <iostream>
- #include <sstream>
- #include <stdlib.h>
- #if TARGET_PLATFORM_LINUX
- #include <arpa/inet.h>
- #endif
- #if TARGET_PLATFORM_WINDOWS
- #pragma comment(lib,"ws2_32.lib")
- #endif
- namespace tars
- {
- #ifndef WORD32
- typedef unsigned int WORD32;
- #endif
- int oi_symmetry_encrypt2_len(int nInBufLen);
- void oi_symmetry_encrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen);
- bool oi_symmetry_decrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen);
- void TC_Tea::encrypt(const char *key, const char *sIn, size_t iLength, vector<char> &buffer)
- {
- size_t outlen = oi_symmetry_encrypt2_len(iLength);
- if (buffer.capacity() < outlen * 2)
- {
- buffer.resize(outlen * 2);
- }
- oi_symmetry_encrypt2(sIn, iLength, key, buffer.data(), &outlen);
- buffer.resize(outlen);
- }
- bool TC_Tea::decrypt(const char *key, const char *sIn, size_t iLength, vector<char> &buffer)
- {
- size_t outlen = iLength;
- if (buffer.capacity() < outlen * 2)
- {
- buffer.resize(outlen * 2);
- }
- buffer.resize(outlen * 2);
- if (!oi_symmetry_decrypt2(sIn, iLength, key, buffer.data(), &outlen))
- {
- return false;
- }
- buffer.resize(outlen);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- ///
- const WORD32 DELTA = 0x9e3779b9;
- #define ROUNDS 16
- #define LOG_ROUNDS 4
- #define SALT_LEN 2
- #define ZERO_LEN 7
- /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
- void TeaEncryptECB(const char *pInBuf, const char *pKey, char *pOutBuf)
- {
- WORD32 y, z;
- WORD32 sum;
- WORD32 k[4];
- int i;
- /*plain-text is TCP/IP-endian;*/
- /*GetBlockBigEndian(in, y, z);*/
- y = ntohl(*((WORD32 *)pInBuf));
- z = ntohl(*((WORD32 *)(pInBuf + 4)));
- /*TCP/IP network byte order (which is big-endian).*/
- for (i = 0; i < 4; i++)
- {
- /*now key is TCP/IP-endian;*/
- k[i] = ntohl(*((WORD32 *)(pKey + i * 4)));
- }
- sum = 0;
- for (i = 0; i < ROUNDS; i++)
- {
- sum += DELTA;
- y += ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
- z += ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
- }
- *((WORD32 *)pOutBuf) = htonl(y);
- *((WORD32 *)(pOutBuf + 4)) = htonl(z);
- /*now encrypted buf is TCP/IP-endian;*/
- }
- /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
- void TeaDecryptECB(const char *pInBuf, const char *pKey, char *pOutBuf)
- {
- WORD32 y, z, sum;
- WORD32 k[4];
- int i;
- /*now encrypted buf is TCP/IP-endian;*/
- /*TCP/IP network byte order (which is big-endian).*/
- y = ntohl(*((WORD32 *)pInBuf));
- z = ntohl(*((WORD32 *)(pInBuf + 4)));
- for (i = 0; i < 4; i++)
- {
- /*key is TCP/IP-endian;*/
- k[i] = ntohl(*((WORD32 *)(pKey + i * 4)));
- }
- sum = DELTA << LOG_ROUNDS;
- for (i = 0; i < ROUNDS; i++)
- {
- z -= ((y << 4) + k[2]) ^ (y + sum) ^ ((y >> 5) + k[3]);
- y -= ((z << 4) + k[0]) ^ (z + sum) ^ ((z >> 5) + k[1]);
- sum -= DELTA;
- }
- *((WORD32 *)pOutBuf) = htonl(y);
- *((WORD32 *)(pOutBuf + 4)) = htonl(z);
- /*now plain-text is TCP/IP-endian;*/
- }
- /*pKey为16byte*/
- /*
- 输入:nInBufLen为需加密的明文部分(Body)长度;
- 输出:返回为加密后的长度(是8byte的倍数);
- */
- /*TEA加密算法,CBC模式*/
- /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
- int oi_symmetry_encrypt2_len(int nInBufLen)
- {
- int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zero的长度*/;
- int nPadlen;
- /*根据Body长度计算PadLen,最小必需长度必需为8byte的整数倍*/
- nPadSaltBodyZeroLen = nInBufLen/*Body长度*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/;
- if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/
- {
- /*模8余0需补0,余1补7,余2补6,...,余7补1*/
- nPadlen = 8 - nPadlen;
- }
- return nPadSaltBodyZeroLen + nPadlen;
- }
- /*pKey为16byte*/
- /*
- 输入:pInBuf为需加密的明文部分(Body),nInBufLen为pInBuf长度;
- 输出:pOutBuf为密文格式,pOutBufLen为pOutBuf的长度是8byte的倍数;
- */
- /*TEA加密算法,CBC模式*/
- /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
- void oi_symmetry_encrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen)
- {
- int nPadSaltBodyZeroLen/*PadLen(1byte)+Salt+Body+Zero的长度*/;
- int nPadlen;
- char src_buf[8], iv_plain[8], *iv_crypt;
- int src_i, i, j;
- /*根据Body长度计算PadLen,最小必需长度必需为8byte的整数倍*/
- nPadSaltBodyZeroLen = nInBufLen/*Body长度*/ + 1 + SALT_LEN + ZERO_LEN/*PadLen(1byte)+Salt(2byte)+Zero(7byte)*/;
- if ((nPadlen = nPadSaltBodyZeroLen % 8)) /*len=nSaltBodyZeroLen%8*/
- {
- /*模8余0需补0,余1补7,余2补6,...,余7补1*/
- nPadlen = 8 - nPadlen;
- }
- /*srand( (unsigned)time( NULL ) ); 初始化随机数*/
- /*加密第一块数据(8byte),取前面10byte*/
- src_buf[0] = (((char)rand()) & 0x0f8)/*最低三位存PadLen,清零*/ | (char)nPadlen;
- src_i = 1; /*src_i指向src_buf下一个位置*/
- while (nPadlen--) src_buf[src_i++] = (char)rand(); /*Padding*/
- /*come here, src_i must <= 8*/
- for (i = 0; i < 8; i++) iv_plain[i] = 0;
- iv_crypt = iv_plain; /*make zero iv*/
- *pOutBufLen = 0; /*init OutBufLen*/
- for (i = 1; i <= SALT_LEN;) /*Salt(2byte)*/
- {
- if (src_i < 8)
- {
- src_buf[src_i++] = (char)rand();
- i++; /*i inc in here*/
- }
- if (src_i == 8)
- {
- /*src_i==8*/
- for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
- src_buf[j] ^= iv_crypt[j];
- /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
- /*加密*/
- TeaEncryptECB(src_buf, pKey, pOutBuf);
- for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
- pOutBuf[j] ^= iv_plain[j];
- /*保存当前的iv_plain*/
- for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
- /*更新iv_crypt*/
- src_i = 0;
- iv_crypt = pOutBuf;
- *pOutBufLen += 8;
- pOutBuf += 8;
- }
- }
- /*src_i指向src_buf下一个位置*/
- while (nInBufLen)
- {
- if (src_i < 8)
- {
- src_buf[src_i++] = *(pInBuf++);
- nInBufLen--;
- }
- if (src_i == 8)
- {
- /*src_i==8*/
- for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
- src_buf[j] ^= iv_crypt[j];
- /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
- TeaEncryptECB(src_buf, pKey, pOutBuf);
- for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
- pOutBuf[j] ^= iv_plain[j];
- /*保存当前的iv_plain*/
- for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
- src_i = 0;
- iv_crypt = pOutBuf;
- *pOutBufLen += 8;
- pOutBuf += 8;
- }
- }
- /*src_i指向src_buf下一个位置*/
- for (i = 1; i <= ZERO_LEN;)
- {
- if (src_i < 8)
- {
- src_buf[src_i++] = 0;
- i++; /*i inc in here*/
- }
- if (src_i == 8)
- {
- /*src_i==8*/
- for (j = 0; j < 8; j++) /*加密前异或前8个byte的密文(iv_crypt指向的)*/
- src_buf[j] ^= iv_crypt[j];
- /*pOutBuffer、pInBuffer均为8byte, pKey为16byte*/
- TeaEncryptECB(src_buf, pKey, pOutBuf);
- for (j = 0; j < 8; j++) /*加密后异或前8个byte的明文(iv_plain指向的)*/
- pOutBuf[j] ^= iv_plain[j];
- /*保存当前的iv_plain*/
- for (j = 0; j < 8; j++) iv_plain[j] = src_buf[j];
- src_i = 0;
- iv_crypt = pOutBuf;
- *pOutBufLen += 8;
- pOutBuf += 8;
- }
- }
- }
- /*pKey为16byte*/
- /*
- 输入:pInBuf为密文格式,nInBufLen为pInBuf的长度是8byte的倍数; *pOutBufLen为接收缓冲区的长度
- 特别注意*pOutBufLen应预置接收缓冲区的长度!
- 输出:pOutBuf为明文(Body),pOutBufLen为pOutBuf的长度,至少应预留nInBufLen-10;
- 返回值:如果格式正确返回true;
- */
- /*TEA解密算法,CBC模式*/
- /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
- bool oi_symmetry_decrypt2(const char *pInBuf, int nInBufLen, const char *pKey, char *pOutBuf, size_t *pOutBufLen)
- {
- int nPadLen, nPlainLen;
- char dest_buf[8], zero_buf[8];
- const char *iv_pre_crypt, *iv_cur_crypt;
- int dest_i, i, j;
- // const char *pInBufBoundary;
- int nBufPos;
- nBufPos = 0;
- if ((nInBufLen % 8) || (nInBufLen < 16)) return false;
- TeaDecryptECB(pInBuf, pKey, dest_buf);
- nPadLen = dest_buf[0] & 0x7/*只要最低三位*/;
- /*密文格式:PadLen(1byte)+Padding(var,0-7byte)+Salt(2byte)+Body(var byte)+Zero(7byte)*/
- i = nInBufLen - 1/*PadLen(1byte)*/ - nPadLen - SALT_LEN - ZERO_LEN; /*明文长度*/
- if ((*pOutBufLen < (size_t)i) || (i < 0)) return false;
- *pOutBufLen = i;
- // pInBufBoundary = pInBuf + nInBufLen; /*输入缓冲区的边界,下面不能pInBuf>=pInBufBoundary*/
- for (i = 0; i < 8; i++) zero_buf[i] = 0;
- iv_pre_crypt = zero_buf;
- iv_cur_crypt = pInBuf; /*init iv*/
- pInBuf += 8;
- nBufPos += 8;
- dest_i = 1; /*dest_i指向dest_buf下一个位置*/
- /*把Padding滤掉*/
- dest_i += nPadLen;
- /*dest_i must <=8*/
- /*把Salt滤掉*/
- for (i = 1; i <= SALT_LEN;)
- {
- if (dest_i < 8)
- {
- dest_i++;
- i++;
- }
- else if (dest_i == 8)
- {
- /*解开一个新的加密块*/
- /*改变前一个加密块的指针*/
- iv_pre_crypt = iv_cur_crypt;
- iv_cur_crypt = pInBuf;
- /*异或前一块明文(在dest_buf[]中)*/
- for (j = 0; j < 8; j++)
- {
- if ((nBufPos + j) >= nInBufLen) return false;
- dest_buf[j] ^= pInBuf[j];
- }
-
- /*dest_i==8*/
- TeaDecryptECB(dest_buf, pKey, dest_buf);
- /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
- pInBuf += 8;
- nBufPos += 8;
- dest_i = 0; /*dest_i指向dest_buf下一个位置*/
- }
- }
- /*还原明文*/
- nPlainLen = *pOutBufLen;
- while (nPlainLen)
- {
- if (dest_i < 8)
- {
- *(pOutBuf++) = dest_buf[dest_i] ^ iv_pre_crypt[dest_i];
- dest_i++;
- nPlainLen--;
- }
- else if (dest_i == 8)
- {
- /*dest_i==8*/
- /*改变前一个加密块的指针*/
- iv_pre_crypt = iv_cur_crypt;
- iv_cur_crypt = pInBuf;
- /*解开一个新的加密块*/
- /*异或前一块明文(在dest_buf[]中)*/
- for (j = 0; j < 8; j++)
- {
- if ((nBufPos + j) >= nInBufLen) return false;
- dest_buf[j] ^= pInBuf[j];
- }
- TeaDecryptECB(dest_buf, pKey, dest_buf);
- /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
- pInBuf += 8;
- nBufPos += 8;
- dest_i = 0; /*dest_i指向dest_buf下一个位置*/
- }
- }
- /*校验Zero*/
- for (i = 1; i <= ZERO_LEN;)
- {
- if (dest_i < 8)
- {
- if (dest_buf[dest_i] ^ iv_pre_crypt[dest_i]) return false;
- dest_i++;
- i++;
- }
- else if (dest_i == 8)
- {
- /*改变前一个加密块的指针*/
- iv_pre_crypt = iv_cur_crypt;
- iv_cur_crypt = pInBuf;
- /*解开一个新的加密块*/
- /*异或前一块明文(在dest_buf[]中)*/
- for (j = 0; j < 8; j++)
- {
- if ((nBufPos + j) >= nInBufLen) return false;
- dest_buf[j] ^= pInBuf[j];
- }
- TeaDecryptECB(dest_buf, pKey, dest_buf);
- /*在取出的时候才异或前一块密文(iv_pre_crypt)*/
- pInBuf += 8;
- nBufPos += 8;
- dest_i = 0; /*dest_i指向dest_buf下一个位置*/
- }
- }
- return true;
- }
- }
|