• UID19
  • 登录2016-09-05
  • 粉丝10
  • 关注12
  • 发帖42
  • 主页
  • 金币837枚
社区居民
乾坤一掷 发布于2015-08-08 15:15
0/1576

TEA加密算法之PHP实现

楼层直达
TEA(Tiny Encryption Algorithm) 是一种简单高效的加密算法,以加密解密速度快,实现简单著称。TEA算法每一次可以操作64-bit(8-byte),采用128-bit(16-byte)作为key,算法采用迭代的形式。

TEA的优势:
不依赖第三方库,用基本的运算既可实现,容易跨平台使用。

代码实现:
class tea {
    private $a, $b, $c, $d;
    private $n_iter;
    public function __construct() {
        $this->setIter ( 32 );
    }
    public function setIter($n_iter) {
        $this->n_iter = $n_iter;
    }
    public function getIter() {
        return $this->n_iter;
    }
    public function encrypt($data, $key) {
        // resize data to 32 bits (4 bytes)
        $n = $this->_resize ( $data, 4 );
              
        // convert data to long
        $data_long [0] = $n;
        $n_data_long = $this->_str2long ( 1, $data, $data_long );
        // resize data_long to 64 bits (2 longs of 32 bits)
        $n = count ( $data_long );
        if (($n & 1) == 1) {
            $data_long [$n] = chr ( 0 );
            $n_data_long ++;
        }
              
        // resize key to a multiple of 128 bits (16 bytes)
        $this->_resize ( $key, 16, true );
        if ('' == $key)
            $key = '0000000000000000';
                  
        // convert key to long
        $n_key_long = $this->_str2long ( 0, $key, $key_long );
              
        // encrypt the long data with the key
        $enc_data = '';
        $w = array (0, 0 );
        $j = 0;
        $k = array (0, 0, 0, 0 );
        for($i = 0; $i < $n_data_long; ++ $i) {
            // get next key part of 128 bits
            if ($j + 4 <= $n_key_long) {
                $k [0] = $key_long [$j];
                $k [1] = $key_long [$j + 1];
                $k [2] = $key_long [$j + 2];
                $k [3] = $key_long [$j + 3];
            } else {
                $k [0] = $key_long [$j % $n_key_long];
                $k [1] = $key_long [($j + 1) % $n_key_long];
                $k [2] = $key_long [($j + 2) % $n_key_long];
                $k [3] = $key_long [($j + 3) % $n_key_long];
            }
            $j = ($j + 4) % $n_key_long;
                  
            $this->_encipherLong ( $data_long [$i], $data_long [++ $i], $w, $k );
                  
            // append the enciphered longs to the result
            $enc_data .= $this->_long2str ( $w [0] );
            $enc_data .= $this->_long2str ( $w [1] );
        }
              
        return $enc_data;
    }
    public function decrypt($enc_data, $key) {
        // convert data to long
        $n_enc_data_long = $this->_str2long ( 0, $enc_data, $enc_data_long );
              
        // resize key to a multiple of 128 bits (16 bytes)
        $this->_resize ( $key, 16, true );
        if ('' == $key)
            $key = '0000000000000000';
                  
        // convert key to long
        $n_key_long = $this->_str2long ( 0, $key, $key_long );
              
        // decrypt the long data with the key
        $data = '';
        $w = array (0, 0 );
        $j = 0;
        $len = 0;
        $k = array (0, 0, 0, 0 );
        $pos = 0;
              
        for($i = 0; $i < $n_enc_data_long; $i += 2) {
            // get next key part of 128 bits
            if ($j + 4 <= $n_key_long) {
                $k [0] = $key_long [$j];
                $k [1] = $key_long [$j + 1];
                $k [2] = $key_long [$j + 2];
                $k [3] = $key_long [$j + 3];
            } else {
                $k [0] = $key_long [$j % $n_key_long];
                $k [1] = $key_long [($j + 1) % $n_key_long];
                $k [2] = $key_long [($j + 2) % $n_key_long];
                $k [3] = $key_long [($j + 3) % $n_key_long];
            }
            $j = ($j + 4) % $n_key_long;
                  
            $this->_decipherLong ( $enc_data_long [$i], $enc_data_long [$i + 1], $w, $k );
                  
            // append the deciphered longs to the result data (remove padding)
            if (0 == $i) {
                $len = $w [0];
                if (4 <= $len) {
                    $data .= $this->_long2str ( $w [1] );
                } else {
                    $data .= substr ( $this->_long2str ( $w [1] ), 0, $len % 4 );
                }
            } else {
                $pos = ($i - 1) * 4;
                if ($pos + 4 <= $len) {
                    $data .= $this->_long2str ( $w [0] );
                          
                    if ($pos + 8 <= $len) {
                        $data .= $this->_long2str ( $w [1] );
                    } elseif ($pos + 4 < $len) {
                        $data .= substr ( $this->_long2str ( $w [1] ), 0, $len % 4 );
                    }
                } else {
                    $data .= substr ( $this->_long2str ( $w [0] ), 0, $len % 4 );
                }
            }
        }
        return $data;
    }
    private function _encipherLong($y, $z, &$w, &$k) {
        $sum = ( integer ) 0;
        $delta = 0x9E3779B9;
        $n = ( integer ) $this->n_iter;
              
        while ( $n -- > 0 ) {
                       //C v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
                       //C v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);  
            $sum = $this->_add ( $sum, $delta );
            $y = $this->_add ( $y, $this->_add ( ($z << 4),$this->a) ^ $this->_add($z , $sum) ^ $this->_add($this->_rshift ( $z, 5 ), $this->b )  );
            $z = $this->_add ( $z, $this->_add ( ($y << 4),$this->a) ^ $this->_add($y , $sum) ^ $this->_add($this->_rshift ( $y, 5 ), $this->b )  );
        }
              
        $w [0] = $y;
        $w [1] = $z;
    }
    private function _decipherLong($y, $z, &$w, &$k) {
        $delta = 0x9E3779B9;        
        if ($this->n_iter == 32) {
            $sum = 0xC6EF3720; // sum = delta<<5, in general sum = delta * n
        }
        else if ($this->n_iter == 16) {
            $sum = 0xE3779B90; //* delta << 4*/
        }
        else {
            $log2 = log($this->n_iter, 2);
            $sum = $delta << $log2;
        }        
              
        $n = ( integer ) $this->n_iter;
              
        while ( $n -- > 0 ) {
                    //C v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
                    //C v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
            $z = $this->_add ( $z, -($this->_add ( ($y << 4),$this->a) ^ $this->_add($y , $sum) ^ $this->_add($this->_rshift ( $y, 5 ), $this->b ) ) );
            $y = $this->_add ( $y, - ($this->_add ( ($z << 4),$this->a) ^ $this->_add($z , $sum) ^ $this->_add($this->_rshift ( $z, 5 ), $this->b ) ) );
            $sum = $this->_add ( $sum, - $delta );
            }
              
        $w [0] = $y;
        $w [1] = $z;
    }
    private function _resize(&$data, $size, $nonull = false) {
        $n = strlen ( $data );
        $nmod = $n % $size;
        if (0 == $nmod)
            $nmod = $size;
              
        if ($nmod > 0) {
            if ($nonull) {
                for($i = $n; $i < $n - $nmod + $size; ++ $i) {
                    $data [$i] = $data [$i % $n];
                }
            } else {
                for($i = $n; $i < $n - $nmod + $size; ++ $i) {
                    $data [$i] = chr ( 0 );
                }
            }
        }
        return $n;
    }
    private function _hex2bin($str) {
        $len = strlen ( $str );
        return pack ( 'H' . $len, $str );
    }
    private function _str2long($start, &$data, &$data_long) {
        $n = strlen ( $data );
              
        //N - unsigned long (always 32 bit, big endian byte order)
        $tmp = unpack ( 'N*', $data );
        $j = $start;
              
        foreach ( $tmp as $value )
            $data_long [$j ++] = $value;
              
        return $j;
    }
    private function _long2str($l) {
        return pack ( 'N', $l );
    }
          
          
    private function _rshift($integer, $n) {
        // convert to 32 bits
        if (0xffffffff < $integer || - 0xffffffff > $integer) {
            $integer = fmod ( $integer, 0xffffffff + 1 );
        }
              
        // convert to unsigned integer
        if (0x7fffffff < $integer) {
            $integer -= 0xffffffff + 1.0;
        } elseif (- 0x80000000 > $integer) {
            $integer += 0xffffffff + 1.0;
        }
              
        // do right shift
        if (0 > $integer) {
            $integer &= 0x7fffffff; // remove sign bit before shift
            $integer >>= $n; // right shift
            $integer |= 1 << (31 - $n); // set shifted sign bit
        } else {
            $integer >>= $n; // use normal right shift
        }
              
        return $integer;
    }
    private function _add($i1, $i2) {
        $result = 0.0;
              
        foreach ( func_get_args () as $value ) {
            // remove sign if necessary
            if (0.0 > $value) {
                $value -= 1.0 + 0xffffffff;
            }
                  
            $result += $value;
        }
              
        // convert to 32 bits
        if (0xffffffff < $result || - 0xffffffff > $result) {
            $result = fmod ( $result, 0xffffffff + 1 );
        }
              
        // convert to signed integer
        if (0x7fffffff < $result) {
            $result -= 0xffffffff + 1.0;
        } elseif (- 0x80000000 > $result) {
            $result += 0xffffffff + 1.0;
        }
              
        return $result;
    }
}
使用方法:
$t = new tea ( );
$encrypt_texy = $tea->encrypt ( $data, $key );
$decrypt_text = $tea->decrypt ( $encrypt_texy, $key );
注意事项:
该算法输入key和data可以是任意值,任意长度。
key长度大于等于16的时候字节时,取前16字节作为有效值。key长度小于16的时候,不足的部分会进行填充,可以选择全部填充字节0x00,或者以key值填充,比如0123456789可以填充为0123456789000000或01234567890123456。
text值填充,加密是先填充4个字节,值是原始text的总长度,然后在结尾填充0保证新的text总长度是8的倍数,然后解密的时候去掉填充。

