有参考!!!

一、实验目的与原理

1) 学习S-DES密码算法的原理

2) 掌握S-DES密码算法的实现

二、实验过程

1) 算法原理

Simplified DES方案,简称S-DES方案,是DES算法的简化版。它是一个供教学而非安全的加密算法,它与DES的特性和结构类似,但参数小。

加密算法涉及五个函数:

(1)初始置换IP(initial permutation)

(2)复合函数fk1,它是由密钥K确定的,具有置换和代换的运算。

(3)置换函数SW

(4)复合函数fk2

(5)初始置换IP的逆置换IP-1

iOS DES算法加解密_iOS DES算法加解密

iOS DES算法加解密_iOS DES算法加解密_02

  

iOS DES算法加解密_P4_03

 

iOS DES算法加解密_密码学_04

2) 算法参数——S-DES所需的几个置换表

① P10={3,5,2,7,4,10,1,9,8,6}

② P8={6,3,7,4,8,5,10,9} 注意这个置换选择输入10位输出8位

③ P4={2,4,3,1}

④ IP={2,6,3,1,4,8,5,7}

⑤ IP-1={4,1,3,5,7,2,8,6}

⑥ EP={4,1,2,3,2,3,4,1} 注意这个是扩展置换,输入4位输出8位

⑦ 两个S盒:

S0:

{1,0,3,2}

{3,2,1,0}

{0,2,1,3}

{3,1,3,2}

S1:

{0,1,2,3}

{2,0,1,3}

{3,0,1,0}

{2,1,0,3}

3) 算法说明

若明文为: m=0001 0110, key选为(01111 11101),给出加密过程和解密过程,并计算出密文和明文。

a)子密钥的生成

① 10位密钥key = 01111 11101

② 对key做P10置换(P10={3,5,2,7,4,10,1,9,8,6})得到 11111 10011

③ 记左半(高位)的为Lk=11111,右半(低位)为Rk=10011

④ LS-1:Lk和Rk均循环左移1位,得到Lk=11111,Rk=00111

⑤ 对Lk和Rk组合得到的11111 00111做P8置换(P8={6,3,7,4,8,5,10,9})选择,得到子密钥K1=0101 1111

⑥ LS-2:Lk和Rk均再次循环左移2位,得到Lk=11111,Rk=11100

⑦ P8:对Lk和Rk组合得到的11111 11100做P8置换选择,得到子密钥K2=1111 1100

以上,通过密钥得到了算法所需的子密钥。

b)加密过程

首先是初始置换

① 对明文m=0001 0110做IP置换(IP={2,6,3,1,4,8,5,7}),得m’=0100 1001

接下来是标准的Feistel密码结构,共有两次循环。

第一次循环

② 记左半(高位)为Lm=0100,右半(低位)为Rm=1001

③ 对Rm做EP扩展置换(EP={4,1,2,3,2,3,4,1}),得Rm’=1100 0011

④ Rm’与子密钥K1按位异或(K1=0101 1111),得Rm’=1001 1100

⑤ Rm’左半1001(A1A2A3A4)进入S0盒替代选择得11(第4行A1A4 /第1列A2A3的数字3,再转成二进制11,A1A4中A1是数位高位),右半1100进入S1盒替代选择的01(第3行10/第3列10的数字1),组合后得Rm’=1101

⑥ 对Rm’做P4置换(P4={2,4,3,1}),得Rm’=1101

⑦ Rm’与Lm按位异或,得Lm’=1001

⑧ Lm’与Rm(最开始的那个Rm)组合得到输出 1001(Lm’) 1001(Rm)

至此完成第一次循环。

⑨ 然后交换高低位,作为第二次循环的输入,即1001(Rm)1001(Lm’)作为输入

开始第二次循环

⑩ 记左半为Ln=1001,右半为Rn=1001

11 对Rn做EP扩展置换(EP={4,1,2,3,2,3,4,1}),得Rn’=1100 0011

12 Rn’与子密钥K2按位异或(K2=1111 1100),得Rn’=0011 1111

13 Rn’左半0011进入S0盒替代选择得10(第2行01/第2列01的数字2,再转成二进制10),右半1111进入S1盒替代选择的11(第4行11/第4列11的数字3,再转成二进制11),组合后得Rn’=1011

14 对Rn’做P4置换(P4={2,4,3,1}),得Rn’=0111

15 Rn’与Ln按位异或,得Ln’=1110

16 Ln’与Rn(最开始的那个Rn)组合得到输出 1110(Ln’) 1001(Rn)

至此完成第二次循环

17 最后进行逆初始置换对上面的输出m’=1110 1001做IP-1置换得到密文m’=0111 0110.

OK,到这里就完成了将明文加密为密文,S-DES加密结束。

c)解密过程

解密过程与加密基本一致,就是密钥使用顺序是相反的,第一次循环使用K2第二次循环使用K1。

首先还是初始置换

① 对密文m=0111 0110做IP置换(IP={2,6,3,1,4,8,5,7}),得m’=1110 1001

Feistel密码结构

第一次循环

② 记左半(高位)为Lm=1110,右半(低位)为Rm=1001

③ 对Rm做EP扩展置换(EP={4,1,2,3,2,3,4,1}),得Rm’=1100 0011

④ Rm’与子密钥K2按位异或(K2=1111 1100),得Rm’=0011 1111

⑤ Rm’左半0011进入S0盒替代选择得10(第2行01/第2列01的数字2,再转成二进制10),右半1111进入S1盒替代选择的11(第4行11/第4列11的数字3,再转成二进制11),组合后得Rm’=1011

⑥ 对Rm’做P4置换(P4={2,4,3,1}),得Rm’=0111

⑦ Rm’与Lm按位异或,得Lm’=1001

