[AS3]AS3的加密算法(TEA)
微型加密算法(TEA)及其相关变种(XTEA,Block TEA,XXTEA) 都是分组加密算法,它们很容易被描述,实现也很简单(典型的几行代码)。
TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。该算法使用 128 位的密钥为 64 位的信息块进行加密,它需要进行 64 轮迭代,尽管作者认为 32 轮已经足够了。该算法使用了一个神秘常数δ作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但δ的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)。
之后 TEA 算法被发现存在缺陷,作为回应,设计者提出了一个 TEA 的升级版本——XTEA(有时也被称为“tean”)。XTEA 跟 TEA 使用了相同的简单运算,但它采用了截然不同的顺序,为了阻止密钥表攻击,四个子密钥(在加密过程中,原 128 位的密钥被拆分为 4 个 32 位的子密钥)采用了一种不太正规的方式进行混合,但速度更慢了。
在AS开发过程中,AS经常会和其他语言通信,通信过程中也会经常涉及到数据加密的问题,所以有必要改写一个AS3版本的TEA加密算法。
- /* TEA 对称性加密/解密函数
- * @author cheche 2010-8
- */
- package {
- import flash.utils.ByteArray;
- import flash.utils.Endian;
- public class TeaEncrypt {
- private static var round:uint=32;
- private static var key:String="3A DA 75 21 DB E3 DB B3 62 B7 49 01 A5 C6 EA D5";
- public static function teaEncrypt(enData:ByteArray):ByteArray {
- enData.position=0;
- var len:uint=Math.ceil(enData.length/8);
- var keyArr:Array=getKey(key);
- var keyBytes:ByteArray = new ByteArray();
- keyBytes.position;
- keyBytes.endian=Endian.LITTLE_ENDIAN;
- for (i=0; i<keyArr.length; i++) {
- keyBytes.writeByte(keyArr[i]);
- }
- var resData:ByteArray = new ByteArray();
- resData.position=0;
- resData.endian=Endian.LITTLE_ENDIAN;
- var nData:ByteArray = new ByteArray();
- nData.position=0;
- nData.endian=Endian.LITTLE_ENDIAN;
- enData.position=0;
- for (var i:uint=0; i<len; i++) {
- var enBytes:ByteArray = new ByteArray();
- enBytes.position=0;
- enBytes.endian=Endian.LITTLE_ENDIAN;
- if (enData.bytesAvailable>=8) {
- enData.readBytes(enBytes,0,8);
- var encrypted:ByteArray = new ByteArray();
- encrypted.position=0;
- encrypted.endian=Endian.LITTLE_ENDIAN;
- encryptencrypted=encrypt(enBytes,keyBytes);
- resData.writeBytes(encrypted,0,encrypted.length);
- encrypted.clear();
- encrypted=null;
- } else {
- enData.readBytes(nData,0,enData.bytesAvailable);
- }
- enBytes.clear();
- }
- nData.position=0;
- if (nData.length>0) {
- resData.writeBytes(nData,0,nData.length);
- }
- keyBytes.clear();
- return resData;
- enData.clear();
- }
- public static function teaDecrypt(decData:ByteArray):ByteArray {
- decData.position=0;
- var len:uint=Math.ceil(decData.length/8);
- var keyArr:Array=getKey(key);
- var keyBytes:ByteArray = new ByteArray();
- keyBytes.position;
- keyBytes.endian=Endian.LITTLE_ENDIAN;
- //将密钥写入缓冲区
- for (i=0; i<keyArr.length; i++) {
- keyBytes.writeByte(keyArr[i]);
- }
- var resData:ByteArray = new ByteArray();
- resData.position=0;
- resData.endian=Endian.LITTLE_ENDIAN;
- decData.position=0;
- for (var i:uint=0; i<len; i++) {
- var decBytes:ByteArray = new ByteArray();
- decBytes.position=0;
- decBytes.endian=Endian.LITTLE_ENDIAN;
- if (decData.bytesAvailable>=8) {
- decData.readBytes(decBytes,0,8);
- var decrypted:ByteArray = new ByteArray();
- decrypted.position=0;
- decrypted.endian=Endian.LITTLE_ENDIAN;
- decryptdecrypted=decrypt(decBytes,keyBytes);
- resData.writeBytes(decrypted,0,decrypted.length);
- decrypted.clear();
- } else {
- var nData:ByteArray = new ByteArray();
- nData.position=0;
- nData.endian=Endian.LITTLE_ENDIAN;
- decData.readBytes(nData,0,decData.bytesAvailable);
- }
- }
- keyBytes.clear();
- decData.clear();
- trace("解密后数据>>>>"+ByteArrayToLongArray(resData,false));
- if (nData.length>0) {
- nData.readBytes(resData,0,nData.length);
- }
- trace("---->"+nData.length);
- return resData;
- resData.clear();
- }
- private static function LongArrayToByteArray(data : Array, includeLength : Boolean):ByteArray {
- var length:uint=data.length;
- var n : uint = (length - 1) << 2;
- if (includeLength) {
- var m:uint=data[length-1];
- if ((m < n - 3) || (m > n)) {
- return null;
- }
- n=m;
- }
- var result : ByteArray = new ByteArray();
- result.endian=Endian.LITTLE_ENDIAN;
- for (var i : uint = 0; i < length; i++) {
- result.writeUnsignedInt(data[i]);
- }
- if (includeLength) {
- result.length=n;
- return result;
- } else {
- return result;
- }
- }
- private static function ByteArrayToLongArray(data : ByteArray, includeLength : Boolean):Array {
- var length:uint=data.length;
- var n:uint=length>>2;
- if (length%4>0) {
- n++;
- data.length += (4 - (length % 4));
- }
- data.endian=Endian.LITTLE_ENDIAN;
- data.position=0;
- var result:Array=[];
- for (var i : uint = 0; i < n; i++) {
- result[i]=data.readUnsignedInt();
- }
- if (includeLength) {
- result[n]=length;
- }
- data.length=length;
- return result;
- }
- private static function encrypt(data:ByteArray, key:ByteArray):ByteArray {
- if (data.length==0) {
- return new ByteArray();
- }
- var v:Array=ByteArrayToLongArray(data,false);
- var k:Array=[987395361,3689143219,1656178945,2781276885];
- if (k.length<4) {
- k.length=4;
- }
- var n:uint=v.length-1;
- var y:uint=v[0];
- var z:uint=v[1];
- var a:uint=k[0];
- var b:uint=k[1];
- var c:uint=k[2];
- var d:uint=k[3];
- var delta=0x9E3779B9;/* (sqrt(5)-1)/2*2^32 */
- var sum:uint=0;
- for (var i:uint = 0; i < round; i++) {/* basic cycle start */
- sum+=delta;
- y += ((z<<4) + a) ^ (z + sum) ^ ((z>>>5) + b);
- z += ((y<<4) + c) ^ (y + sum) ^ ((y>>>5) + d);/* end cycle */
- }
- v[0]=y;
- v[1]=z;
- return LongArrayToByteArray(v,false);
- }
- private static function decrypt(data : ByteArray, key : ByteArray):ByteArray {
- if (data.length==0) {
- return new ByteArray();
- }
- var v:Array=ByteArrayToLongArray(data,false);
- var k:Array=[987395361,3689143219,1656178945,2781276885];//密钥写死
- if (k.length<4) {
- k.length=4;
- }
- var n:uint=v.length-1;
- var y:uint=v[0];
- var z:uint=v[1];
- var a:uint=k[0];
- var b:uint=k[1];
- var c:uint=k[2];
- var d:uint=k[3];
- var delta=0x9E3779B9;/* (sqrt(5)-1)/2*2^32 */
- var sum:uint=0xE3779B90;
- if (round==32) {
- sum=0xC6EF3720;//delta << 5
- } else if (round == 16) {
- sum=0xE3779B90;
- }//delta << 4
- for (var i:uint = 0; i < round; i++) {/* basic cycle start */
- z -= ((y << 4) + c) ^ (y + sum) ^ ((y >>>5) + d);
- y -= ((z << 4) + a) ^ (z + sum) ^ ((z >>>5) + b);
- sum-=delta;
- }
- v[0]=y;
- v[1]=z;
- return LongArrayToByteArray(v, false);
- }
- private static function getKey(keyStr:String):Array {
- var key:String=keyStr;
- var arr:Array = new Array();
- var res:Array = new Array();
- var target:Array = new Array();
- arr=key.split(" ");
- var curStr:String="";
- var len:uint=arr.length;
- for (var i:uint=0; i<arr.length; i++) {
- var newnewArr:Array = new Array();
- curStr=arr[i];
- for (var j:uint=0; j<2; j++) {
- var char:String=curStr.charAt(j);
- newArr.push(char);
- }
- target.push(newArr);
- }
- for (i = 0; i < target.length; i++) {
- var a:int=isNumber(target[i][0]);
- var b:int=isNumber(target[i][1]);
- var resNum:int=a*16+b;
- res.push(resNum);
- }
- return res;
- }
- private static function isNumber(char:String):int {
- var arr:Array=["0","1","2","3","4","5","6","7","8","9"];
- for (var i:uint=0; i<arr.length; i++) {
- if (char==arr[i]) {
- return int(char);
- break;
- }
- }
- var id:int=0;
- switch (char) {
- case "A" :
- id=10;
- break;
- case "B" :
- id=11;
- break;
- case "C" :
- id=12;
- break;
- case "D" :
- id=13;
- break;
- case "E" :
- id=14;
- break;
- case "F" :
- id=15;
- break;
- default :
- break;
- }
- return id;
- }
- private static function intToHexChar(index:int):String {
- var hex:Array=['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
- return hex[index];
- }
- private static function intToHexString(arr:Array):String {
- var myStr:String="";
- for (var i:uint=0; i<arr.length; ++i) {
- var t:uint=arr[i];
- var a:uint=Math.floor(t/16);
- var b:uint=Math.floor(t%16);
- myStr+=intToHexChar(a);
- myStr+=intToHexChar(b);
- myStr+=" ";
- }
- return myStr;
- }
- }
热门文章推荐
- [HLS]做自己的m3u8点播系统使用HTTP Live Streaming(HLS技术)
- [FMS]FMS流媒体服务器配置与使用相关的介绍
- [AS3]什么是M3U8,与HTML5的区别是什么
- AS2.0 让flash自适应全屏,并且不自动缩放
- [AS3]as3.0的sound类常用技巧整理
- [AS3]as3与ByteArray详解、ByteArray介绍、ByteArray用法
- 关于RTMP,RTMPT,RTMPS,RTMPE,RTMPTE协议的介绍
- [JS]分享浏览器弹出窗口不被拦截JS示例