actionscript DES 加密 解密 (AES,其他加密)

时间:2021-01-04 18:58:48

找了半天其实都没找到什么好的DES加密代码。

难怪有一个博主说,他找了半天没找到自己实现了一个。http://www.iteye.com/topic/422575

但貌似他自己都说加密大的明文会出错,所以我就不敢试用了。

另外,在天地会下载了一个,发现功能还是能达到的,貌似是把js版转过来的。但是加密的速度非常的低,应该是实现的问题。比我在一个外国佬微博找到的AES加密代码还要慢十几倍。

(!!!补充,最后发现还是外国佬写好的那个Crypto库( http://code.google.com/p/as3crypto/ )最好,虽然用起来很麻烦。见文章最后。)

不过,无论怎么说,都值得称赞,在这里分享一下代码。

package crypto
{
	import flash.display.Sprite;
	import flash.events.EventDispatcher;
	import flash.events.ProgressEvent;
	import flash.utils.ByteArray;

	/**
	 * Des加密
	 * 
	 * @author 闪闪小巴依
	 */
	public class DES
	{
		//IP变换,用于打乱64位明文
		private const IP:Array = [
			58,50,42,34,26,18,10,2,
			60,52,44,36,28,20,12,4,
			62,54,46,38,30,22,14,6, 
			64,56,48,40,32,24,16,8,
			57,49,41,33,25,17,9,1, 
			59,51,43,35,27,19,11,3,
			61,53,45,37,29,21,13,5,
			63,55,47,39,31,23,15,7
		];
		//IP-1变换,用户输出64位密文
		private const IP_1:Array = [
			40,8,48,16,56,24,64,32,
			39,7,47,15,55,23,63,31,
			38,6,46,14,54,22,62,30, 
			37,5,45,13,53,21,61,29, 
			36,4,44,12,52,20,60,28, 
			35,3,43,11,51,19,59,27, 
			34,2,42,10,50,18,58,26, 
			33,1,41,9,49,17,57,25			
		];
		//PC_1变换
		private const PC_1:Array = [
			57,49,41,33,25,17,9, 
			1,58,50,42,34,26,18, 
			10,2,59,51,43,35,27,
			19,11,3,60,52,44,36,
			63,55,47,39,31,23,15, 
			7,62,54,46,38,30,22, 
			14,6,61,53,45,37,29, 
			21,13,5,28,20,12,4
		];
		//PC_2变换
		private const PC_2:Array = [
			14,17,11,24,1,5,3, 
			28,15,6,21,10,23,19, 
			12,4,26,8,16,7,27,
			20,13,2,41,52,31,
			37,47,55,30,40,51,45,
			33,48,44,49,39,56,34,
			53,46,42,50,36,29,32

		];
		//E变换,将32位膨胀为48位
		private const E:Array = [
			32,1,2,3,4,5,
			4,5,6,7,8,9, 
			8,9,10,11,12,13, 
			12,13,14,15,16,17, 
			16,17,18,19,20,21,
			20,21,22,23,24,25, 
			24,25,26,27,28,29, 
			28,29,30,31,32,1

		];
		//P变换,将膨胀后的压缩回32位
		private static var P:Array = [
			16,7,20,21, 
			29,12,28,17, 
			1,15,23,26, 
			5,18,31,10, 
			2,8,24,14, 
			32,27,3,9, 
			19,13,30,6, 
			22,11,4,25
		];
		private const sbox:Array = [
			[
				[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
				[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
				[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 ],
				[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
			],
			[
				[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
				[ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
				[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
				[ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
			],
			[
				[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
				[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
				[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
				[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ]
			],
			[
				[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ],
				[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 ],
				[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
				[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
			],
			[
				[ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
				[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 ],
				[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
				[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
			],
			[
				[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
				[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
				[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
				[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 ]
			],
			[
				[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ],
				[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
				[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 ],
				[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 ]
			],
			[
				[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
				[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
				[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
				[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
			]
		];
		public const leftMoveStep:Array = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1];
		private var key:ByteArray;
		private var key_i:Array;
		public function DES(key:ByteArray)
		{
			this.key = key;
			if(this.key.length != 8){
				throw new Error("key 错误");
			}else{
				var keyArray:Array = new Array();
				for(var i:int = 0;i<8;i++){
					var ts:Array = this.D2B(this.key[i]);
					for(var j:int = 0;j<8;j++){
						keyArray.push(ts[j]);
					}
				}
				//trace(keyArray);
				this.key_i = this.getKeys(keyArray);
				for(var m:int = 0;m<key_i.length;m++){
					//trace("key"+m+":"+key_i[m]);
				}
				//trace(this.key_i)
				//trace(this.key_i);
			}
		}
		public function encrypt(source:ByteArray):ByteArray{
			var ret:ByteArray = new ByteArray();
			var filledSource:ByteArray = this.fullFill64(source);
			var a:Number = filledSource.length/8;
			var b:Number = filledSource.length%8;
			for(var i:int = 0;i<a;i++){
				var block:Array = new Array();
				for(var m:int = 0;m<8;m++){
					var bytes:Array = this.D2B(filledSource[i*8+m]);
					for(var n:int = 0;n<8;n++){
						block.push(bytes[n]);
					}
				}
				var encryptedBlock:Array = this.encryptUnit(block);
				for(var k:int = 0;k<8;k++){
					var encryptedByte:Array = new Array();
					for(var l:int = 0;l<8;l++){
						encryptedByte.push(encryptedBlock[k*8+l]);
					}
					var encryptedInt:int = this.B2D(encryptedByte);
					ret.writeByte(encryptedInt);
				}
			}
			return ret;
		}
		public function decrypt(source:ByteArray):ByteArray{
			var ret:ByteArray = new ByteArray();
			var a:Number = source.length/8;
			var b:Number = source.length%8;
			for(var i:int = 0;i<a;i++){
				var block:Array = new Array();
				for(var m:int = 0;m<8;m++){
					var bytes:Array = this.D2B(source[i*8+m]);
					for(var n:int = 0;n<8;n++){
						block.push(bytes[n]);
					}
				}
				var decryptedBlock:Array = this.decriptUnit(block);
				for(var k:int = 0;k<8;k++){
					var decryptedByte:Array = new Array();
					for(var l:int = 0;l<8;l++){
						decryptedByte.push(decryptedBlock[k*8+l]);
					}
					var decryptedInt:int = this.B2D(decryptedByte);
					ret.writeByte(decryptedInt);
				}
			}
			ret = this.filterFilled(ret);
			return ret;
		}
		private function encryptUnit(source:Array):Array{
			var ret:Array ;
			var IPRes:Array = this.IPConvort(source);
			//trace("IPRes"+IPRes);
			for(var i:int = 0;i<16;i++){
				this.f(IPRes,i,1);
				//trace("the"+i+"loop");
				//trace(IPRes);
			}
			ret = this.IP_1Convert(IPRes);
			return ret;
		}
		private function decriptUnit(source:Array):Array{
			var ret:Array;
			var IPRes:Array = this.IPConvort(source);
			for(var i:int = 15;i>=0;i--){
				this.f(IPRes,i,0);
			}
			ret = this.IP_1Convert(IPRes);
			return ret;
		}
		public function IPConvort(source:Array):Array{
			var ret:Array = new Array(64);
			for(var i:int = 0;i<ret.length;i++){
				ret[i] = source[IP[i]-1];
			}
			return ret;
		}
		public  function IP_1Convert(source:Array):Array{
			var ret:Array = new Array(64);
			for(var i:int = 0;i<64;i++){
				ret[i] = source[IP_1[i]-1];
			}
			return ret;
		
		}
		public function PC_1Convert(source:Array):Array{
			var ret:Array = new Array(56);
			for(var i:int = 0;i<56;i++){
				ret[i] = source[PC_1[i]-1];
			}
			return ret;
		}
		public function B2D(source:Array):int{
			var ret:int = 0;
			for(var i:int =0;i<source.length;i++){
				ret += source[source.length-1-i]*Math.pow(2,i);
			}
			return ret;
		}
		public function D2B(source:int):Array{
			var ret:Array = new Array();
			var m:int = source;
			var ts:int = 0;
			var n:int = 0;
			do{
				ts = m;
				m = Math.floor(m/2);
				n= ts - m*2;
				ret.push(n);
			}while(m != 0);
			for(m = ret.length;m<8;m++){
				ret.push(0);
			}
			m = Math.floor(ret.length/2);
			for(n = 0;n<m;n++){
				ts = ret[n];
				ret[n] = ret[ret.length-1-n];
				ret[ret.length -1-n] = ts;
			}
			return ret;
		}
		public function getKeys(source:Array):Array{
			var ret:Array = new Array();
			var keyByte:Array = PC_1Convert(source);
			for(var i:int = 0;i<16;i++){
				leftMove(keyByte,leftMoveStep[i]);
				var keyI:Array = new Array(48)
				for(var j:int = 0;j<48;j++){
					keyI[j] = keyByte[PC_2[j]-1];
				}
				ret.push(keyI);
			}
			return ret;
		}
		public function leftMove(source:Array,offset:int):void{
			var ret:Array = new Array(56);
			var c0:Array = new Array(28);
			var d0:Array = new Array(28);
			var c1:Array = new Array(28);
			var d1:Array = new Array(28);
			for(var i:int = 0;i<28;i++){
				c0[i] = source[i];
				d0[i] = source[i+28];
			}
			if(offset == 1){
				for(var i:int = 0;i<27;i++){
					c1[i] = c0[i+1];
					d1[i] = d0[i+1];
				}
				c1[27] = c0[0];
				d1[27] = d0[0];
			}else if(offset == 2){
				for(var i:int = 0;i<26;i++){
					c1[i] = c0[i+2];
					d1[i] = d0[i+2];
				}
				c1[26] = c0[0];
				d1[26] = d0[0];
				c1[27] = c0[1];
				d1[27] = d0[1];
			}
			for(var i:int = 0;i<28;i++){
				source[i] = c1[i];
				source[i+28] = d1[i];
			}
		}
		private function fullFill64(byte:ByteArray):ByteArray{
			var ret:ByteArray = new ByteArray();
			var len:int = byte.length;
			var padlen:int = 8 - (len%8);
			var newlen:int = len+padlen;  
			ret.length = newlen;
			ret.writeBytes(byte,0,byte.length);
			for(var i:int = len;i<newlen;i++){
				ret.writeByte(padlen);
			}
			
			return ret;
		}
		private function filterFilled(byte:ByteArray):ByteArray{
			var ret:ByteArray = new ByteArray();
			var padlen:int = byte[byte.length-1];
			var len:int = byte.length - padlen;
			ret.length = len;
			ret.writeBytes(byte,0,len);
			return ret;
		}
		private function f(source:Array,times:int,flag:int):void{
			var l0:Array = new Array(32);
			var r0:Array = new Array(32);
			var l1:Array = new Array(32);
			var r1:Array = new Array(32);
			var re:Array = new Array(48);
			var s:Array = new Array(8);
			for(var i:int = 0;i<8;i++){
				s[i] = new Array(6);
			}
			var sout:Array = new Array(32);
			var rp:Array = new Array(32);
			
			
			for(var i:int = 0;i<32;i++){
				l0[i] = source[i];
				r0[i] = source[i+32];
			}
			//trace("l0"+l0);
			//trace("r0"+r0);
			for(var i:int = 0;i<48;i++){
				re[i] = r0[E[i]-1];
				re[i] = re[i]+this.key_i[times][i];
				if(re[i] == 2){
					re[i] = 0;
				}
			}
			//var outS:String = "====================\n";
			for(var i:int = 0;i<8;i++){
				for(var j:int = 0;j<6;j++){
					s[i][j] = re[i*6+j];
					//outS += s[i][j];
					//outS += ",";
				}
				//outS +="\n";
				var x:int = s[i][1]*8+s[i][2]*4+s[i][3]*2+s[i][4]*1;
				var y:int = s[i][0]*2+s[i][5]*1;
				var sboxData:int = this.sbox[i][y][x];
				
				//trace("s"+i+": "+sboxData);
				var outB:Array = this.D2B(sboxData);
				for(var j:int = 0;j<4;j++){
					sout[i*4+j] = outB[4+j];
				}
			}
			//outS += "==================";
			//trace(outS);
			for(var i:int = 0;i<32;i++){
				rp[i] = sout[P[i]-1];
				l1[i] = r0[i];
				r1[i] = l0[i];
				r1[i] = l0[i]+rp[i];
				if(r1[i] == 2){
					r1[i] = 0;
				}
				if(((flag==0)&&(times == 0))||((flag==1)&&(times==15))){
					source[i] = r1[i];
					source[i+32] = l1[i];
				}else{
					source[i] = l1[i];
					source[i+32] = r1[i];
				}
			}
			
		}
	}
}

另外,关于AES的加密,可以看http://code.google.com/p/as3crypto/

写了一个DES的封装(因为我只用了DES):大家只需要下载了Crypto库,加入到项目即可使用下边这个类。加密速度很好,180bytes的中文字,只需要300多毫秒加密解密(2.8G双核CPU)

package crypto
{
	import com.hurlant.crypto.Crypto;
	import com.hurlant.crypto.symmetric.AESKey;
	import com.hurlant.util.Hex;
	
	import flash.utils.ByteArray;

	public class Crypto
	{
		private var key:ByteArray = Hex.toArray("abababababababab"); //8 bytes hex num
		
		public function Crypto()
		{
		}
		
		public function encryptByDES(plainText:ByteArray):ByteArray
		{
			var copy:ByteArray = copyArray(plainText);
			Crypto.getCipher("des-ecb", key).encrypt(copy);
			return copy;
		}
		public function decryptByDES(encryptedText:ByteArray):ByteArray
		{
			var copy:ByteArray = copyArray(encryptedText);
			Crypto.getCipher("des-ecb", key).decrypt(copy);
			return copy;
		}
		private function copyArray(origin:ByteArray):ByteArray{
			var copyArray:ByteArray = new ByteArray;
			var pos:int = origin.position;
			origin.position = 0;
			copyArray.writeBytes(origin, 0, origin.length);
			origin.position = pos;
			return copyArray;
		}
	}
}

或者http://code.google.com/p/lostinactionscript/