⑧ Lm’与Rm(最开始的那个Rm)组合得到输出 1001(Lm’) 1001(Rm)

至此完成第一次循环。

⑨ 然后交换高低位,作为第二次循环的输入,即1001(Rm) 1001(Lm’)作为输入

开始第二次循环

⑩ 记左半为Ln=1001,右半为Rn=1001

11 对Rn做EP扩展置换(EP={4,1,2,3,2,3,4,1}),得Rn’=1100 0011

12 Rn’与子密钥K1按位异或(K1=0101 1111),得Rn’=1001 1100

13 Rn’左半1001进入S0盒替代选择得11(第4行11/第1列00的数字3,再转成二进制11),右半1100进入S1盒替代选择的01(第3行10/第3列10的数字1),组合后得Rn’=1101

14 对Rn’做P4置换(P4={2,4,3,1}),得Rn’=1101

15 Rn’与Ln按位异或,得Ln’=0100

16 Ln’与Rn(最开始的那个Rn)组合得到输出0100(Ln’) 1001(Rn)

至此完成第二次循环。

17 最后进行逆初始置换

18 对上面的输出m’=0100 1001做IP-1置换(IP-1={4,1,3,5,7,2,8,6})得到明文m’=0001 0110.

这样就完成的S-DES的解密。

输入:

第一行输入主密钥

第二行输入明文

输出

输出密文

输入样例1

1100011110
00101000
0111111101
00010110

输出样例1

10001010
01110110

代码:

import java.util.Scanner;
public class Main{
    static int P4[] = new int[] { 2, 4, 3, 1 };
    static int P8[] = new int[] { 6, 3, 7, 4, 8, 5, 10, 9 };
    static int P10[] = new int[] { 3, 5, 2, 7, 4, 10, 1, 9, 8, 6 };
    static int IP[] = new int[] { 2, 6, 3, 1, 4, 8, 5, 7 };
    static int IP_1[] = 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 S1[][] = { { 1, 0, 3, 2 }, { 3, 2, 1, 0 }, { 0, 2, 1, 3 },
            { 3, 1, 3, 2 }, };
    static int S2[][] = { { 0, 1, 2, 3 }, { 2, 0, 1, 3 }, { 3, 0, 1, 0 },
            { 2, 1, 0, 3 }, };
    static int x1,x2=0;
    //Px置换函数
    static int fx1(int a, int b[], int c) {
        int x = 0;
        for (int i = 0; i < b.length; i++) {
            x <<= 1;
            x |= (a >> (c - b[i])) & 1;
        }
        //返回Px置换之后的结果
        return x;
    }
    //传入参数之后调用
    static int fx2(int a, int b) {
        int l = (a >> 4) & 0xf;
        int r = a & 0xf;
        //调用函数进行EP置换
        return ((l ^ EP(r, b)) << 4) | r;
    }
    //进行初始置换
    static void DES(String key) {
        //将字符串转换为int型之后再转换为二进制
        int x = Integer.parseInt(key, 2);
        //对输入的密钥进行P10置换
        x = fx1(x, P10, 10);
        //定义两个0变量
        int lk,rk=0;
        //左半位右半位移动
        lk = (x >> 5) & 0x1f;
        rk = x & 0x1f;
        lk = ((lk & 0xf) << 1) | ((lk & 0x10) >> 4);
        rk = ((rk & 0xf) << 1) | ((rk & 0x10) >> 4);
        //将左半有伴移动后的结果结合进行P8置换
        x1 = fx1((lk << 5) | rk, P8, 10);
        //之后再次结合准备进行P8置换运算,得到子密钥
        lk = ((lk & 0x07) << 2) | ((lk & 0x18) >> 3);
        rk = ((rk & 0x07) << 2) | ((rk & 0x18) >> 3);
        x2 = fx1((lk << 5) | rk, P8, 10);
    }
    //使用EP拓展置换
    static int EP(int a, int b) {
        int t,t0,t1,x1,x2,y1,y2;
        //进行EP拓展运算
        t= fx1(a, EP, 4) ^ b;
        //分为左半部分和右半部分
        t0 = (t >> 4) & 0xf;  t1 = t & 0xf;
        x1 = ((t0 & 0x8) >> 2) | (t0 & 1);
        y1 = (t0 >> 1) & 0x3;
        x2 = ((t1 & 0x8) >> 2) | (t1 & 1);
        y2 = (t1 >> 1) & 0x3;
        //左半部分和右半部分分别进入S1盒以及S2盒进行代替。
        t0 = S1[x1][y1]; t1 = S2 [x2][y2];
        //进行P4置换
        t = fx1((t0 << 2) | t1, P4, 4);
        return t;
    }

    public static void main(String[] args){
        //明文、密文、密钥
        String bigtext, smalltext, key;
        Scanner scan = new Scanner(System.in);
        while(scan.hasNext()) {
            key = scan.next();
            bigtext = scan.next();
            DES(key);
            //加密过程
            int temp = Integer.parseInt(bigtext, 2);
            //进行IP置换
            temp = fx1(temp, IP, 8);
            //调用函数,传入参数之后进行EP置换
            temp = fx2(temp, x1);
            //进行位移运算
            temp=((temp & 0xf) << 4) | ((temp >> 4) & 0xf);
            temp = fx2(temp, x2);
            //进行IP_1置换得到密文准备输出
            temp = fx1(temp, IP_1, 8);
            //返回一个string
            smalltext = Integer.toString(temp, 2);
            //设定的DES解密范围为8位,输出的密文也设置为8位
            if (smalltext.length() < 8) {
                for (int i = 0; i < 8 - smalltext.length(); i++)
                    smalltext = "0" + smalltext;
            }
            //输出解析后的密文
            System.out.println(smalltext);
        }
    }
}