一、DES算法
DES全称为Data Encryption Standard,即数据加密标准,是一种使用对称密钥的分组加密算法,它是1972年由美国IBM公司研制的对称密码体制加密算法。
明文按64位进行分组,每次对一个分组进行加密;密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。
二、原理
输入:Plaintext,key
输出:ciphertext
明文按64bit分组,每一分组按下图所示进行加密,输出也是64bit:
右边过来的是每一轮加密所使用的密钥,密钥产生过程具体如下:
这里会产生十六个子密钥,对应十六轮迭代Round。其中,PC-1负责取出由用户提供的56bits密钥(即去除第8,16,24,32,40,48,56,64位),然后按表进行置换,接着将56bits分成左右两半,并分别存到C和D中,将C和D按照移位表LS分别循环左移指定位数,然后合并再进行压缩置换(PC-2),得到一个48位的子密钥。
PC-1表 和 PC-2表 如下:
移位表LS 如下:
一轮迭代具体如下:
其中,
初始置换IP
将64 bit明文的位置进行置换,得到一个乱序的64 bit明文组
而后分成左右两段,每段为32 bit,以L0和R0表示
逆初始置换IP-1
将16轮迭代后给出的64 bit组进行置换,得到输出的密文组。输出为阵中元素按行读得的结果。
选择扩展运算E
功能:将输入的32 bit 扩展成48 bit的输出,即对原第32, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25, 28, 29各位都重复一次,实现数据扩展。将表中数据按行读出得到48 bit输出。
选择压缩运算S
功能:将前面送来的48 bit数据自左至右分成8组,每组为6 bit。而后并行送入8个S盒,每个S盒为一非线性代换网络,有4个输出。
置换运算P(P盒)
功能:对S1至S8盒输出的32 bit数据进行坐标置换
P盒置换
三、加密过程
对于任意长度的明文,DES首先对其进行分组,使得每一组的长度为64位,然后分别对每个64位的明文分组进行加密。
对于每个64位长度的明文分组的加密过程如下:
1)初始置换IP:输入分组按照初始置换表重排次序,进行初始置换。
2)16轮循环:DES对经过初始置换的64位明文进行16轮类似的子加密过程。每一轮的子加密过程要经过DES的f函数,其过程如下:
<1>将64位明文在中间分开,划分为2部分,每部分32位,左半部分记为L,右半部分记为R,以下的操作都是对右半部分数据进行的。
<2>E盒扩展置换:扩展置换将32位的输入数据根据扩展置换表扩展成为48位的输出数据。
<3>异或运算:将48位的明文数据与48位的子密钥进行异或运算
<4> S盒置换:S盒置换是非线性的,48位输入数据根据S盒置换表置换成为32位输出数据。
<5>P盒置换:S盒置换后的32位输出数据根据直接置换表进行直接置换。
<6>经过P盒直接置换的32位输出数据与本轮的L部分进行异或操作,结果作为下 一轮子加密过程的R部分。本轮的R部分直接作为下一轮子加密过程的L部分。然后进入下一轮子加密过程,直到16轮全部完成。
3)终结置换IP-1:按照终结置换表进行终结置换,64位输出就是密文。
其中,在每一轮的子加密过程中,48位的明文数据要与48位的子密钥进行异或运算,
子密钥的产生过程如下:
<1>循环左移:根据循环左移表对C和D进行循环左移。循环左移后的C和D部分作为 下一轮子密钥的输入数据,直到16轮全部完成。
<2>将C和D部分合并成为56位的数据。
<3>压缩型换位pc2:56位的输入数据根据压缩型换位pc2表输出48位的子密钥,这48位的子密钥将与48位的明文数据进行异或操作。
四、解密
DES的解密过程与加密过程完全相同。唯一的不同是,子密钥的使用顺序完全相反。
加密: k1,k2,k3, … , k16
解密:k16, … , k3, k2, k1
五、代码实现
注意:下面代码仅是简单实现了des算法,没有考虑数据的填充,也就是说输入必须是64bit的整数倍
/**
* 功能: des加解密
* 输入:
* 输出:
*@author wangjie
*
*/
public class Des {
//置换IP表
final static int[] IP_Table = new int[]{
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表
final static int[] IPR_Table = new int[]{
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
};
//E位选择表(扩展置换表)
static final int[] E_Table = new int[]{
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换位表(单纯换位表)
final static int[] P_Table = new int[]{
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
};
//PC1选位表(密钥生成置换表1)
final static int[] PC1_Table = new int[]{
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,