sdes
key:1100011110
plaintext:00101000
生成k1,k2
key-> k1(4bits), k2(4bits)
P10,P8: 长度为10和8的置换
P10:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|
3 | 5 | 2 | 7 | 4 | 10 | 1 | 9 | 8 | 6 |
P8:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
6 | 3 | 7 | 4 | 8 | 5 | 10 | 9 |
(k1 = P8(shift(P10(k))))
(k2 = P8(shift^3(P10(k))))
Bit # | 1 2 3 4 5 6 7 8 9 10 |
---|---|
(K) | 1 1 0 0 0 1 1 1 1 0 |
(P10(K)) | 0 0 1 1 0 0 1 1 1 1 |
(Shif t(P10(K))) | 0 1 1 0 0 1 1 1 1 0 |
(P8(Shif t(P10(K)))) | 1 1 1 0 1 0 0 1 |
Bit # | 1 2 3 4 5 6 7 8 9 10 |
---|---|
(K) | 1 1 0 0 0 1 1 1 1 0 |
(P10(K)) | 0 0 1 1 0 0 1 1 1 1 |
(Shift^3(P10(K))) | 1 0 0 0 1 1 1 0 1 1 |
(P8(Shift^3(P10(K)))) | 1 0 1 0 0 1 1 1 |
k1 = {1110 1001} and k2 = {1010 0111}
加密
- (p = IP(p))
- (p = f_k(p,k1))
- (p = SW(p))
- (p = f_k(p,k2))
- (p = IP^{-1}(p))
解密将2,4互换即可
把P写成 (P=(L,R))
(IP):8位置换(2,6,3,1,4,8,5,7)
,(IP^{-1}): IP的逆操作{4,1,3,5,7,2,8,6}
(SW): (SW(P) = SW(L,R) = (R,L)), 左右bit互换
(f_k): (f_k(L,R) = (L{igoplus}F(R,SK),R))
(F(p,k)):
- 对P做 (E/P) 扩展置换如
(E/P) |
---|
4 1 2 3 2 3 4 1 |
- (P = P igoplus k)
- P(L,R) 左右四个bits分别进入两个S盒得到左右两个bits共4bits
- 再对P做一次4位置换
S盒:
S盒操作如下:第一个和第四个输入作为一个2位数指定S盒中的一行,第二和第三个输入作为一个2位数指定S盒中的一列。比如0010,则输出是S盒的第一行第二列这里是3(二进制的11),类似的 和的值找到在第二个S盒中的值。
实现
import java.io.IOException;
public class SimpleDES {
/**
* @param args
*/
// two keys K1 and K2
static int K1=0;
static int K2=0;
/*some parameters*/
static int P10[]=new int[]{3,5,2,7,4,10,1,9,8,6};
static int P8[]=new int[]{6,3,7,4,8,5,10,9};
static int P4[]=new int[]{2,4,3,1};
static int IP[]=new int[]{2,6,3,1,4,8,5,7};
static int IPI[]=new int[]{4,1,3,5,7,2,8,6};
static int EP[]=new int[]{4,1,2,3,2,3,4,1};
static int S0[][]={
{1,0,3,2},
{3,2,1,0},
{0,2,1,3},
{3,1,3,2},
};
static int S1[][]={
{0,1,2,3},
{2,0,1,3},
{3,0,1,0},
{2,1,0,3},
};
//根据数组交换
static int Permute(int num,int p[],int pmax){
int result=0;
for(int i=0;i<p.length;i++){
result<<=1;
result|=(num>>(pmax-p[i]))&1;
}
return result;
}
//生成k1,k2
static void SDES(String Key){
int K=Integer.parseInt(Key,2);
K=Permute(K,P10,10);
int th=0,tl=0;
th=(K>>5)&0x1f;//取Key的高5位
tl=K&0x1f; //取Key的低5位
//LS-1
th=((th&0xf)<<1) | ((th & 0x10) >> 4);//循环左移一位
tl=((tl&0xf)<<1) | ((tl & 0x10) >> 4);//循环左移一位
K1=Permute(( th << 5)| tl,P8,10); //生成K1
System.out.println("K1:"+Integer.toString(K1,2));
//LS-2
th=((th & 0x07)<< 2) |((th & 0x18) >> 3);//循环左移二位
tl=((tl & 0x07)<< 2) |((tl & 0x18) >> 3);//循环左移二位
K2=Permute((th<<5) | tl,P8,10); //生成K2
System.out.println("K2:"+Integer.toString(K2,2));
}
/*
1. E/P
2. P^K
3. P = S1(L)|S2(R)
4. P = P4(P)
*/
static int F(int R,int K){
int t=Permute(R,EP,4)^K; // 1,2
int t0=(t>>4)& 0xf;
int t1=t&0xf;
t0= S0[((t0 & 0x8)>>2) | (t0 & 1)] [(t0>>1)&0x3];
t1= S1[((t1 & 0x8)>>2) | (t1 & 1)] [(t1>>1)&0x3]; // 3
t= Permute((t0<<2)|t1,P4,4); // 4
return t;
}
//fk函数 fk = (L^F(r,k),r)
static int fk(int input,int k){
int l=(input>>4) & 0xf;
int r=input & 0xf;
return ((l^F(r,k))<< 4)| r;
}
//switch function 左右移位
static int SW(int x)
{
return ((x&0xf)<<4) | ((x>>4)&0xf);
}
//加密
static String encrypt(String input){
int m=Integer.parseInt(input, 2);
m=Permute(m,IP,8);
m=fk(m,K1);
m=SW(m);
m=fk(m,K2);
m=Permute(m,IPI,8);
return Integer.toString(m, 2);
}
//解密
static String decrypt(String input){
int m=Integer.parseInt(input, 2);
m=Permute(m,IP,8);
m=fk(m,K2);
m=SW(m);
m=fk(m,K1);
m=Permute(m,IPI,8);
return Integer.toString(m, 2);
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String plaintext,ciphertext,key;
java.util.Scanner scan = new java.util.Scanner(System.in);
System.out.println("1:加密,2:解密,3:退出,请输入一个数字来选择:");
int mode=scan.nextInt();
while(true){
if(mode==1){
System.out.println("请输入明文:");
plaintext=scan.next();
System.out.println("请输入密钥:");
key=scan.next();
SDES(key);
ciphertext=encrypt(plaintext);
//如果密文不足8位,补足8位
if(ciphertext.length()<8){
for(int i=0;i<8-ciphertext.length();i++)
ciphertext="0"+ciphertext;
}
System.out.println("加密后的密文为:"+ciphertext);
}
else if(mode==2){
System.out.println("请输入密文:");
ciphertext=scan.next();
System.out.println("请输入密钥:");
key=scan.next();
SDES(key);
plaintext=decrypt(ciphertext);
if(plaintext.length()<8){
for(int i=0;i<8-plaintext.length();i++)
plaintext="0"+plaintext;
}
System.out.println("解密后的明文为:"+plaintext);
}
else if(mode==3) break;
System.out.println("1:加密,2:解密,3:退出,请输入一个数字来选择:");
mode=scan.nextInt();
}
}
}