提供详细的demo,见附件。


Note:本源代码由“极分享”社区创建,添加或者修改,我们会持续优化源代码以提供更好的解决方案,更多详情和支持请前往finalshares.com

0人打赏
您需要登录后才可以回帖
发表回复
极贡献
技术问答
专题荟萃
程序人生
视觉设计
Android开发
iOS开发
编程语言
前端开发
后端开发
服务器架构
软件测试
运维方案
创业路上



最热文章墙

  • 59908/343   【精品推荐】200多种Android动画效果的强悍框架,太全了,不看这个,再有动画的问题,不理你了^@^

  • 33115/188   情人节福利,程序员表白的正确姿势:改几行代码就变成自己的表白了

  • 31789/141   省时省力的Android组件群来了,非常棒的原型参考

  • 28842/223   【精品推荐】Android版产品级的音乐播放器源码,功能太强大了,最好的产品原型有木有?

  • 26180/2   超全!整理常用的iOS第三方资源

  • 25579/0   Python爬虫:常用浏览器的useragent

  • 24675/70   原创表白APP,以程序员的姿势备战新年后的7夕,持续完善中!

  • 22839/138   2016抢红包软件及源码

  • 19937/29   麻省理工的一帮疯子,真的实现了随意操控万物!(绝对黑科技)

  • 19784/25   Android工程师面试题大全

  • 19190/27   2016程序员跳槽全攻略

  • 18982/9   GitHub上排名前50的iOS项目:总有一款你用得着

  • 18500/20   码魂:程序员的牛B漫画

  • 16859/3   吐槽那些程序员的搞笑牛逼注释

  • 16781/149   Android版类似UC浏览器:非常赞,产品级的源码

  • 15690/1   iOS 动画总结

  • 15210/41   一个绚丽的loading动效分析与实现!

  • 15193/10   2016年最全的Android面试考题+答案 精编版

  • 14779/73   【持续更新中】Android福利贴(二):资料源码大放送

  • 14723/83   Android小而全的博客源码:非常适合全面掌握开发技巧

  • 14649/10   女程序员的梦,众网友的神回复

  • 14508/44   惊艳的App引导页:背景图片切换加各个页面动画效果

  • 14456/11   年会上现场review代码是怎么样的体验!

  • 14158/23   个人收集的Android 各类功能源代码

  • 14076/5   新一代Android渠道打包工具:1000个渠道包只需要5秒

  • 13258/19   珍藏多年的素材,灵感搜寻网站

  • 13212/53   基于瀑布流的美女图片浏览App,有注释的源代码

  • 12872/17   用JavaScript 来开发iOS和Android 原生应用:React Native开源框架中文版来啦

  • 12753/15   基于Android支付宝支付设计和开发方案

  • 12713/74   仿京东商城客户端Android最新版,不错的原型和学习资料

  • 12494/20   Android福利第三波【Android电子书】

  • 12310/17   什么是真正的黑客:收获12200+Stars,人气远超微软开源VS

  • 12127/18   65条最常用正则表达式,你要的都在这里了

  • 12116/94   Android带弹幕的视频播放器源码,来自大名鼎鼎的Bilibili弹幕网站

  • 11989/70   【精品推荐】类似360安全卫士安Android源码:非常赞的产品原型

  • 11721/7   用程序员的姿势抢过年的火车票

  • 11666/7   一张图搞定iOS学习路线,非常全面

  • 11606/11   有木有这样一张酷图帮你集齐所有git命令超实用

  • 11584/0   iOS中文版资源库,非常全

  • 11139/10   成为Java顶尖程序员 ,看这11本书就够了

  • 10873/18   一张图搞定Android学习路线,非常全面

  • 10810/10   微信支付终于成功了(安卓,iOS),在此分享

  • 10458/44   在线音乐播放器完整版(商用级的源码):非常赞,可听免费高品质专辑

  • 10428/3   基于Node.js的强大爬虫,能直接发布抓取的文章哦

  • 10336/29   【持续更新中】Android福利贴(一):资料源码

  • 10329/0   GitHub iOS 库和框架Top100 

  • 9903/4   46 个非常有用的 PHP 代码片段

  • 9672/3   即时通信第三方库

  • 9561/61   【技巧一】搭配Android Studio,如何实现App远程真机debug?

  • 9496/9   烧了5亿美金,这家神秘的公司即将颠覆人类未来!

  • 9447/8   流媒体视频直播方案

  • 9299/9   B站建开源工作组:APP想支持炫酷弹幕的看过来

  • 9181/18   八个最优秀的Android Studio插件

  • 9151/2   【精品推荐】高质量PHP代码的50个实用技巧:非常值得收藏

  • 9056/9   中国黑客的隐秘江湖:攻守对立,顶尖高手月入千万美元

  • 8620/6   开箱即用!Android四款系统架构工具

  • 8515/3   一张图看清Linux 内核运行原理

  • 8413/10   十大技巧快速提升Android应用开发性能

  • 8388/3   10款GitHub上最火爆的国产开源项目——可以媲美西半球

  • 8073/1   Android性能优化视频,文档以及工具

  • 返回顶部