(1)先了解变换,沙盒先后了解均可(变换和沙盒在下面做特殊说明)
(2)将明文m进行ip变换,获得ipm
(3)通过k获取16个子密钥key[0-15],每个子密钥48位->(过程如下)
->64位k密钥通过pc1变换缩小为48位
->均分为c[0] ,d[0].执行移位操作等得到c[1-16] d[1-16]
移位操作为循环左移
16次移位中,1,2,9,16循环左移一位,其他左移2位
移位之后进行合并得到c[i+1] d[i+1]
(比如c[0]d[0]均左移1位得到c[1]d[1])
C[i] d[i] 合并后经过pc2变换得到key[i-1],即子密钥
(备注: 如k[0-15]由c[1-16]和d[1-16]合并变换而来)
(4)将ipm分为2部分,即l[0],r[0].
(5)确定f函数值->
->将输入的r[i], 开始为r[0],32位通过E变换,膨胀为48位
->膨胀后的结果与k[i]做异或
->48位通过沙盒s,缩小为32位(沙盒变换,做特殊说明)
->进行p变换
->通过上面步骤可以得到r[0],l[0] , key[0-15] f[0]
R[i+1] = l[i] 异或 f[i]
L[i+1] = r[i]
即: 变换右边为左边与函数f的异或,赋值左边等于右边
每得到一个新的右边r[i],将可以与已知k[i]确定f[i]函数值使得算法延续
进行16次,得到r[0-16] l[0-16]
将r[16]和l[16]合并,经过ip1变换得到密文e
(注意最后一次合并,右边放左边了,其他合并都正常)
3.特殊说明:
1> 变换. 一定位数的数组,将位置打乱,甚至有些重复出现,有些不再出现,由此产生一个新数组的过程,被我称为变换。
举例: int[] a = {5,6,7}
变换矩阵为 { 2, 1, 1,0}
那么取{ a[2],a[1] , a[1] ,a[0] }为新数组,即{7,6,6,5 } 为产生的新数组(当然,des操作中数组值只有0和1,变换后长度不确定)
2 >沙盒
效果: 48位缩小为32位,并且数据发生变化
操作:均分为8份,8份每份长为6个01串 ,如s0-s5
计算x =s0*2+s5;
y= s4+s3*2+s2*4+s1*8;
每个6位通过上面计算后都在自己的沙盒中找沙盒中x行y列值
将该值转为4位2进制01串
将8个4位2进制合并编程32位
package com; /** * * @author 黎锦燊 * @qq:303058345 */@tel 15927404406 public class Change { //这是一些变换表 int[] m = { 0,1,1,0,1,1,0,0, 0,1,1,0,0,1,0,1, 0,1,1,0,0,0,0,1, 0,1,1,1,0,0,1,0, 0,1,1,0,1,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,1,1,0, 0,1,1,0,0,1,1,1 }; int[] k = { 0,1,1,0,0,0,1,1, 0,1,1,0,1,1,1,1, 0,1,1,0,1,1,0,1, 0,1,1,1,0,0,0,0, 0,1,1,1,0,1,0,1, 0,1,1,1,0,1,0,0, 0,1,1,0,0,1,0,1, 0,1,1,1,0,0,1,0 }; int[] ip = { 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, 56,48,40,32,24,16,8,0, 58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6}; int[] ip1 = {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,0,40,8,48,16,56,24}; int[] E= {31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8,9,10,11,12, 11,12,13,14,15,16, 15,16,17,18,19,20, 19,20,21,22,23,24, 23,24,25,26,27,28, 27,28,29,30,31, 0}; int[] P = {15,6,19,20,28,11,27,16, 0,14,22,25,4,17,30,9, 1,7,23,13,31,26,2,8, 18,12,29,5,21,10,3,24}; int S[][][] =//S1 {{{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}}}; int[] pc1 = {56,48,40,32,24,16,8, 0,57,49,41,33,25,17, 9,1,58,50,42,34,26, 18,10,2,59,51,43,35, 62,54,46,38,30,22,14, 6,61,53,45,37,29,21, 13,5,60,52,44,36,28, 20,12,4,27,19,11,3}; int[] pc2 = {13,16,10,23,0,4,2,27, 14,5,20,9,22,18,11,3, 25,7,15,6,26,19,12,1, 40,51,30,36,46,54,29,39, 50,44,32,47,43,48,38,55, 33,52,45,41,49,35,28,31}; //key[0]对应key1 ,即k[0-15]对应k1-k16 //产生密钥过程 public int[][] getKey() { out("key ->"); display(k); int[][] key= new int[16][]; int first0[] = new int[56]; int second[] = new int[48]; int[][] c=new int[17][]; int[][] d=new int[17][]; //通过pc1,变换位置 first0= change(k,pc1); out("first0 ->"); display(first0); c[0]= split(first0)[0]; d[0]=split(first0)[1]; for(int i=1;i<=16;i++) { if(i==1 || i==2 ||i==9 ||i==16) { //循环左移一位 c[i]=moveleft(c[i-1],1) ; d[i]=moveleft(d[i-1],1) ; } else { //循环左移两位 c[i]=moveleft(c[i-1],2) ; d[i]=moveleft(d[i-1],2) ; } } for(int i=1;i<=16;i++) { second=add(c[i],d[i]); key[i-1]=change(second,pc2); } return key; } //加密过程 public void DES() { out("m------->"); display(m); //1.将明文m通过ip变换,获得ipm. int[] ipm = change(m,ip); out("ipm----->"); display(ipm); //1.1 获得子密钥 int[][] key=getKey(); for(int i=0;i<16;i++) { out("key["+i+"]--->"); display(key[i]); } System.out.println("get the right childkey"); //2.将ipm分为2部分,即l0,r0 int[][] l=new int[17][]; int[][] r=new int[17][]; l[0]=split(ipm)[0]; r[0]=split(ipm)[1]; int[][] f=new int[16][32]; for(int i=0;i<16;i++) { f[i]=functionf(r[i], key[i]); out("f["+i+"]-->"); display(f[i]); r[i+1]=exclusiveOr(l[i],f[i]); l[i+1]=r[i]; } for(int i=0;i<17;i++) { out("l["+i+"]--->"); display(l[i]); out("r["+i+"]--->"); display(r[i]); } int[] result = new int[64]; result = add(r[16],l[16]); result = change(result,ip1); out("-------------->"); display(result); } //异或运算 public int[] exclusiveOr(int[] l,int[] f) { int [] result = new int[l.length]; for(int i=0;i<l.length;i++) { result[i]=l[i]^f[i]; } return result; } //将一个6位数组s ,通过第b个沙河,变成一个长度为4的数组 public int[] functionS(int[] s, int b) { int[] result = new int[4]; int x =s[0]*2+s[5]; int y= s[4]+s[3]*2+s[2]*4+s[1]*8; out(S[b][x][y]+"-"); result=intToHex(S[b][x][y],4); return result; } //将一个int s 转换为2进制,保存再长度为b的数组中,数组存储0/1,输出会发现倒序 public int[] intToHex(int s , int b) { int[] result = new int[b]; for(int i=0;i<b;i++) { result[b-i-1]= s%2; s=s/2; } return result; } //将32位,与48密钥处理得到32位 public int[] functionf(int[] r, int[] k) { //将输入r0 32位膨胀为48位 int[] result = new int[32]; int[] the = new int[48]; the = change(r,E); //膨胀后与k1异或 int[] the1 = exclusiveOr(the, k); //将48位数组拆分位8个6位 int[][] th = new int[8][]; th[0]=split(split(split(the1)[0])[0])[0]; th[1]=split(split(split(the1)[0])[0])[1]; th[2]=split(split(split(the1)[0])[1])[0]; th[3]=split(split(split(the1)[0])[1])[1]; th[4]=split(split(split(the1)[1])[0])[0]; th[5]=split(split(split(the1)[1])[0])[1]; th[6]=split(split(split(the1)[1])[1])[0]; th[7]=split(split(split(the1)[1])[1])[1]; //通过沙河 进行s变换,缩位32位 int[][] ts = new int[8][4]; for(int i=0;i<8;i++) { ts[i]= functionS(th[i], i); } int[] tu = new int[32]; int[] tk = ts[0]; for(int i=1;i<8;i++) { tk=add(tk,ts[i]); } tu=tk; //进行p变换,混乱位置 result = change(tu,P); return result; } //输出一个数组存储的数据 public void display(int [] s) { for(int i=0;i<s.length;i++) { System.out.print(s[i]);} System.out.println(); } //输出一个不换行的字符串 public void out(String s) { System.out.print(s); } //将数组old经过way矩阵位置置换 public int[] change(int[] old , int[] way) { int[] now =new int[way.length]; for(int i=0;i<way.length;i++) { now[i]=old[way[i]]; } return now; } //将数组old分成2个保存再now[0]和now[1]中 public int[][] split(int[] old) { int[][] now = new int[2][old.length/2]; for(int i=0;i<old.length/2;i++) { now[0][i]=old[i]; now[1][i]=old[i+old.length/2]; } return now; } //将2个数组进行合并 public int[] add(int[] left,int[] right) { int[] now = new int[left.length+right.length]; for(int i=0;i<left.length;i++) { now[i]=left[i]; } for(int i=left.length;i<right.length+left.length;i++) { now[i]=right[i-left.length]; } return now; } //数组m循环左移k位 public int[] moveleft(int[] m, int k) { int[] result= new int[m.length]; int[] the = new int[k]; for(int i=0;i<k;i++) { the[i] = m[i]; } for(int i=0;i<m.length-k;i++) { result[i]=m[i+k]; } for(int i=m.length-k;i<m.length;i++) { result[i]=the[i- (m.length-k)]; } return result; } public static void main(String[] args) { Change c = new Change(); c.DES(); } }
原文:http://www.cnblogs.com/UseMyWay/p/des.html