深入理解并实现DES算法
来源:互联网 发布:下载软件管家12345 编辑:程序博客网 时间:2024/05/29 04:36
深入理解并实现DES算法
1. DES简介
- DES算法属于分组加密算法
- 信息按照固定长度进行分组,分组长度为64位
- 混淆和扩散是它采用的两个最重要的安全特性
- 混淆是指通过密码算法使明文和密文以及密钥的关系非常复杂,无法从数学上描述或者统计。
- 扩散是指明文和密钥中的每一位信息的变动,都会影响到密文中许多位信息的变动,从而隐藏统计上的特性,增加密码的安全。
需要注意的地方是掌握DES算法的16轮加、解密流程以及子密钥的产生流程。
2.DES实现大纲
在我的另一篇博客《加密算法之对称加密–DES》已经提到过DES算法的大致过程,整个流程如下图:
为了深入理解整个流程,我们将细化讲解DES算法里十六轮迭代变化中的子密钥生成以及F函数。
3.DES算法之子密钥生成
(1)子密钥生成流程梗概:
(2)子密钥置换选择1(把64位的密钥变为56位长):
假设原密钥为Ks= k1,k2,k3,……,k64
DES算法的实际密钥长度为56,因为64位原密钥每8位的最后一位即第8,16,24,32,40,48,56,64位为校验位。通过如图的置换规则,将实际的56为位密钥选择出来并置乱:
因此置换选择1之后,56位密钥为Ks’ = k1,k2,k3……k56,其中k1 = Ks[57], k2 = Ks[49],k3 = Ks[41],……k56 = Ks[4].
(3)子密钥迭代变换
实际密钥Ks’ = k1,k2,k3……k56
1)分组
将56位实际密钥分为Ci和Di两组,其中:
- Ci = k1,k2,……,k28
- Di = k29,k30,……k56
2)循环移位(左移)
- 移位判断表:
第一列和第三列代表迭代次数,第二列和第四列代表对应的循环左移位数。 - 第1,2,9,16轮迭代时循环左移一位,其余循环左移两位
- 最终得到:
- 循环左移一位:Ci’=k2,k3,……k28,k1;Di’=K30,k31,……k56,k29
- 循环左移两位:Ci’=k3,k4,……k1,k2;Di’=K31,k32,……k29,k30
3)选择置换2
将第2)步得到的Ci’以及Di’拼接起来形成56位密钥Ks” = [Ci’,Di’],
然后进行选择置换2,置换列表如图:
最后得到每一轮迭代所用到的48位子密钥ki = k1,k2,k3,……,k48,其中k1 = Ks”[14], k2 = Ks”[17],……k48 = Ks”[32].
4.DES算法之F函数变换
DES算法第i轮圈变换流程如下图:
根据此图可以得到迭代公式:
并且可以很清晰的看到每一轮迭代所进行的操作,接下来将详细讲一下F函数中的操作
(1)F函数梗概:
(2)E扩展置换
扩展方式:
- 将输入的32比特Ri每4比特为一组分为8块;
- 分别将第m-1块的最右比特和第m+1块的最左比特添到第m块的左边和右边,形成输出的第m个6比特块.
形如:
理解:将1-32位看成一个环,因此第1位前是第32位,第4位后是第5位。。。
(3)异或加密
- 将前一步得到的48位经过扩展序列与每一轮的密钥ki进行按位异或
(4)S盒变换
- 目的:将48位序列压缩为32位序列
过程详解:
- 每6位输入记为B1,B2,B3,B4,B5,B6
- B1B6作为S盒的行号,B2B3B4B5作为S盒的列号
S盒内容
举例
(5)P置换
经过S盒变换的序列最后进行P置换:方式类似于之前的置换方式。
5.DES算法Java实现
public class DES_Key { public static void main(String[] args) { //Scanner input = new Scanner(System.in);// System.out.println("请输入十六进制明文:");// String plaintxt = input.next();// Integer tmpInt = Integer.valueOf(plaintxt,16);// String binary_plain = Integer.toBinaryString(tmpInt);// System.out.println(binary_plain);// System.out.println("请输入十六进制明文密钥:");// String Key = input.next(); String Key = "1234567890ABCDFE"; String binary_Key = hexString2binaryString(Key); System.out.print("binary_Key:"); //0001 0010 0011 0100 0101 0110 0111 1000 1001 0000 1010 1011 1100 1101 1111 1110 System.out.println(binary_Key); ArrayList<char[]> resultKi = new ArrayList<char[]>();//存放16个Ki GenerateKey(binary_Key,resultKi); Iterator<char[]> it = resultKi.iterator(); int KiIndex = 0; while(it.hasNext()){ char []temp = (char[]) it.next(); System.out.print("第"+(KiIndex+1)+"轮密钥:"); System.out.println(temp); KiIndex++; } String Plain = "1111111111111110"; String binary_Plain = hexString2binaryString(Plain); System.out.print("binary_Plain:"); System.out.println(binary_Plain); char[] DESEncrypt = EncryptCircleTrans(binary_Plain, resultKi); System.out.print("DES加密结果:"); System.out.println(DESEncrypt); char[] DESDecrypt = DecryptCircleTrans(ToString(DESEncrypt), resultKi); System.out.print("DES解密结果:"); System.out.println(DESDecrypt); } //辅助函数:将char转为String public static String ToString(char[]a){ String b = ""; for(int i=0;i<a.length;i++){ b += a[i]; } return b; } //char数组转为int public static int[] trsnChar2Int(char[] CharArr){ int [] resultArr = new int[CharArr.length]; for(int i=0;i<CharArr.length;i++){ resultArr[i] = CharArr[i]-'0'; } return resultArr; } //十六进制转2进制字符串 public static String hexString2binaryString(String hexString) { if (hexString == null) return null; String bString = "", tmp; for (int i = 0; i < hexString.length(); i++) { tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString .substring(i, i + 1), 16)); bString += tmp.substring(tmp.length() - 4); } return bString; } //密钥选择置换PC_1 (64-56) public static char[] KeyPermutation1(String Key){ char [] key = Key.toCharArray();//Get 64bits key array //System.out.println(key); char [] resultKey = new char[56]; int PC_1[] = 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,7,62,54,46,38,30,22, 14,6,61,53,45,37,29,21,13,5,28,20,12,4}; for(int i=0;i<resultKey.length;i++){ resultKey[i] = key[PC_1[i]-1]; } return resultKey; } //CD选择置换PC_2 (56-48) public static char[] KeyPermutation2(char[] CD){ char [] cd = CD;//Get 56bits CD array //System.out.println(cd.length); char [] resultCd = new char[48]; int PC_2[] = new int[]{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}; for(int i=0;i<48;i++){ resultCd[i] = cd[PC_2[i]-1]; } return resultCd; } //循环生成密钥Ki public static char[] CircleGenKey(char[]C,char[]D,int flag){ char [] Ci = C; char [] Di = D; if(flag == 0 || flag == 1 || flag == 8 || flag == 15 ){ //循环左移1 for(int i=0;i<28;i++){ C[i] = Ci[(i+1)%28]; D[i] = Di[(i+1)%28]; } if(flag == 15) C[27] = '0'; } else{//循环左移2 char temp0 = C[0]; char temp00 = D[0]; for(int i=0;i<28;i++){ C[i] = C[(i+1)%28]; D[i] = D[(i+1)%28]; } C[27]=temp0; D[27]=temp00; char temp1=C[0]; char temp11=D[0]; for(int i=0;i<28;i++){ C[i] = C[(i+1)%28]; D[i] = D[(i+1)%28]; } C[27]=temp1; D[27]=temp11; } //System.out.println(C); //System.out.println(D); char [] ResultKey = new char[56]; for(int i=0;i<28;i++){ ResultKey[i]= C[i]; } for(int j=28;j<56;j++){ ResultKey[j]= D[j-28]; } char[] ResultKi = KeyPermutation2(ResultKey); return ResultKi;//ki } //生成密钥16轮Ki public static void GenerateKey(String Key,ArrayList<char[]> resultKi){ char [] keySeed = KeyPermutation1(Key);//Get 56bits key that after OptPermutation PC_1 char [] LeftC0 = new char[28]; for(int i=0;i<LeftC0.length;i++){ LeftC0[i] = keySeed[i]; } char [] RightD0 = new char[28]; for(int j=0;j<RightD0.length;j++){ RightD0[j] = keySeed[j+28]; } char [] LeftC = LeftC0; char [] RightD = RightD0; for(int i=0;i<16;i++){ char[] temp = CircleGenKey(LeftC,RightD,i); resultKi.add(temp); //System.out.println(temp); } } //将原明文进行IP置换 public static char[] InitialPermutation(char[] plaintxt) { char plain[] = plaintxt; int[] IP = 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}; char[]result = new char[64]; for(int i=0; i< plaintxt.length; i++){ result[i]= plain[IP[i]-1]; } return result ; } //IP 逆置换 public static char[] ReverseInitialPermutation(char[]afterCircle) { char[] afterCircleTmp = afterCircle; char[] resultReverseIP = new char[64]; int [] IPReverse = 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 }; for(int i=0;i<resultReverseIP.length;i++){ resultReverseIP[i] = afterCircleTmp[IPReverse[i]-1]; } return resultReverseIP; } //异或操作 public static char[] XorAandB(char[]A,char[]B){ char[]tmpA = A; char[]tmpB = B; int []OperateA = trsnChar2Int(tmpA); int []OperateB = trsnChar2Int(tmpB); if(OperateA.length != OperateB.length){ return null; } char[] XorResult = new char[OperateA.length]; for(int i=0;i<OperateA.length;i++){ int temp = OperateA[i]^OperateB[i]; XorResult[i] = (char) ('0'+temp); } return XorResult; } //E 扩展 public static char[] FunctionExtension(char[] Ri){ char[] tempRi = Ri; char[] resultRi = new char[48]; int[] Extension = 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}; for(int i=0;i<48;i++){ resultRi[i] = tempRi[Extension[i]-1]; } return resultRi; } //加密函数f 置换函数P public static char[] FunctionPermutation(char[] Sout ){ char[] tempSout = Sout; char[] resultPout = new char[32]; int [] Permutation = 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}; for(int i=0;i<32;i++){ resultPout[i] = tempSout[Permutation[i]-1]; } return resultPout; } //加密函数f S盒变换 public static char[] SBoxTrans(char[] E_nor_Ki){ int [][][] Sbox = new int[][][]{ {{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}}, // S2 {{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}}, // S3 {{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}}, // S4 {{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}}, // S5 {{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}}, // S6 {{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}}, // S7 {{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}}, // S8 {{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}}}; char outBox[] = new char[32]; for(int i=0;i<8;i++){ char[] temp6in = new char[6]; for(int i1=0;i1<6;i1++){ temp6in[i1] = E_nor_Ki[i*6+i1]; } //System.out.println(temp6in); int [] tem6in_int = trsnChar2Int(temp6in); int row = tem6in_int[0]*2+tem6in_int[5]; int column = tem6in_int[1]*8+tem6in_int[2]*4+tem6in_int[3]*2+tem6in_int[4]; int soutInt = Sbox[i][row][column]; String HexSoutmp = Integer.toHexString(soutInt); char[] binarySoutChar = hexString2binaryString(HexSoutmp).toCharArray(); int [] binarySoutInt = trsnChar2Int(binarySoutChar); for(int j=0;j<4;j++){ outBox[i*4+j] = (char) ('0'+binarySoutInt[j]); } } return outBox; } //F函数 public static char[] EcryptFunction(char[]Ri_1,char[]Ki){ char []tmpRi_1 = Ri_1; char []tmpKi = Ki; char[] ExtensionR = FunctionExtension(tmpRi_1);//获得Ri经过E扩展后的数组32-48 //Ri'与Ki异或操作 char [] resultXorAandB = XorAandB(tmpKi,ExtensionR); char[]resultSBoxTrans = SBoxTrans(resultXorAandB); char[] FunctionResult = FunctionPermutation(resultSBoxTrans); return FunctionResult; } //DES 16轮加密圈变换 public static char[] EncryptCircleTrans(String IPtxt,ArrayList<char[]> listKi){ char[] IPtxt_tmp = IPtxt.toCharArray(); char []resultOfIP = InitialPermutation(IPtxt_tmp);//明文IP初始置换 char[] afterIPRi = new char[32]; char[] afterIPLi = new char[32]; for(int i=0;i<32;i++){//获得初始L0和R0 afterIPLi[i] = resultOfIP[i]; afterIPRi[i] = resultOfIP[i+32]; } char[] resultRi = afterIPRi; char[] resultLi = afterIPLi; for(int i=0;i<16;i++){//循环16次 char[]resultRitmp = resultRi; char[]resultLitmp = resultLi; resultLi = resultRitmp;//Li = Ri-1 char[] FOut = EcryptFunction(resultRitmp,listKi.get(i)); resultRi = XorAandB(resultLitmp,FOut); } char[] finalCircleResult = new char[64]; for(int i=0;i<32;i++){ finalCircleResult[i] = resultLi[i]; finalCircleResult[32+i] = resultRi[i]; } char[] resultEncrypted = ReverseInitialPermutation(finalCircleResult); return resultEncrypted; } //DES 16轮解密圈变换 public static char[] DecryptCircleTrans(String Encrypted,ArrayList<char[]> listKi){ char[] IEncrypted_tmp = Encrypted.toCharArray(); char []resultOfIP = InitialPermutation(IEncrypted_tmp);//密文IP-1逆置换 char[] afterIPRi = new char[32]; char[] afterIPLi = new char[32]; for(int i=0;i<32;i++){//获得初始L16和R16 afterIPLi[i] = resultOfIP[i]; afterIPRi[i] = resultOfIP[i+32]; } char[] resultRi = afterIPRi; char[] resultLi = afterIPLi; for(int i=15;i>=0;i--){//循环16次 char[]resultRitmp = resultRi; char[]resultLitmp = resultLi; resultRi = resultLitmp;//Ri-1 = Li char[] FOut = EcryptFunction(resultLitmp,listKi.get(i)); resultLi = XorAandB(resultRitmp,FOut); } char[] finalCircleResult = new char[64]; for(int i=0;i<32;i++){ finalCircleResult[i] = resultLi[i]; finalCircleResult[32+i] = resultRi[i]; } char[] resultDecrypted = ReverseInitialPermutation(finalCircleResult); return resultDecrypted; }
- 深入理解并实现DES算法
- 如何实现DES算法
- 如何实现DES算法
- 如何实现DES算法
- 如何实现DES算法.
- 如何实现DES算法
- 如何实现DES算法
- DES算法实现
- 如何实现DES算法
- DES算法流水实现
- 如何实现DES算法
- DES算法的实现
- java实现DES算法
- 如何实现DES算法
- c++实现des算法
- DES、RSA算法实现
- Des算法的实现
- Des算法C++实现
- while 动态创建对象
- Sublime Text 3快捷键
- 欢迎使用CSDN-markdown编辑器
- 登录界面的数据传输流程 AJax
- android-广播、持久化、内容提供器
- 深入理解并实现DES算法
- DirectFB学习之适配FreeType支持
- [2]TQ2440、ADS1.2、JLINK建立集成开发环境
- 三、复合类型
- #1505 : 小Hi和小Ho的礼物
- My First RPG Game总结二
- iOS发送http请求
- C# GridView帮助类
- java中重载与重写的区别