(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