- 浏览: 178135 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
-
xiangyufangai:
很好很强大膜拜中哈哈!!
VB 两个字符串处理函数(类似Left/Mid/Right/Split的结合) -
hellohank:
这个……叫摘要算法,不叫加密算法~
Java实现的加密工具类(支持MD5和SHA) -
NIUCH1029291561:
接口有问题奥
网银在线支付接口和应用 -
yeuego:
能幫你就行了
MySQL索引分析 -
ForgiDaved:
很给力的介绍。记得前段时间给一个系统加功能,设计的表没有 ...
MySQL索引分析
如果对技术有兴趣的,以下这编值得看看起来
DES加密算法
DES是一种相对”古老”的算法,在上个世纪70年代由IBM开发完成。在1976年被美国政府采用,并于1977年作为非机要部门的数据加密标准而公布。DES是一种单密钥对称加解密算法。
DES算法流程
DES是一个分组加密算法,利用一个64位的密钥对64位的数据进行加密,输出64位的密文,64位的密钥当中,每一个字节的第8位作为奇偶校验位而忽略,所以实际上的密钥是56位,DES算法的步骤如下:
初始明文X经过初始IP置换表得到IP(X), 把IP(X)分为两部分(L0,R0),经过16轮置换,XOR和替换操作后,通过逆IP置换表生成密文,公式如下:
Ln = R(n-1)
Rn = L(n-1) + f (R(n-1),Kn)
+号表示XOR异或操作。Kn为密钥分组。整个加密流程见下图
生成子密钥
K1-K16是由64位密钥经过16轮的循环移位生成的16组子密钥。
设密钥K(64位)= 01100011 01101111 01101101 01110000 01110101 01110100 01100101 01110010(大家经过8421码算一下,转换成16进制就是63 6F 6D 70 75 74 65 72,其实就是字符串computer)。注意红色标识的为奇偶校验位,实际密钥位56位。
对K使用PC-1表进行置换:
得出K+ (56位)= 00000000 11111111 11111111 10111000 00110111 01100000 01101000
把K+均分为两部分,那么
C0 = 00000000 11111111 11111111 1011 ,
D0 = 1000 00110111 01100000 01101000
然后开始根据移位常数表进行16轮移位,第1,2,9,16轮循环左移1位,其他左移2位。
那么
C1 = C0 循环左移1位 = 0000 0001 1111 1111 1111 1111 0110
D1 = C1 循环左移1位 = 0000 0110 1110 1100 0000 1101 0001
C2 = C1 循环左移1位 = 0000 0011 1111 1111 1111 1110 1100
D2 = C2 循环左移1位 = 0000 1101 1101 1000 0001 1010 0010
…….
C16 = C15 循环左移1位 = 0000 0000 1111 1111 1111 1111 1011
D16 = D15 循环左移1位 = 1000 0011 0111 0110 0000 0110 1000
C(n) + D(n) = K(n), 对Kn使用PC-2表进行置换,得出16组子密钥(48位1组)
K1 = 11110000 10111110 11101110 11010000 00000111 10011000
……
K16 = 11110001 10111110 00101110 00000001 10000010 01011110
加密过程
初始置换
设明文M(64位) = 01110100 01100101 01110011 01110100 00100000 01100100 01100101 01110011(就是字符串test des)
对明文M使用IP表进行置换
IP = 11101111 10001101 01101011 11000110 00000000 11111111 00000000 10000100
进而
L0 = 11101111 10001101 01101011 11000110
R0 = 00000000 11111111 00000000 10000100
16轮变换
从L0,R0开始 循环16次,使用上文的公式
Ln = R(n-1)
Rn = L(n-1) + f (R(n-1),Kn)
得出L1R1-L16R16, 函数f从一个32位的数据块和一个48位的子密钥Kn得到一个新的32位数据块(算法稍后详细介绍) 最终得出
L16 = 11000000 10110011 00110001 10001011
R16 = 10101110 10111011 11100010 10110010
对R16L16(64位)使用IP-1表进行逆置换,得出密文:
00111010 01110111 01000000 01010010 00111001 01111101 10000100 11110111
最终我们从明文M = 74 65 73 74 20 64 65 73
得出密文 C = 3A 77 40 52 39 7D 84 F7
DES的加密与解密使用相同的算法,把密钥的使用顺序颠倒即可。
下面开始正式的编码
使用FD创建一个空项目,新建一个名为DES的类,方便起见我们把DES设成单件类,
第一步把我们上面所讲到的一些表编码进类里面
代码:
package
{
/**
* ...
* @author bardpub
*/
public class DES
{
private static var _instance:DES;
// 置换选择表一 (PC-1)
public static var bSelSwapTable_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)
public static var bSelSwapTable_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
] ;
// 初始置换表 (IP)
public static var bInitSwapTable: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)
public static var bInitReSwapTable: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
] ;
// 位扩展表32-->48 (E)
public static var bBitExternTable: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
] ;
// 32位置换表--用于F的尾置换 (P)
public static var bTailSwapTable: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
] ;
//8个S盒
public static var SB:Array = [
[
14, 4, 13, 1, 1, 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
],
[
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
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, 13, 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 function DES()
{
}
public static function getInstance():DES
{
if (_instance == null)
_instance = new DES();
return _instance;
}
}
}
然后声明几个变量,用来存储有关内容,
代码:
private var _bKey:ByteArray; //原始KEY (64 bit)
private var _bSubKey:ByteArray; //新的子KEY ( 16 * 48 bit)
private var _bOrigMsg:ByteArray; //初始明文
private var _lMsg:ByteArray; //保存(L0-L16)
private var _rMsg:ByteArray; //保存R0-R16
private var _bCryptedMsg:ByteArray; //保存密文
在DES的构造函数中初始化这些变量:
代码:
_bKey = new ByteArray();
_bKey.length = 8;
_bSubKey = new ByteArray();
_bSubKey.length = 96;
_bOrigMsg = new ByteArray();
_bOrigMsg.length = 8;
_bCryptedMsg = new ByteArray();
_bCryptedMsg.length = 8;
_lMsg = new ByteArray();
_rMsg = new ByteArray();
_lMsg.length = _rMsg.length = 68;
ByteArray是以字节位单位存储内容的,所以我们存储64位的数据块只需要长度为8的ByteArray对象,_bSubKey中我们要存储K1-K16的内容 ,每一个子密钥的位数是48位,6字节.因此需要6 * 16的长度。 _lMsg,_rMsg同理存储L0-L16,R0-R16 L为32位4字节,因此需要4 * 17 = 68字节长度来存储。 因为加密算法中都是以位为单位操作的,AS中没有直接操作位的语法(其实绝大多数语言都没有) 因此我们需要按位运算符来帮忙了。
这些东西对系统学过计算机的同学来说很容易了,如果是半路出家的可能平时没怎么接触过这些。因此我说得稍微啰嗦一点。
var b:ByteArray = new ByteArray();
b.writeByte(0);
这时b的内容用2进制表示就是:00000000 要想把某一位设为1需要使用 |(按位或运算符),它对操作数中相应的位进行或运算。如果两个对应的位中有一个是1,结果位就是1。如果两个位都是0,结果就是0
00000000 | 10000000 = 01000000
也就是 b | 0x80 = 10000000
同理 b | 0x40 = 01000000
b | 0x20 = 00100000
b | 0x10 = 00010000
b | 0x8 = 00001000
b | 0x4 = 00000100
b | 0x2 = 00000010
b | 0x1 = 00000001
再说一个小技巧 16进制与2进制的转换,以前我的老师把它称为8421码,一个2进制数转换为16进制 每4位转换为一个16进制数 从高到底第一位是如果该位上是1那么数值就是8 第2位是4 第3位是2 第4位是1, 把他们相加就是16进制的表示, 如2进制数01001010 每4位一组 0100 1010
0 + 4 + 0 + 0 = 4 ;8 + 0 + 2 +0 = 10(A) 16进制数就是4A。
如果要把某位上设为0需要使用& (按位与运算符) 它对操作数中相应的位进行与运算。如果相应的位都是1,结果位就是1,否则就是0。
设b = 11101000 , b & 0111111 = 0x01101000, 这个01111111怎么来的呢 把10000000取反就行了,10000000 16进制是0x80 ,那么~0x80 = 01111111; ~是取反运算符,可以反转操作数中的位,即1变成0,0变成1。
为了方便后面的操作 我们把0x80,0x40等等定义成DES类的一个属性数组:
//方便位操作的掩码
public static const BITMASK:Array = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 ];
定义setter方法来添加密钥与明文
代码:
/**
* 设置初始密钥
*/
public function set bKey(value:ByteArray):void
{
if (value.length < 8)
{
throw new Error("密钥必须为64位");
return;
}
for (var i:int = 0; i < 8; i++ )
{
_bKey[i] = value[i];
}
}
/**
* 设置初始明文
*/
public function set bOrigMsg(value:ByteArray):void
{
if (value.length < 8)
{
throw new Error("明文必须为64位");
return;
}
for (var i:int = 0; i < 8; i++ )
{
_bOrigMsg[i] = value[i];
}
}
如果输入的密钥长度小于64位则抛出错误,否则把密钥的内容复制到_bKey中。
定义一个辅助方法byteArraySet(byte, value:int),用来把byteArray对象的内容设为value
代码:
/**
* 把ByteArray对象的内容设为指定值
* @param value
*/
public function byteArraySet(byteArray:ByteArray, value:int):void
{
byteArray.position = 0;
for (var i:int = 0, len:int = byteArray.length; i < len; i++ )
{
byteArray.writeByte(value);
}
}
定义一个genSubKey方法用来生成子密钥: public function genSubKey():void {};
首先我们把_bSubKey的内容清空,
byteArraySet(_bSubKey, 0);
然后对初始密钥使用PC-1表进行置换,定义一个bTemp的byteArray对象来存储置换后的内容,
置换思路是这样的:依次检查_bKey中的PC-1表中索引的位,如果该位为1,则把bTemp中当前次数的位设为1,否则不做任何操作(因为我们初始化bTemp的时候,bTemp内容全部为0)。那么如何检查_bKey中指定的位是否为1呢?我们使用&(按位与运算符),这是按位与运算符,它对操作数中相应的位进行与运算。如果相应的位都是1,结果位就是1,否则就是0。
如果我们要检查0010 0001块中第3位是否为1,那么0010 0001 & 0010 0000结果为0010 0000,结果不为0表示0010 0001第3位是1,否则就是0。
这样我们需要检查_bKey中第10位是否为1那么 _bKey[int((10-1)/8)] & 0100 0000就是结果了(bKey中的元素是以字节为单位的,第10位那就处在第2个字节中的第2位,也就是_bKey[1]中的第2位,那么_bKey[1] & 0x40的结果如果不为0那么_bkey的第10位就是1,否则就是0。
代码:
var byteIndex:int, bitIndex:int, bTemp:ByteArray;
bTemp = new ByteArray();
bTemp.length = 7;
//置换选择1,对初始密钥使用PC-1置换
for (var i:int = 0; i < 56; i++ )
{
byteIndex = (bSelSwapTable_1[i] - 1) / 8;
bitIndex = 7 - (bSelSwapTable_1[i] - 1) % 8;
if (_bKey[byteIndex] & BITMASK[bitIndex])
{
bTemp[int(i / 8)] |= BITMASK[7 - i % 8];
}
}
byteIndex = (bSelSwapTable_1[i] - 1) / 8; 取得当前要检查的位在_bkey中的索引位置。
bitIndex = 7 - (bSelSwapTable_1[i] - 1) % 8; 取得当前要检查的为在_bkey中某索引的第几个位置
if (_bKey[byteIndex] & BITMASK[bitIndex])
如果当前位不为1,那么把bTemp中当前位设为1:
bTemp[int(i / 8)] |= BITMASK[7 - i % 8];
然后要经过16轮变换产生子密钥
先定一个bTempkey用来存储每轮变化时产生的值
代码:
var tmpLen:int = 0;
//经过16轮变换产生子密钥
for (var iTurn:int = 1; iTurn <= 16; iTurn++ )
{
var bShiftBit:int = 2;
if (iTurn == 1 || iTurn == 2 || iTurn == 9 || iTurn == 16)
{
bShiftBit = 1;
}
tmpLen = bShiftBit + 28;
//循环移位
for (i = bShiftBit; i < tmpLen; i++ )
{
//生成C(n)
if (bTemp[int(i % 28 / 8)] & BITMASK[7 - (i % 28) % 8])
{
bTempKey[int((i - bShiftBit) / 8)] |= BITMASK[7 - (i - bShiftBit) % 8];
}
//生成D(n)
if (bTemp[int((i % 28 + 28) / 8)] & BITMASK[7 - (i % 28 + 28) % 8])
{
bTempKey[int((i + 28 - bShiftBit) / 8)] |= BITMASK[7 - (i + 28 - bShiftBit) % 8];
}
}
//置换2
for (i = 0; i < 48; i++ )
{
byteIndex = (bSelSwapTable_2[i] - 1) / 8;
bitIndex = 7 - (bSelSwapTable_2[i] - 1) % 8;
if (bTempKey[byteIndex] & BITMASK[bitIndex])
{
_bSubKey[int(i / 8) + (iTurn - 1) * 6] |= BITMASK[7 - (i % 8)];
}
}
byteArrayCpy(bTemp, bTempKey);
byteArraySet(bTempKey, 0);
}
首先按当前的轮数得到是左移一位还是两位
代码:
var bShiftBit:int = 2;
if (iTurn == 1 || iTurn == 2 || iTurn == 9 || iTurn == 16)
{
bShiftBit = 1;
}
然后把bTemp分为Cn Dn(28位)进行循环,把结果存在bTempkey中,循环28次,如果移位数是1那么依次取出bTemp的2-3-4-5…28-1位的值设为bTempkey的1-28位的值, Dn就是Cn的基础上+上28就是了
代码:
tmpLen = bShiftBit + 28;
//循环移位
for (i = bShiftBit; i < tmpLen; i++ )
{
//生成C(n)
if (bTemp[int(i % 28 / 8)] & BITMASK[7 - (i % 28) % 8])
{
bTempKey[int((i - bShiftBit) / 8)] |= BITMASK[7 - (i - bShiftBit) % 8];
}
//生成D(n)
if (bTemp[int((i % 28 + 28) / 8)] & BITMASK[7 - (i % 28 + 28) % 8])
{
bTempKey[int((i + 28 - bShiftBit) / 8)] |= BITMASK[7 - (i + 28 - bShiftBit) % 8];
}
}
然后把CnDn用PC-2表进行置换 存储在_bSubKey中
代码:
//置换2
for (i = 0; i < 48; i++ )
{
byteIndex = (bSelSwapTable_2[i] - 1) / 8;
bitIndex = 7 - (bSelSwapTable_2[i] - 1) % 8;
if (bTempKey[byteIndex] & BITMASK[bitIndex])
{
_bSubKey[int(i / 8) + (iTurn - 1) * 6] |= BITMASK[7 - (i % 8)];
}
}
最后把bTempKey的值复制到bTemp中, 把bTemp的值清空,开始新一轮的循环
代码:
byteArrayCpy(bTemp, bTempKey);
byteArraySet(bTempKey, 0);
新建一个initSwap方法对明文进行初始置换
代码:
/**
* 根据IP表对明文M进行初始置换
*/
public function initSwap():void
{
byteArraySet(_lMsg, 0);
byteArraySet(_rMsg, 0);
var byteIndex:int, bitIndex:int;
for (var i:int = 0; i < 32; i++ )
{
byteIndex = (bInitSwapTable[i] - 1) / 8;
bitIndex = 7 - (bInitSwapTable[i] - 1) % 8;
if (_bOrigMsg[byteIndex] & BITMASK[bitIndex])
{
_lMsg[ int(i / 8)] |= BITMASK[7 - (i % 8)];
}
byteIndex = (bInitSwapTable[i+32] - 1) / 8;
bitIndex = 7 - (bInitSwapTable[i + 32] - 1) % 8;
if (_bOrigMsg[byteIndex] & BITMASK[bitIndex])
{
_rMsg[ int(i / 8)] |= BITMASK[7 - (i % 8)];
}
}
}
思路跟前面置换密钥是一样的,就不多说了.
新建一个singleTurn方法进行单轮转换
代码:
/**
* 单轮加密
* @param iTurn
* @param mode
*/
public function singleTurn(iTurn:int, mode:Boolean):void
{
//L(n) = R(n-1)
for (var i:int = 0; i < 4; i++ )
{
_lMsg[i + iTurn * 4] = _rMsg[i + (iTurn - 1) * 4];
}
F(iTurn, mode);
for (i = 0; i < 4; i++ )
{
_rMsg[i + iTurn * 4] ^= _lMsg[i + (iTurn - 1) * 4];
}
}
//L(n) = R(n-1)
for (var i:int = 0; i < 4; i++ )
{
_lMsg[i + iTurn * 4] = _rMsg[i + (iTurn - 1) * 4];
}
把Rn-1的值复制到Ln中(Ln存储在_Lmsg[n] 到_lmsg[n+4]中, Rn同样);
然后使用F函数对R(n-1)与Kn进行处理.F函数稍后讲解
F(iTurn, mode);
最后确定Rn的值(与Ln-1进行XOR操作)
for (var i:int = 0; i < 4; i++ )
{
_lMsg[i + iTurn * 4] = _rMsg[i + (iTurn - 1) * 4];
}
DES算法的关键部分就是F函数的实现,F函数输入的是右部的32位,首先通过扩展置换表,把32位扩展为48位,使他与子密钥长度相同,然后与子密钥进行XOR操作,再经过S盒处理,最后经过尾置换输出.
S盒的作用是把48位变成通过非线性转换为32位输出,总用有8个S盒,每一个S盒的作用是把6位变成4位输出,其中第1位和第6位组合作为行索引值,中间4位组合作为列索引值,例如对S盒输入的是101110,于是行索引=10(2进制)=2,列索引=0111(2进制) = 7, S1(2,7)=11 = 1011(2进制),经过S盒之后还有一个尾置换.
代码:
/**
* F函数
* @param iTurn 转换轮数
* @param mode 方式(加密OR解密)
*/
public function F(iTurn:int , mode:Boolean):void
{
var bTemp:ByteArray = new ByteArray();
bTemp.length = 6;
var C:ByteArray = new ByteArray();
C.length = 4;
var byteIndex:int, bitIndex:int;
//R --> E(R) 保存在bTemp中
for (var i:int = 0; i < 48; i++ )
{
byteIndex = (bBitExternTable[i] - 1) / 8;
bitIndex = 7 - (bBitExternTable[i] - 1) % 8;
if (_rMsg[byteIndex + (iTurn - 1) * 4] & BITMASK[bitIndex])
{
bTemp[int(i / 8)] |= BITMASK[7 - i % 8];
}
}
//E(R) --> K 保存在bTemp中
for (i = 0; i < 6; i++ )
{
if (mode)
{
bTemp[i] ^= _bSubKey[(iTurn - 1) * 6 + i];
}
else
{
bTemp[i] ^= _bSubKey[96 - iTurn * 6 + i];
}
}
var bStartPos:int = 0, bTarPos:int = 0;
var bRowIndex:int = 0, bColIndex:int = 0 ; //保存行数与列数
for (var bBoxIndex:int = 0; bBoxIndex < 8; bBoxIndex ++ )
{
// 确定行值
if ( bTemp[int(bStartPos / 8)] & BITMASK[(~bStartPos) & 7] )
{
bColIndex += 2 ;
}
if ( bTemp[int((bStartPos + 5) / 8)] & BITMASK[(~(bStartPos + 5)) & 7] )
{
bColIndex += 1 ;
}
// 确定列值
if ( bTemp[int((bStartPos+1)/8)] & BITMASK[(~(bStartPos+1))&7] )
bRowIndex += 8 ;
if ( bTemp[int((bStartPos+2)/8)] & BITMASK[(~(bStartPos+2))&7] )
bRowIndex += 4 ;
if ( bTemp[int((bStartPos+3)/8)] & BITMASK[(~(bStartPos+3))&7] )
bRowIndex += 2 ;
if ( bTemp[int((bStartPos+4)/8)] & BITMASK[(~(bStartPos+4))&7] )
bRowIndex += 1 ;
// 取出S(i)盒中由上面行列所对应的值bTarValue
var bTarValue:int = SB[bBoxIndex][bColIndex * 16 + bRowIndex];
// 把bTarValue转化成对应的C(i)
if ( bTarValue >= 8 )
{
C[int(bTarPos/8)] |= BITMASK[(~bTarPos)&7] ;
bTarValue -= 8 ;
}
if ( bTarValue >= 4 )
{
C[int((bTarPos+1)/8)] |= BITMASK[(~(bTarPos+1))&7] ;
bTarValue -= 4 ;
}
if ( bTarValue >= 2 )
{
C[int((bTarPos+2)/8)] |= BITMASK[(~(bTarPos+2))&7] ;
bTarValue -= 2 ;
}
if ( bTarValue >= 1 )
{
C[int((bTarPos+3)/8)] |= BITMASK[(~(bTarPos+3))&7] ;
bTarValue -= 1 ;
}
bRowIndex = bColIndex = 0 ;
bStartPos += 6 ;
bTarPos += 4 ;
}
// 尾置换
for ( i = 0; i < 32; i++ )
{
if ( C[int((bTailSwapTable[i]-1)/8)] & BITMASK[(~(bTailSwapTable[i]-1))&7] )
_rMsg[iTurn * 4 + int(i /8)] |= BITMASK[(~i)&7] ;
else
_rMsg[iTurn * 4 + int(i /8)] &= ( ~(BITMASK[(~i)&7]) );
}
}
}
注意到这里常出现的BITMASK[(~(i))&7], 它其实就是BITMASK[7 - (i % 8)];因为位操作要比加减乘除要快得多,你可以把前面的操作都这样改过来,还有一个可以优化的地方就是int(i / 8)
可以改为 i >> 3;
最后创建一个函数initReSwap进行逆置换,生成密文
复制内容到剪贴板
代码:
/**
* 初始逆置换
*/
public function initReSwap():void
{
byteArraySet(_bCryptedMsg, 0);
for ( var i:int = 0; i < 64; i++ )
{
if (bInitReSwapTable[i] <= 32)
{
if (_rMsg[64 + int((bInitReSwapTable[i] - 1) / 8)] &
BITMASK[(~(bInitReSwapTable[i] - 1)) & 7])
{
_bCryptedMsg[int(i / 8)] |= BITMASK[(~i) & 7];
}
else
{
_bCryptedMsg[int(i / 8)] &= ( ~(BITMASK[(~i)&7]) ) ;
}
}
else
{
if (_lMsg[64 + int((bInitReSwapTable[i] - 1 - 32) / 8)] &
BITMASK[(~(bInitReSwapTable[i] - 32 - 1)) & 7])
{
_bCryptedMsg[int(i / 8)] |= BITMASK[(~i) & 7];
}
else
{
_bCryptedMsg[int(i / 8)] &= ( ~(BITMASK[(~i)&7]) ) ;
}
}
}
}
}
最终我们的DES加密类就完成了,记得给¬_ bCryptedMsg设置一个getter
加密的时候对明文以64位进行分组,不足64的0补齐
发表评论
-
3d加载人物
2011-03-09 13:35 1172package { import caurin ... -
Dragon-Studio 之 Flash Alternativa 3D引擎 基础教程
2011-03-09 13:34 980欢饮大家来到Dragon的 ... -
Flash 3D引擎比较
2011-03-09 13:33 1140最近做的一个项目中需要用到 3D,所以粗略的学习了一些目前Fl ... -
基于Flash的3D引擎-Alternativa3D
2011-03-09 10:03 1539Alternativa3D 是由 Altenativa ... -
Flash 3D引擎比较
2011-03-02 00:49 875http://blog.sina.com.cn/s/blog_ ... -
3角函数转化函数整理
2011-03-02 00:42 629先发一不分//有空再补全~~class Math2 { var ... -
ActionScript 3.0 基础之以文本形式、XML形式和JSON形式与ASP.NET通信
2011-03-02 00:26 1169介绍Flash ActionScript 3.0 以文本形式与 ... -
AS3的A寻路代码,了解一下
2011-03-02 00:01 963地形数据不属于A*寻路 ... -
AS3.0的加载机制
2011-03-01 23:44 1157还是坚持自己的原则,从 ... -
As3.0 xml + Loader
2011-03-01 23:43 990上面的地址是曾经也就是刚刚过去的一个月前学习AS2.0的时 ... -
AS3.0 styleSheet
2011-03-01 23:41 1787styleSheet和TextFormat类似,也是用来定义文 ... -
Flash Socket通信的安全策略问题
2011-02-27 23:38 818收录一下先,确实解决了问题。 将flash发布为htm ... -
纯AS代码实现可预览本地图片的flash上传客户端(AS3)
2011-02-15 22:30 862需要Flash Player 10+版本的支持,原理就是主要利 ... -
Flash 3D引擎比较
2011-02-15 21:27 1186转载此文目的是让喜爱研究Flash 3D的朋友能有个大致了解, ... -
AS3.0 styleSheet
2011-02-15 17:33 1551Flash Player 支持原 CSS1 规范 (www.w ...
相关推荐
《CryptoDemo--Flex(AS 3.0)加密算法工具详解》 在现代软件开发中,数据安全至关重要,尤其是在网络传输和存储时。对于使用Adobe Flex进行开发的项目,加密技术成为了保护敏感信息的关键手段。本文将深入探讨...
总的来说,AS3.0中的MD5加密例子展示了如何在Flash环境中实现数据的安全处理,尽管MD5在现代密码学中已经不再理想,但它在一些旧系统中仍然存在,了解其工作原理和使用方法对理解和维护这些系统至关重要。
"Crypto"是一个专门为AS3设计的加密类库,它提供了一系列强大的加密算法,帮助开发者实现数据的安全传输和存储。 1. **加密基础知识**:加密是将可读信息转化为不可读信息的过程,目的是保护数据不被未经授权的用户...
qt 一个基于Qt Creator(qt,C++)实现中国象棋人机对战.
热带雨林自驾游自然奇观探索
冰川湖自驾游冰雪交融景象
C51 单片机数码管使用 Keil项目C语言源码
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
前端分析-2023071100789s12
Laz_制作了一些窗体和对话框样式.7z
1、文件内容:ocaml-docs-4.05.0-6.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ocaml-docs-4.05.0-6.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
学习笔记-沁恒第六讲-米醋
工业机器人技术讲解【36页】
内容概要:本文档详细介绍了在 CentOS 7 上利用 Docker 容器化环境来部署和配置 Elasticsearch 数据库的过程。首先概述了 Elasticsearch 的特点及其主要应用场景如全文检索、日志和数据分析等,并强调了其分布式架构带来的高性能与可扩展性。之后针对具体的安装流程进行了讲解,涉及创建所需的工作目录,准备docker-compose.yml文件以及通过docker-compose工具自动化完成镜像下载和服务启动的一系列命令;同时对可能出现的问题提供了应对策略并附带解决了分词功能出现的问题。 适合人群:从事IT运维工作的技术人员或对NoSQL数据库感兴趣的开发者。 使用场景及目标:该教程旨在帮助读者掌握如何在一个Linux系统中使用现代化的应用交付方式搭建企业级搜索引擎解决方案,特别适用于希望深入了解Elastic Stack生态体系的个人研究与团队项目实践中。 阅读建议:建议按照文中给出的具体步骤进行实验验证,尤其是要注意调整相关参数配置适配自身环境。对于初次接触此话题的朋友来说,应该提前熟悉一下Linux操作系统的基础命令行知识和Docker的相关基础知识
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
网络小说的类型创新、情节设计与角色塑造
毕业设计_基于springboot+vue开发的学生考勤管理系统【源码+sql+可运行】【50311】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - 业务管理:班级信息、学生信息、课程信息、考勤记录、假期信息、公告信息 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
内容概要:本文介绍了使用 Matlab 实现基于 BO(贝叶斯优化)的 Transformer 结合 GRU 门控循环单元时间序列预测的具体项目案例。文章首先介绍了时间序列预测的重要性及其现有方法存在的限制,随后深入阐述了该项目的目标、挑战与特色。重点描述了项目中采用的技术手段——结合 Transformer 和 GRU 模型的优点,通过贝叶斯优化进行超参数调整。文中给出了模型的具体实现步骤、代码示例以及完整的项目流程。同时强调了数据预处理、特征提取、窗口化分割、超参数搜索等关键技术点,并讨论了系统的设计部署细节、可视化界面制作等内容。 适合人群:具有一定机器学习基础,尤其是熟悉时间序列预测与深度学习的科研工作者或从业者。 使用场景及目标:适用于金融、医疗、能源等多个行业的高精度时间序列预测。该模型可通过捕捉长时间跨度下的复杂模式,提供更为精准的趋势预判,辅助相关机构作出合理的前瞻规划。 其他说明:此项目还涵盖了从数据采集到模型发布的全流程讲解,以及GUI图形用户界面的设计实现,有助于用户友好性提升和技术应用落地。此外,文档包含了详尽的操作指南和丰富的附录资料,包括完整的程序清单、性能评价指标等,便于读者动手实践。