TEA加密算法的CC++实现(转载)

    技术2026-05-03  1

    TEA加密算法的C/C++实现

    转载自 http://www.cppblog.com/ant/archive/2007/10/12/31326.html

     

    TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。算法真的很简单,TEA算法每一次可以操作64-bit(8-byte),采 用128-bit(16-byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。目前我只知道QQ一直用的是16轮TEA。没 什么好说的,先给出C语言的源代码(默认是32轮):

     1  void  encrypt(unsigned  long   * v, unsigned  long   * k) {  2      unsigned  long  y = v[ 0 ], z = v[ 1 ], sum = 0 , i;          /*  set up  */  3      unsigned  long  delta = 0x9e3779b9 ;                  /*  a key schedule constant  */  4      unsigned  long  a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ];    /*  cache key  */  5       for  (i = 0 ; i  <   32 ; i ++ ) {                         /*  basic cycle start  */  6          sum  +=  delta;  7          y  +=  ((z << 4 +  a)  ^  (z  +  sum)  ^  ((z >> 5 +  b);  8          z  +=  ((y << 4 +  c)  ^  (y  +  sum)  ^  ((y >> 5 +  d); /*  end cycle  */  9       } 10      v[ 0 ] = y; 11      v[ 1 ] = z; 12   } 13   14  void  decrypt(unsigned  long   * v, unsigned  long   * k) { 15      unsigned  long  y = v[ 0 ], z = v[ 1 ], sum = 0xC6EF3720 , i;  /*  set up  */ 16      unsigned  long  delta = 0x9e3779b9 ;                   /*  a key schedule constant  */ 17      unsigned  long  a = k[ 0 ], b = k[ 1 ], c = k[ 2 ], d = k[ 3 ];     /*  cache key  */ 18       for (i = 0 ; i < 32 ; i ++ ) {                             /*  basic cycle start  */ 19          z  -=  ((y << 4 +  c)  ^  (y  +  sum)  ^  ((y >> 5 +  d); 20          y  -=  ((z << 4 +  a)  ^  (z  +  sum)  ^  ((z >> 5 +  b); 21          sum  -=  delta;                                 /*  end cycle  */ 22       } 23      v[ 0 ] = y; 24      v[ 1 ] = z; 25  }

    C语言写的用起来当然不方便,没关系,用C++封装以下就OK了: util.h

     1   #ifndef UTIL_H  2   #define UTIL_H  3    4  #include  < string >  5  #include  < cstdlib >  6    7  typedef unsigned  char   byte ;  8  typedef unsigned  long  ulong;  9   10  /* 11   *convert int to hex char. 12   *example:10 -> 'A',15 -> 'F' 13  */ 14  char  intToHexChar( int  x); 15   16  /* 17   *convert hex char to int. 18   *example:'A' -> 10,'F' -> 15 19  */ 20  int  hexCharToInt( char  hex); 21   22   using std::string; 23  /* 24   *convert a byte array to hex string. 25   *hex string format example:"AF B0 80 7D" 26  */ 27  string bytesToHexString( const   byte   * in, size_t size); 28   29  /* 30   *convert a hex string to a byte array. 31   *hex string format example:"AF B0 80 7D" 32  */ 33  size_t hexStringToBytes( const  string  & str,  byte   * out); 34   35  #endif /* UTIL_H */

    util.cpp

     1  #include  " util.h "  2  #include  < vector >  3    4   using namespace std;  5    6  char  intToHexChar( int  x) {  7       static   const   char  HEX[ 16 =  {  8           ' 0 ' ' 1 ' ' 2 ' ' 3 ' ,  9           ' 4 ' ' 5 ' ' 6 ' ' 7 ' , 10           ' 8 ' ' 9 ' ' A ' ' B ' , 11           ' C ' ' D ' ' E ' ' F ' 12       }; 13       return  HEX[x]; 14   } 15   16  int  hexCharToInt( char  hex) { 17      hex  =  toupper(hex); 18       if  (isdigit(hex)) 19           return  (hex  -   ' 0 ' ); 20       if  (isalpha(hex)) 21           return  (hex  -   ' A '   +   10 ); 22       return   0 ; 23   } 24   25  string bytesToHexString( const   byte   * in, size_t size) { 26       string str; 27       for  (size_t i  =   0 ; i  <  size;  ++ i) { 28           int  t  =  in[i]; 29           int  a  =  t  /   16 ; 30           int  b  =  t  %   16 ; 31          str.append( 1 , intToHexChar(a)); 32          str.append( 1 , intToHexChar(b)); 33           if  (i  !=  size  -   1 ) 34              str.append( 1 '   ' ); 35       } 36       return  str; 37   } 38   39  size_t hexStringToBytes( const  string  & str,  byte   * out) { 40   41      vector < string >  vec; 42      string::size_type currPos  =   0 , prevPos  =   0 ; 43       while  ((currPos  =  str.find( '   ' , prevPos))  !=  string::npos) { 44          string b(str.substr(prevPos, currPos  -  prevPos)); 45           vec.push_back(b); 46          prevPos  =  currPos  +   1 ; 47       } 48       if  (prevPos  <  str.size()) { 49           string b(str.substr(prevPos)); 50           vec.push_back(b); 51       } 52      typedef vector < string > ::size_type sz_type; 53      sz_type size  =  vec.size(); 54       for  (sz_type i  =   0 ; i  <  size;  ++ i) { 55           int  a  =  hexCharToInt(vec[i][ 0 ]); 56           int  b  =  hexCharToInt(vec[i][ 1 ]); 57          out[i]  =  a  *   16   +  b; 58       } 59       return  size; 60  }

    tea.h

     1   #ifndef TEA_H  2   #define TEA_H  3    4  /*  5   *for htonl,htonl  6   *do remember link "ws2_32.lib"  7  */  8  #include  < winsock2.h >  9  #include  " util.h " 10   11  class  TEA { 12  public : 13      TEA( const   byte   * key,  int  round  =   32 , bool isNetByte  =   false ); 14      TEA( const  TEA  & rhs); 15      TEA &  operator = ( const  TEA  & rhs); 16       void  encrypt( const   byte   * in,  byte   * out); 17       void  decrypt( const   byte   * in,  byte   * out); 18  private : 19       void  encrypt( const  ulong  * in, ulong  * out); 20       void  decrypt( const  ulong  * in, ulong  * out); 21      ulong ntoh(ulong netlong) {  return  _isNetByte  ?  ntohl(netlong) : netlong; } 22      ulong hton(ulong hostlong) {  return  _isNetByte  ?  htonl(hostlong) : hostlong; } 23  private : 24       int  _round;  // iteration round to encrypt or decrypt 25      bool _isNetByte;  // whether input bytes come from network 26       byte  _key[ 16 ];  // encrypt or decrypt key 27   }; 28   29  #endif /* TEA_H */

    tea.cpp

     1  #include  " tea.h "  2  #include  < cstring >   // for memcpy,memset  3    4   using namespace std;  5    6  TEA::TEA( const   byte   * key,  int  round  /* = 32 */ , bool isNetByte  /* = false */ )  7   :_round(round)  8   ,_isNetByte(isNetByte) {  9       if  (key  !=   0 ) 10          memcpy(_key, key,  16 ); 11       else 12          memset(_key,  0 16 ); 13   } 14   15  TEA::TEA( const  TEA  & rhs) 16   :_round(rhs._round) 17   ,_isNetByte(rhs._isNetByte) { 18      memcpy(_key, rhs._key,  16 ); 19   } 20   21  TEA &  TEA::operator = ( const  TEA  & rhs) { 22       if  ( & rhs  !=   this ) { 23          _round  =  rhs._round; 24          _isNetByte  =  rhs._isNetByte; 25          memcpy(_key, rhs._key,  16 ); 26       } 27       return   * this ; 28   } 29   30  void  TEA::encrypt( const   byte   * in,  byte   * out) { 31      encrypt(( const  ulong * )in, (ulong * )out); 32   } 33   34  void  TEA::decrypt( const   byte   * in,  byte   * out) { 35      decrypt(( const  ulong * )in, (ulong * )out); 36   } 37   38  void  TEA::encrypt( const  ulong  * in, ulong  * out) { 39   40      ulong  * =  (ulong * )_key; 41      register ulong y  =  ntoh(in[ 0 ]); 42      register ulong z  =  ntoh(in[ 1 ]); 43      register ulong a  =  ntoh(k[ 0 ]); 44      register ulong b  =  ntoh(k[ 1 ]); 45      register ulong c  =  ntoh(k[ 2 ]); 46      register ulong d  =  ntoh(k[ 3 ]); 47      register ulong delta  =   0x9E3779B9 /*  (sqrt(5)-1)/2*2^32  */ 48      register  int  round  =  _round; 49      register ulong sum  =   0 ; 50   51       while  (round -- ) {     /*  basic cycle start  */ 52          sum  +=  delta; 53          y  +=  ((z  <<   4 +  a)  ^  (z  +  sum)  ^  ((z  >>   5 +  b); 54          z  +=  ((y  <<   4 +  c)  ^  (y  +  sum)  ^  ((y  >>   5 +  d); 55      }     /*  end cycle  */ 56      out[ 0 =  ntoh(y); 57      out[ 1 =  ntoh(z); 58   } 59   60  void  TEA::decrypt( const  ulong  * in, ulong  * out) { 61   62      ulong  * =  (ulong * )_key; 63      register ulong y  =  ntoh(in[ 0 ]); 64      register ulong z  =  ntoh(in[ 1 ]); 65      register ulong a  =  ntoh(k[ 0 ]); 66      register ulong b  =  ntoh(k[ 1 ]); 67      register ulong c  =  ntoh(k[ 2 ]); 68      register ulong d  =  ntoh(k[ 3 ]); 69      register ulong delta  =   0x9E3779B9 /*  (sqrt(5)-1)/2*2^32  */ 70      register  int  round  =  _round; 71      register ulong sum  =   0 ; 72   73       if  (round  ==   32 ) 74          sum  =   0xC6EF3720 /*  delta << 5 */ 75       else   if  (round  ==   16 ) 76          sum  =   0xE3779B90 /*  delta << 4 */ 77       else 78          sum  =  delta  *  round; 79   80       while  (round -- ) {     /*  basic cycle start  */ 81          z  -=  ((y  <<   4 +  c)  ^  (y  +  sum)  ^  ((y  >>   5 +  d); 82          y  -=  ((z  <<   4 +  a)  ^  (z  +  sum)  ^  ((z  >>   5 +  b); 83          sum  -=  delta; 84      }     /*  end cycle  */ 85      out[ 0 =  ntoh(y); 86      out[ 1 =  ntoh(z); 87  }

    需要说明的是TEA的构造函数: TEA(const byte *key, int round = 32, bool isNetByte = false); 1.key - 加密或解密用的128-bit(16byte)密钥。 2.round - 加密或解密的轮数,常用的有64,32,16。 3.isNetByte - 用来标记待处理的字节是不是来自网络,为true时在加密/解密前先要转换成本地字节,执行加密/解密,然后再转换回网络字节。偷偷告诉你,QQ就是这样做的! 最后当然少不了测试代码: test.cpp

     1  #include  " tea.h "  2  #include  " util.h "  3  #include  < iostream >  4    5   using namespace std;  6    7  int  main() {  8    9       const  string plainStr( " AD DE E2 DB B3 E2 DB B3 " ); 10       const  string keyStr( " 3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4 " ); 11       const   int  SIZE_IN  =   8 , SIZE_OUT  =   8 , SIZE_KEY  =   16 ; 12       byte  plain[SIZE_IN], crypt[SIZE_OUT], key[SIZE_KEY]; 13   14      size_t size_in  =  hexStringToBytes(plainStr, plain); 15      size_t size_key  =  hexStringToBytes(keyStr, key); 16   17       if  (size_in  !=  SIZE_IN  ||  size_key  !=  SIZE_KEY) 18           return   - 1 ; 19   20      cout  <<   " Plain:  "   <<  bytesToHexString(plain, size_in)  <<  endl; 21      cout  <<   " Key  :  "   <<  bytesToHexString(key, size_key)  <<  endl; 22   23      TEA tea(key,  16 true ); 24       tea.encrypt(plain, crypt); 25      cout  <<   " Crypt:  "   <<  bytesToHexString(crypt, SIZE_OUT)  <<  endl; 26   27       tea.decrypt(crypt, plain); 28      cout  <<   " Plain:  "   <<  bytesToHexString(plain, SIZE_IN)  <<  endl; 29       return   0 ; 30  }

    运行结果: Plain: AD DE E2 DB B3 E2 DB B3 Key  : 3A DA 75 21 DB E2 DB B3 11 B4 49 01 A5 C6 EA D4 Crypt: 3B 3B 4D 8C 24 3A FD F2 Plain: AD DE E2 DB B3 E2 DB B3

    最新回复(0)