QQTEA加密解密实现


分类: 加密算法   1295人阅读  评论(0)  收藏  举报

本文从konglinglong的项目wingIM转载而来,使用者必须尊重原作者的著作权,在其授权范围内使用。中文注释为我所加,感谢原作者的辛勤劳动和无私共享精神!

wingIM发布在谷歌代码里,地址为:http://code.google.com/p/wingim/

crypt.h

[cpp]  view plain copy
  1. /** 
  2.  * The QQ2003C protocol plugin 
  3.  * 
  4.  * for gaim 
  5.  * 
  6.  * Copyright © 2004 Puzzlebird 
  7.  * 
  8.  * This program is free software; you can redistribute it and/or modify 
  9.  * it under the terms of the GNU General Public License as published by 
  10.  * the Free Software Foundation; either version 3 of the License, or 
  11.  * (at your option) any later version. 
  12.  * 
  13.  * This program is distributed in the hope that it will be useful, 
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16.  * GNU General Public License for more details. 
  17.  * 
  18.  * You should have received a copy of the GNU General Public License 
  19.  * along with this program; if not, write to the Free Software 
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  21.  * 
  22.  ************************************************** 
  23.  * Reorganized by Minmin , 2005-3-27 
  24.  ************************************************** 
  25.  */  
  26.   
  27. #ifndef Crypt_H  
  28. #define Crypt_H  
  29.   
  30. #define DECRYPT 0x00  
  31. #define ENCRYPT 0x01  
  32.   
  33. #include "Wingdefines.h"  
  34.   
  35. class Crypt  
  36. {  
  37. public:  
  38.     Crypt();  
  39.     ~Crypt();  
  40.   
  41.     static void encrypt( unsigned char* instr, int32 instrlen, unsigned char* key,  
  42.                 unsigned char*  outstr, int32* outstrlen_ptr);  
  43.   
  44.     static int decrypt(unsigned char* instr, int32 instrlen, unsigned char* key,  
  45.                 unsigned char*  outstr, int32* outstrlen_ptr);  
  46.   
  47. private:  
  48.     static int rand(void);  
  49.     static void teaEncipher(unsigned int *const v, const unsigned int *const k,  
  50.                 unsigned int *const w);  
  51.     static void teaDecipher(unsigned int *const v, const unsigned int *const k,  
  52.                 unsigned int *const w);  
  53.   
  54.     static int qq_crypt ( unsigned char   flag,  unsigned char*  instr,  int32  instrlen,  
  55.                 unsigned char*  key, unsigned char*  outstr, int32* outstrlen_ptr);  
  56. };  
  57.   
  58. #endif  


crypt.cpp

