DES算法实现(密码学第四次实验作业)

DES算法是一种典型的Feistel结构的分组密码算法,它的明文分组长度为64bit,密钥分组长度为64bit,其中有8bit是奇偶校验,所以有效密钥长度为56bit。DES算法的加密和解密采用同一过程,安全性依赖有效密钥。

DES算法加密过程

大致过程 : IP初始置换——16轮迭代变换——IP逆置换

 

1.需要输入的数据:

KEY:8字节密钥(64bit)

MIN:8字节明文(64bit)

相关介绍:

字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位。

字符是指计算机中使用的文字和符号,比如1  2  3  A  B  C  a  b  c  ~ ! ·  # 等等。

在不同编码中字符和字节的对应关系不同,

ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。

在加密过程中,是以64bit的形式进行变换的,即64位的二进制序列,所以要将输入的密钥和明文转化为64位二进制序列的形式

如:'a' 的ASCII值为97,将97转变为8位的二进制序列为  01100001

 

2 . IP初始置换:

将64位明文序列按下表进行置换(位置变换)

int IP_T[64] =    //IP置换矩阵
{
    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
};

将置换后的数据 分成  L0(32bit),R0(32bit)两部分

 

3 . 16轮迭代变换

迭代过程:

DES算法实现(密码学第四次实验作业)_第1张图片

 

如图所示: 下一轮的左半部分就是上一轮的右半部分,下一轮的右半部分 先由 上一轮右半部分与轮密钥Ki进行F函数变换,再与上一轮的左半部分异或得到,即如下列公式:

       Li = Ri-1

       Ri = Li-1  ⊕ F(Ri-1 , Ki)

   

3.1 轮密钥生成 

1 . 64位秘钥降至56位秘钥,将密钥排成 8*8 的矩阵,每一行的第八位将作为奇偶校验位被忽略,于是形成了初始的56位的密钥

再通过置换表置换 PC-1(表中不含8,16,24,32,40,48,56,64这八个数),如下:

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

2.再将得到的56位密钥分成C0和D0,前28位为C0,后28位为D0

      按循环左移表循环左移:

1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16
1  1  2  2  2  2  2  2  1  2   2   2   2   2   2   1

将循环左移后的Ci,Di合并,得到56位,再通过置换表PC-2,变为48位,即为轮密钥Ki:

                                                                  PC-2

void PC_2(int input[56], int output[48])//PC_2
{
    for (int i = 0; i<48; i++)
        output[i] = input[PC2_T[i] - 1];
}

 

3.2  E盒扩展置换

将原来的明文数据的右半部分R从32位扩展成为48位,在两边扩展了两列 如下表进行扩展置换:

int E_T[48] =  //扩展矩阵
{
    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
};

    将扩展后的 48bit 与得到的 46bit轮密钥 Ki 进行 异或,得到S盒的输入

   

3.3  S盒代替压缩

  将48位数据按照每6位分为一组,一共分为8组,并分别输入S1, S2,S3,S4,S5,S6,S7,S8这8个盒子中,每个盒子产生4位的输出,将每个S 盒的输出拼接成32位。 

每个盒子中的具体实现: 每组6bit,每组的第一位和最后一位构成的2位二进制数对应的十进制数为S盒的行号x,中间四位构成的4位二进制数对应的十进制数为S盒的列号y。在S盒中找到坐标为(x,y)的数,将这个10进制数化为4位的二进制数,即为此S盒输出的4bit。

int S_Box[8][4][16] =  //8个S盒 ,每个盒为4行16列
{
    // 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
};

   

    3.4  P盒置换

将S盒得到的32位数,按P盒进行置换

int PC2_T[48] =  // 密钥第二次置换矩阵
{
    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
};

 

4 . IP逆置换

经过16轮的迭代之后,将输出的L16和R16左右交换,合并起来形成64位的二进制数,最后 按照下表 进行IP逆置换,得到64bit密文

int IPR_T[64] =   //逆IP置换矩阵
{
    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
};

解密过程和加密一样。

代码:

#include
#include
#include
using namespace std;
int IP_T[64] =    //IP置换矩阵
{
    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
};
int E_T[48] =  //扩展矩阵
{
    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
};
int P_T[32] =  //  P 盒
{
    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
};
int IPR_T[64] =   //逆IP置换矩阵
{
    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
};
int PC1_T[56] =   //密钥第一次置换矩阵
{
    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
};
int PC2_T[48] =  // 密钥第二次置换矩阵
{
    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
};
int S_Box[8][4][16] =   //8个S盒 每个盒为4行16列
{
    // 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
};
void CharToBit(char input[], int output[], int len)       //把char转换为64二进制
{
    for(int i=0;i>j)&1;
}
void BitToChar(int intput[], char output[], int bits)   //把64bit转换为8字节
{
    for(int i=0;i<8;i++)
        for(int j=0;j<8;j++)
        output[i]=output[i]*2+intput[j+8*i];
}
void Xor(int A[], int B[], int len)//异或操作
{
    for (int i = 0; i> i) & 1;
}
void F_func(int input[32], int output[32], int subkey[48])//完成DES算法轮变换
{
    int len = 48;
    int temp[48] = { 0 },temp_1[32] = { 0 };
    E(input, temp);  //E盒扩展置换
    Xor(temp, subkey, len);  //与Ki异或
    S(temp, temp_1);         //S盒代替压缩
    P(temp_1, output);       //P盒置换
};
void RotateL(int input[28], int output[28], int leftCount) //秘钥循环左移
{
    int len = 28;
    for (int i = 0; i

 

 

你可能感兴趣的:(应用密码学)