在晚上找了一天了,有找到一个代码,但是tea加出来随机不了,晕死。
急需要正确的PHP TEA加解密算法。请贴上完整代码。解决后继续加分。

解决方案 »

  1.   


    参考,查看完整版本,请访问 PHP之TEA算法实现:PHP之TEA算法实现
    算法简单,而且效率高,每次可以操作8个字节的数据,加密解密的KEY为16字节,即包含4个int数据的int型数组,加密轮数应为8的倍数,一般比较常用的轮数为64,32,16,QQ原来就是用TEA16来还原密码的.TEA算法
    核心为view sourceprint?01.#include <stdint.h> 
    02. 
     
    03.void encrypt (uint32_t* v, uint32_t* k) { 
    04.    
    uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */
    05.    
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    06.    
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    07.    
    for (i=0; i < 32; i++) {                       /* basic cycle start */
    08.        
    sum += delta; 
    09.        
    v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); 
    10.        
    v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); 
    11.    
    }                                              /* end cycle */
    12.    
    v[0]=v0; v[1]=v1; 
    13.} 
    14. 
     
    15.void decrypt (uint32_t* v, uint32_t* k) { 
    16.    
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */
    17.    
    uint32_t delta=0x9e3779b9;                     /* a key schedule constant */
    18.    
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */
    19.    
    for (i=0; i<32; i++) {                         /* basic cycle start */
    20.        
    v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); 
    21.        
    v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); 
    22.        
    sum -= delta; 
    23.    
    }                                              /* end cycle */
    24.    
    v[0]=v0; v[1]=v1; 
    25.}PHP部分代码非我原创,大家可以了解一下这方面的知识view sourceprint?001.<?php 
    002.$date = '8345354023476-3434'; 
    003.$key = '12345'; 
    004. 
     
    005.$t = new tea ( ); 
    006.$tea = $t->encrypt ( $date, $key ); 
    007.$eetea = $t->decrypt ( $tea, $key ); 
    008. 
     
    009.var_dump ( $tea ); 
    010.var_dump ( $eetea ); 
    011.class tea { 
    012.    
    private $a, $b, $c, $d; 
    013.    
    private $n_iter; 
    014.    
    public function __construct() { 
    015.        
    $this->setIter ( 32 ); 
    016.    

    017. 
     
    018.    
    private function setIter($n_iter) { 
    019.        
    $this->n_iter = $n_iter; 
    020.    

    021. 
     
    022.    
    private function getIter() { 
    023.        
    return $this->n_iter; 
    024.    

    025. 
     
    026.    
    public function encrypt($data, $key) { 
    027.        
    // resize data to 32 bits (4 bytes) 
    028.        
    $n = $this->_resize ( $data, 4 ); 
    029. 
     
    030.        
    // convert data to long 
    031.        
    $data_long [0] = $n; 
    032.        
    $n_data_long = $this->_str2long ( 1, $data, $data_long ); 
    033. 
     
    034.        
    // resize data_long to 64 bits (2 longs of 32 bits) 
    035.        
    $n = count ( $data_long ); 
    036.        
    if (($n & 1) == 1) { 
    037.            
    $data_long [$n] = chr ( 0 ); 
    038.            
    $n_data_long ++; 
    039.        

    040. 
     
    041.        
    // resize key to a multiple of 128 bits (16 bytes) 
    042.        
    $this->_resize ( $key, 16, true ); 
    043.        
    if ('' == $key) 
    044.            
    $key = '0000000000000000'; 
    045. 
     
    046.        
    // convert key to long 
    047.        
    $n_key_long = $this->_str2long ( 0, $key, $key_long ); 
    048. 
     
    049.        
    // encrypt the long data with the key 
    050.        
    $enc_data = ''; 
    051.        
    $w = array (0, 0 ); 
    052.        
    $j = 0; 
    053.        
    $k = array (0, 0, 0, 0 ); 
    054.        
    for($i = 0; $i < $n_data_long; ++ $i) { 
    055.            
    // get next key part of 128 bits 
    056.            
    if ($j + 4 <= $n_key_long) { 
    057.                
    $k [0] = $key_long [$j]; 
    058.                
    $k [1] = $key_long [$j + 1]; 
    059.                
    $k [2] = $key_long [$j + 2]; 
    060.                
    $k [3] = $key_long [$j + 3]; 
    061.            
    } else { 
    062.                
    $k [0] = $key_long [$j % $n_key_long]; 
    063.                
    $k [1] = $key_long [($j + 1) % $n_key_long]; 
    064.                
    $k [2] = $key_long [($j + 2) % $n_key_long]; 
    065.                
    $k [3] = $key_long [($j + 3) % $n_key_long]; 
    066.            

    067.            
    $j = ($j + 4) % $n_key_long; 
    068. 
     
    069.            
    $this->_encipherLong ( $data_long [$i], $data_long [++ $i], $w, $k ); 
    070. 
     
    071.            
    // append the enciphered longs to the result 
    072.            
    $enc_data .= $this->_long2str ( $w [0] ); 
    073.            
    $enc_data .= $this->_long2str ( $w [1] ); 
    074.        

    075. 
     
    076.        
    return $enc_data; 
    077.    

    078. 
     
    079.    
    public function decrypt($enc_data, $key) { 
    080.        
    // convert data to long 
    081.        
    $n_enc_data_long = $this->_str2long ( 0, $enc_data, $enc_data_long ); 
    082. 
     
    083.        
    // resize key to a multiple of 128 bits (16 bytes) 
    084.        
    $this->_resize ( $key, 16, true ); 
    085.        
    if ('' == $key) 
    086.            
    $key = '0000000000000000'; 
    087. 
     
    088.        
    // convert key to long 
    089.        
    $n_key_long = $this->_str2long ( 0, $key, $key_long ); 
    090. 
     
    091.        
    // decrypt the long data with the key 
    092.        
    $data = ''; 
    093.        
    $w = array (0, 0 ); 
    094.        
    $j = 0; 
    095.        
    $len = 0; 
    096.        
    $k = array (0, 0, 0, 0 ); 
    097.        
    $pos = 0; 
    098. 
     
    099.        
    for($i = 0; $i < $n_enc_data_long; $i += 2) { 
    100.            
    // get next key part of 128 bits 
    101.            
    if ($j + 4 <= $n_key_long) { 
    102.                
    $k [0] = $key_long [$j]; 
    103.                
    $k [1] = $key_long [$j + 1]; 
    104.                
    $k [2] = $key_long [$j + 2]; 
    105.                
    $k [3] = $key_long [$j + 3]; 
    106.            
    } else { 
    107.                
    $k [0] = $key_long [$j % $n_key_long]; 
    108.                
    $k [1] = $key_long [($j + 1) % $n_key_long]; 
    109.                
    $k [2] = $key_long [($j + 2) % $n_key_long]; 
    110.                
    $k [3] = $key_long [($j + 3) % $n_key_long]; 
    111.            

    112.            
    $j = ($j + 4) % $n_key_long; 
    113. 
     
    114.            
    $this->_decipherLong ( $enc_data_long [$i], $enc_data_long [$i + 1], $w, $k ); 
    115. 
     
    116.            
    // append the deciphered longs to the result data (remove padding) 
    117.            
    if (0 == $i) { 
    118.                
    $len = $w [0]; 
    119.                
    if (4 <= $len) { 
      

  2.   

    120.                    
    $data .= $this->_long2str ( $w [1] ); 
    121.                
    } else { 
    122.                    
    $data .= substr ( $this->_long2str ( $w [1] ), 0, $len % 4 ); 
    123.                

    124.            
    } else { 
    125.                
    $pos = ($i - 1) * 4; 
    126.                
    if ($pos + 4 <= $len) { 
    127.                    
    $data .= $this->_long2str ( $w [0] ); 
    128. 
     
    129.                    
    if ($pos + 8 <= $len) { 
    130.                        
    $data .= $this->_long2str ( $w [1] ); 
    131.                    
    } elseif ($pos + 4 < $len) { 
    132.                        
    $data .= substr ( $this->_long2str ( $w [1] ), 0, $len % 4 ); 
    133.                    

    134.                
    } else { 
    135.                    
    $data .= substr ( $this->_long2str ( $w [0] ), 0, $len % 4 ); 
    136.                

    137.            

    138.        

    139.        
    return $data; 
    140.    

    141. 
     
    142.    
    private function _encipherLong($y, $z, &$w, &$k) { 
    143.        
    $sum = ( integer ) 0; 
    144.        
    $delta = 0x9E3779B9; 
    145.        
    $n = ( integer ) $this->n_iter; 
    146. 
     
    147.        
    while ( $n -- > 0 ) { 
    148.                       
    //C v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); 
    149.                       
    //C v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);   
    150. 
     
    151.            
    $sum = $this->_add ( $sum, $delta ); 
    152.            
    $y = $this->_add ( $y, $this->_add ( ($z << 4),$this->a) ^ $this->_add($z , $sum) ^ $this->_add($this->_rshift ( $z, 5 ), $this->b )  ); 
    153.            
    $z = $this->_add ( $z, $this->_add ( ($y << 4),$this->a) ^ $this->_add($y , $sum) ^ $this->_add($this->_rshift ( $y, 5 ), $this->b )  ); 
    154.        

    155. 
     
    156.        
    $w [0] = $y; 
    157.        
    $w [1] = $z; 
    158.    

    159. 
     
    160.    
    private function _decipherLong($y, $z, &$w, &$k) { 
    161.        
    // sum = delta<<5, in general sum = delta * n 
    162.        
    $sum = 0xC6EF3720; 
    163.        
    $delta = 0x9E3779B9; 
    164.        
    $n = ( integer ) $this->n_iter; 
    165. 
     
    166.        
    while ( $n -- > 0 ) { 
    167.                    
    //C v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); 
    168.                    
    //C v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); 
    169.            
    $z = $this->_add ( $z, -($this->_add ( ($y << 4),$this->a) ^ $this->_add($y , $sum) ^ $this->_add($this->_rshift ( $y, 5 ), $this->b ) ) ); 
    170.            
    $y = $this->_add ( $y, - ($this->_add ( ($z << 4),$this->a) ^ $this->_add($z , $sum) ^ $this->_add($this->_rshift ( $z, 5 ), $this->b ) ) ); 
    171.            
    $sum = $this->_add ( $sum, - $delta ); 
    172.            

    173. 
     
    174.        
    $w [0] = $y; 
    175.        
    $w [1] = $z; 
    176.    

    177. 
     
    178.    
    private function _resize(&$data, $size, $nonull = false) { 
    179.        
    $n = strlen ( $data ); 
    180.        
    $nmod = $n % $size; 
    181.        
    if (0 == $nmod) 
    182.            
    $nmod = $size; 
    183. 
     
    184.        
    if ($nmod > 0) { 
    185.            
    if ($nonull) { 
    186.                
    for($i = $n; $i < $n - $nmod + $size; ++ $i) { 
    187.                    
    $data [$i] = $data [$i % $n]; 
    188.                

    189.            
    } else { 
    190.                
    for($i = $n; $i < $n - $nmod + $size; ++ $i) { 
    191.                    
    $data [$i] = chr ( 0 ); 
    192.                

    193.            

    194.        

    195.        
    return $n; 
    196.    

    197. 
     
    198.    
    private function _hex2bin($str) { 
    199.        
    $len = strlen ( $str ); 
    200.        
    return pack ( 'H' . $len, $str ); 
    201.    

    202. 
     
    203.    
    private function _str2long($start, &$data, &$data_long) { 
    204.        
    $n = strlen ( $data ); 
    205. 
     
    206.        
    $tmp = unpack ( 'N*', $data ); 
    207.        
    $j = $start; 
    208. 
     
    209.        
    foreach ( $tmp as $value ) 
    210.            
    $data_long [$j ++] = $value; 
    211. 
     
    212.        
    return $j; 
    213.    

    214. 
     
    215.    
    private function _long2str($l) { 
    216.        
    return pack ( 'N', $l ); 
    217.    

    218. 
     
    219.    
    private function _rshift($integer, $n) { 
    220.        
    // convert to 32 bits 
    221.        
    if (0xffffffff < $integer || - 0xffffffff > $integer) { 
    222.            
    $integer = fmod ( $integer, 0xffffffff + 1 ); 
    223.        

    224. 
     
    225.        
    // convert to unsigned integer 
    226.        
    if (0x7fffffff < $integer) { 
    227.            
    $integer -= 0xffffffff + 1.0; 
    228.        
    } elseif (- 0x80000000 > $integer) { 
    229.            
    $integer += 0xffffffff + 1.0; 
    230.        

    231. 
     
    232.        
    // do right shift 
    233.        
    if (0 > $integer) { 
    234.            
    $integer &= 0x7fffffff; // remove sign bit before shift 
    235.            
    $integer >>= $n; // right shift 
    236.            
    $integer |= 1 << (31 - $n); // set shifted sign bit 
    237.        
    } else { 
    238.            
    $integer >>= $n; // use normal right shift 
    239.        

    240. 
     
    241.        
    return $integer; 
    242.    

    243. 
     
    244.    
    private function _add($i1, $i2) { 
    245.        
    $result = 0.0; 
    246. 
     
    247.        
    foreach ( func_get_args () as $value ) { 
    248.            
    // remove sign if necessary 
    249.            
    if (0.0 > $value) { 
    250.                
    $value -= 1.0 + 0xffffffff; 
    251.            

    252. 
     
    253.            
    $result += $value; 
    254.        

    255. 
     
    256.        
    // convert to 32 bits 
    257.        
    if (0xffffffff < $result || - 0xffffffff > $result) { 
    258.            
    $result = fmod ( $result, 0xffffffff + 1 ); 
    259.        

    260. 
     
    261.        
    // convert to signed integer 
    262.        
    if (0x7fffffff < $result) { 
    263.            
    $result -= 0xffffffff + 1.0; 
    264.        
    } elseif (- 0x80000000 > $result) { 
    265.            
    $result += 0xffffffff + 1.0; 
    266.        

    267. 
     
    268.        
    return $result; 
    269.    

    270. 
     
    271.// }}} 
    272.} 
    273. 
     
    274.?>
    上面的是TEA的算法,XTEA算法为view sourceprint?01.#include <stdint.h> 
    02. 
     
    03.void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) { 
    04.    
    unsigned int i; 
    05.    
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9; 
    06.    
    for (i=0; i < num_rounds; i++) { 
    07.        
    v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); 
    08.        
    sum += delta; 
    09.        
    v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); 
    10.    

    11.    
    v[0]=v0; v[1]=v1; 
    12.} 
    13. 
     
    14.void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const k[4]) { 
    15.    
    unsigned int i; 
    16.    
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds; 
    17.    
    for (i=0; i < num_rounds; i++) { 
    18.        
    v1 ?= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); 
    19.        
    sum ?= delta; 
    20.        
    v0 ?= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); 
    21.    

    22.    
    v[0]=v0; v[1]=v1; 
    23.}
    那PHP中只需要把运算的位置改下就OKview sourceprint?01.private function _teaencipherLong($y, $z, &$w, &$k) { 
    02.    
    $sum = ( integer ) 0; 
    03.    
    $delta = 0x9E3779B9; 
    04.    
    $n = ( integer ) $this->n_iter; 
    05.    
    while ( $n -- > 0 ) { 
    06.        
    $y = $this->_add ( $y, $this->_add ( $z << 4 ^ $this->_rshift ( $z, 5 ), $z ) ^ $this->_add ( $sum, $k [$sum & 3] ) ); 
    07.        
    $sum = $this->_add ( $sum, $delta ); 
    08.        
    $z = $this->_add ( $z, $this->_add ( $y << 4 ^ $this->_rshift ( $y, 5 ), $y ) ^ $this->_add ( $sum, $k [$this->_rshift ( $sum, 11 ) & 3] ) ); 
    09.    

    10.    
    $w [0] = $y; 
    11.    
    $w [1] = $z; 
    12.} 
    13.private function _decipherLong($y, $z, &$w, &$k) { 
    14.    
    // sum = delta<<5, in general sum = delta * n 
    15.    
    $sum = 0xC6EF3720; 
    16.    
    $delta = 0x9E3779B9; 
    17.    
    $n = ( integer ) $this->n_iter; 
    18.    
    while ( $n -- > 0 ) { 
    19.        
    $z = $this->_add ( $z, - ($this->_add ( $y << 4 ^ $this->_rshift ( $y, 5 ), $y ) ^ $this->_add ( $sum, $k [$this->_rshift ( $sum, 11 ) & 3] )) ); 
    20.        
    $sum = $this->_add ( $sum, - $delta ); 
    21.        
    $y = $this->_add ( $y, - ($this->_add ( $z << 4 ^ $this->_rshift ( $z, 5 ), $z ) ^ $this->_add ( $sum, $k [$sum & 3] )) ); 
    22.    

    23.    
    $w [0] = $y; 
    24.    
    $w [1] = $z; 
    25.} 
    XXTEA的算法
    核心为view sourceprint?01.#define MX (z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[p&3^e]^z); 
    02. 
    long btea(long* v, long n, long* k) { 
    03.   
    unsigned long z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9; 
    04.   
    long p, q ; 
    05.   
    if (n > 1) {          /* Coding Part */
    06.     
    q = 6 + 52/n; 
    07.     
    while (q-- > 0) { 
    08.       
    sum += DELTA; 
    09.       
    e = (sum >> 2) & 3; 
    10.       
    for (p=0; p<n-1; p++) y = v[p+1], z = v[p] += MX; 
    11.       
    y = v[0]; 
    12.       
    z = v[n-1] += MX; 
    13.     

    14.     
    return 0 ; 
    15.   
    } else if (n < -1) {  /* Decoding Part */
    16.     
    n = -n; 
    17.     
    q = 6 + 52/n; 
    18.     
    sum = q*DELTA ; 
    19.     
    while (sum != 0) { 
    20.       
    e = (sum >> 2) & 3; 
    21.       
    for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX; 
    22.       
    z = v[n-1]; 
    23.       
    y = v[0] -= MX; 
    24.       
    sum -= DELTA; 
    25.     

    26.     
    return 0; 
    27.   

    28.   
    return 1; 
    29. 
    }
    也是运算不一样,这个就不写了,有人已经写过这方面的代码了
      

  3.   

    我希望tea加密后得到的是对加密后的字节数组的16进制串,以上加密函数得出的是string,经过strtohex,却是30位的,而且还不会随机变化,不懂不懂啊,有人吗?