找了半天其实都没找到什么好的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/