[cpp]  view plain copy
  1. /** 
  2.  * The QQ2003C protocol plugin 
  3.  * 
  4.  * for gaim 
  5.  * 
  6.  * Copyright © 2004 Puzzlebird 
  7.  * 
  8.  * This program is free software; you can redistribute it and/or modify 
  9.  * it under the terms of the GNU General Public License as published by 
  10.  * the Free Software Foundation; either version 3 of the License, or 
  11.  * (at your option) any later version. 
  12.  * 
  13.  * This program is distributed in the hope that it will be useful, 
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16.  * GNU General Public License for more details. 
  17.  * 
  18.  * You should have received a copy of the GNU General Public License 
  19.  * along with this program; if not, write to the Free Software 
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  21.  * 
  22.  ************************************************** 
  23.  * Reorganized by Minmin , 2005-3-27 
  24.  ************************************************** 
  25.  */  
  26.   
  27. #include "crypt.h"  
  28.   
  29. #include   
  30. #ifdef _WIN32  
  31. #include   
  32. #else  
  33. #include   
  34. #endif  
  35. #include   
  36.   
  37. Crypt::Crypt()  
  38. {  
  39. }  
  40.   
  41. Crypt::~Crypt()  
  42. {  
  43. }  
  44.   
  45. void Crypt::teaEncipher(unsigned int *const v, const unsigned int *const k,  
  46.             unsigned int *const w)  
  47. {  
  48.     register unsigned int  
  49.         y     = ntohl(v[0]),  
  50.         z     = ntohl(v[1]),  
  51.         a     = ntohl(k[0]),  
  52.         b     = ntohl(k[1]),  
  53.         c     = ntohl(k[2]),  
  54.         d     = ntohl(k[3]),  
  55.         n     = 0x10,       /* do encrypt 16 (0x10) times */  
  56.         sum   = 0,  
  57.         delta = 0x9E3779B9; /*  0x9E3779B9 - 0x100000000 = -0x61C88647 */  
  58.   
  59.     while (n-- > 0) {  
  60.         sum += delta;  
  61.         y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);  
  62.         z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);  
  63.     }  
  64.   
  65.     w[0] = htonl(y); w[1] = htonl(z);  
  66. }  
  67. void Crypt::teaDecipher(unsigned int *const v, const unsigned int *const k,  
  68.             unsigned int *const w)  
  69. {  
  70.     register unsigned int  
  71.         y     = ntohl(v[0]),  
  72.         z     = ntohl(v[1]),  
  73.         a     = ntohl(k[0]),  
  74.         b     = ntohl(k[1]),  
  75.         c     = ntohl(k[2]),  
  76.         d     = ntohl(k[3]),  
  77.         n     = 0x10,  
  78.         sum   = 0xE3779B90,  
  79.         /* why this ? must be related with n value*/  
  80.         delta = 0x9E3779B9;  
  81.   
  82.     /* sum = delta<<5, in general sum = delta * n */  
  83.     while (n-- > 0) {  
  84.         z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);  
  85.         y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);  
  86.         sum -= delta;  
  87.     }  
  88.   
  89.     w[0] = htonl(y); w[1] = htonl(z);  
  90. }  
  91.   
  92. void Crypt::encrypt( unsigned char* instr, int32 instrlen, unsigned char* key,  
  93.             unsigned char*  outstr, int32* outstrlen_ptr)  
  94. {  
  95.     unsigned char  
  96.         plain[8],         /* plain text buffer*/  
  97.         plain_pre_8[8],   /* plain text buffer, previous 8 bytes*/  
  98.         * crypted,        /* crypted text*/  
  99.         * crypted_pre_8,  /* crypted test, previous 8 bytes*/  
  100.         * inp;            /* current position in instr*/  
  101.     int  
  102.         pos_in_byte = 1,  /* loop in the byte */  
  103.         is_header=1,      /* header is one byte*/  
  104.         count=0,          /* number of bytes being crypted*/  
  105.         padding = 0;      /* number of padding stuff*/  
  106.   
  107.     //void encrypt_every_8_byte (void);  
  108.   
  109.       
  110.     /*** we encrypt every eight byte ***/  
  111. #define encrypt_every_8_byte()  \  
  112.     {\  
  113.     for(pos_in_byte=0; pos_in_byte<8; pos_in_byte++) {\  
  114.     if(is_header) { plain[pos_in_byte] ^= plain_pre_8[pos_in_byte]; }\  
  115.             else { plain[pos_in_byte] ^= crypted_pre_8[pos_in_byte]; }\  //待加密单元等于明文与前面已加密的8字节异或(交织算法第一步)  
  116.     } /* prepare plain text*/\  
  117.     teaEncipher( (unsigned int *) plain,\  
  118.     (unsigned int *) key, \  
  119.     (unsigned int *) crypted);   /* encrypt it*/\        //TEA加密  
  120.     \  
  121.     for(pos_in_byte=0; pos_in_byte<8; pos_in_byte++) {\    
  122.     crypted[pos_in_byte] ^= plain_pre_8[pos_in_byte]; \  //密文等于加密后的数据与前一单元待加密的数据异或 (交织算法第二步)  
  123.     } \  
  124.     memcpy(plain_pre_8, plain, 8);     /* prepare next*/\  
  125.     \  
  126.     crypted_pre_8   =   crypted;       /* store position of previous 8 byte*/\  
  127.     crypted         +=  8;             /* prepare next output*/\  
  128.     count           +=  8;             /* outstrlen increase by 8*/\  
  129.     pos_in_byte     =   0;             /* back to start*/\  
  130.     is_header       =   0;             /* and exit header*/\  
  131.     }/* encrypt_every_8_byte*/  
  132.   
  133.       
  134.     pos_in_byte = (instrlen + 0x0a) % 8; /* header padding decided by instrlen*/  
  135.     if (pos_in_byte) {  
  136.         pos_in_byte = 8 - pos_in_byte;  //求出要padding多少字节  
  137.     }  
  138.     plain[0] = (rand() & 0xf8) | pos_in_byte; //头部第一个字节  
  139.   
  140.     memset(plain+1, rand()&0xff, pos_in_byte++); //padding n 个字节  
  141.     memset(plain_pre_8, 0x00, sizeof(plain_pre_8)); //前8个字节清零  
  142.   
  143.     crypted = crypted_pre_8 = outstr;  
  144.   
  145.     padding = 1; /* pad some stuff in header*/    //pad 2 bytes  
  146.     while (padding <= 2) { /* at most two byte */  
  147.         if(pos_in_byte < 8) { plain[pos_in_byte++] = rand() & 0xff; padding ++; }  
  148.         if(pos_in_byte == 8){ encrypt_every_8_byte(); }  
  149.     }  
  150.   
  151.     inp = instr;  
  152.     while (instrlen > 0) {  
  153.         if (pos_in_byte < 8) { plain[pos_in_byte++] = *(inp++); instrlen --; } //复制明文至待加密数据区  
  154.         if (pos_in_byte == 8){ encrypt_every_8_byte(); } //满8个字节则加密  
  155.     }  
  156.   
  157.     padding = 1; /* pad some stuff in tailer*/           //pad 7 bytes 00  
  158.     while (padding <= 7) { /* at most sever byte*/  
  159.         if (pos_in_byte < 8) { plain[pos_in_byte++] = 0x00; padding ++; }  
  160.         if (pos_in_byte == 8){ encrypt_every_8_byte(); }  
  161.     }  
  162.   
  163.     *outstrlen_ptr = count;  
  164.   
  165. }  
  166.   
  167. int Crypt::rand(void)  
  168. {  
  169.     /* it can be the real random seed function*/  
  170.     return 0xdead; /* override with number, convenient for debug*/  
  171. }  
  172.   
  173. int Crypt::decrypt( unsigned char* instr, int32 instrlen, unsigned char* key,  
  174.             unsigned char*  outstr, int32* outstrlen_ptr)  
  175. {  
  176.     unsigned char  
  177.         decrypted[8], m[8],  
  178.         * crypt_buff,  
  179.         * crypt_buff_pre_8,  
  180.         * outp;  
  181.     int  
  182.         count,           //明文数据长度  
  183.         context_start,  //长度临时变量  
  184.         pos_in_byte,  
  185.         padding;  
  186.   
  187. #define decrypt_every_8_byte()  {\    
  188.     bool bNeedRet = false;\  
  189.     for (pos_in_byte = 0; pos_in_byte < 8; pos_in_byte ++ ) {\   
  190.         if (context_start + pos_in_byte >= instrlen) \  
  191.         {\  
  192.             bNeedRet = true;\  
  193.             break;\  
  194.         }\  
  195.         decrypted[pos_in_byte] ^= crypt_buff[pos_in_byte];\ //待解密单元等于前面已解密单元与下一个待解密单元异或  
  196.     }\  
  197.     if( !bNeedRet ) { \  
  198.         teaDecipher( (unsigned int *) decrypted, \  
  199.         (unsigned int *) key, \  
  200.         (unsigned int *) decrypted);\    //解密  
  201.     \  
  202.         context_start +=  8;\  
  203.         crypt_buff    +=  8;\  
  204.         pos_in_byte   =   0;\  
  205.     }\  
  206. }/* decrypt_every_8_byte*/  
  207.   
  208.     /* at least 16 bytes and %8 == 0*/  
  209.     if ((instrlen % 8) || (instrlen < 16)) return 0;  
  210.     /* get information from header*/  
  211.     teaDecipher( (unsigned int *) instr,  
  212.         (unsigned int *) key,  
  213.         (unsigned int *) decrypted);   //解出头部,然后decrypted缓冲区就有初值了  
  214.     pos_in_byte = decrypted[0] & 0x7;  
  215.     count = instrlen - pos_in_byte - 10; /* this is the plaintext length*/  
  216.     /* return if outstr buffer is not large enought or error plaintext length*/  
  217.     if (*outstrlen_ptr < count || count < 0) return 0;  
  218.   
  219.     memset(m, 0, 8);  
  220.     crypt_buff_pre_8 = m;  
  221.     *outstrlen_ptr = count;   /* everything is ok! set return string length*/  
  222.   
  223.     crypt_buff = instr + 8;   /* address of real data start */  
  224.     context_start = 8;        /* context is at the second 8 byte*/  
  225.     pos_in_byte ++;           /* start of paddng stuffv*/  
  226.   
  227.     padding = 1;              /* at least one in header*/  
  228.     while (padding <= 2) {    /* there are 2 byte padding stuff in header*/  
  229.         if (pos_in_byte < 8) {  /* bypass the padding stuff, none sense data*/  
  230.             pos_in_byte ++; padding ++;  
  231.         }  
  232.         if (pos_in_byte == 8) {  
  233.             crypt_buff_pre_8 = instr;  
  234.             //if (! decrypt_every_8_byte()) return 0;  
  235.             decrypt_every_8_byte();  
  236.         }  
  237.     }/* while*/  
  238.   
  239.     outp = outstr;  
  240.     while(count !=0) {  
  241.         if (pos_in_byte < 8) {  
  242.             *outp = crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]; //输出明文等于前一个密文单元数据异或当前解密后单元  
  243.             outp ++;  
  244.             count --;  
  245.             pos_in_byte ++;  
  246.         }  
  247.         if (pos_in_byte == 8) {  
  248.             crypt_buff_pre_8 = crypt_buff - 8;  
  249.             //if (! decrypt_every_8_byte()) return 0;  
  250.             decrypt_every_8_byte();  
  251.         }  
  252.     }/* while*/  
  253.   
  254.     for (padding = 1; padding < 8; padding ++) {  
  255.         if (pos_in_byte < 8) {  
  256.             if (crypt_buff_pre_8[pos_in_byte] ^ decrypted[pos_in_byte]) return 0; //若是和0异或的话则说明已解密完毕了  
  257.             pos_in_byte ++;  
  258.         }  
  259.         if (pos_in_byte == 8 ) {  
  260.             crypt_buff_pre_8 = crypt_buff;  
  261.             //if (! decrypt_every_8_byte()) return 0;  
  262.             decrypt_every_8_byte();  
  263.         }  
  264.     }/* for*/  
  265.     return 1;  
  266.   
  267. }  
  268.   
  269.   
  270. int Crypt::qq_crypt ( unsigned char   flag,  unsigned char*  instr,  int32  instrlen,  
  271.             unsigned char*  key, unsigned char*  outstr, int32* outstrlen_ptr)  
  272. {  
  273.     if (flag == DECRYPT)  
  274.         return decrypt(instr, instrlen, key, outstr, outstrlen_ptr);  
  275.     else  
  276.         if (flag == ENCRYPT)  
  277.             encrypt(instr, instrlen, key, outstr, outstrlen_ptr);  
  278.   
  279.     return 1; /* flag must be DECRYPT or ENCRYPT*/  
  280. }/* qq_crypt*/  


 

你可能感兴趣的:(c/c++,oicq,Reverse,engineering,Encryption,and,decryption)