数据加密标准DES是分组密码的典型代表,是上世纪八九十年代很常用的加密算法。
DES的整体结构采用16圈Feistel模型。大致过程如下:
1.将待加密的明文分组,每组64比特
2.对于每一组,进行初始置换
3.置换后将明文分为左半部分和右半部分各32比特,接着进行16圈迭代
3.1 每一圈中,右半部分在48比特圈(子)密钥k的作用下进行f变换,得到的32比特数据
与左半部分按位异或,产生的32比特数据作为下一圈迭代的右半部分
3.2 原右半部分直接作为下一圈迭代的左半部分
3.3
4.最后左右部分合并再进行一次置换,即可得到密文
接下来介绍一下圈(子)密钥k的生成算法:
/*输入64位初始密钥(这里是16位16进制数),迭代16轮,每一轮输出48位圈密钥
1.对64位的初始密钥进行置换选择1
2.将置换选择1输出的56比特数据分成左右两部分,每部分28位
3.1 每一轮将两部分分别进行循环左移,左移的位数与其所在圈数有关,进行16轮
3.2 左移后进行置换选择2得到48比特的圈密钥
4. 重复第3步16次,总共得到16圈子密钥
*/
c++实现如下:
#include<bits/stdc++.h>
bool key[66] , C[29] ,D[29];
int k(0);
int table1[56] = {57,49,41,33,25,17,9,1 //置换选择表1,用于从64位初始密钥中选择56位
,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 table2[48] = {14,17,11,24,1,5, //置换选择表2,将得到的56位进行置换选择2,得到真正的圈密钥
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 dis[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};//C寄存器和D寄存器循环左移的位数
void to_binary(int n) //将10进制数转换为4位2进制数
{
int K = k+3;
while(n)
{
key[K--] = n % 2;
n /= 2;
}
while(k <= K)
key[K--] = 0;
k = k + 4;
}
void transform16_64(char *s)//将16位16进制数转换为64位二进制
{
for(int i = 0 ; s[i] ; i++)
{
if(s[i] < 65)
to_binary(s[i] - '0');
else to_binary(s[i] - 55);
}
}
void exchange1() //置换选择1,产生C,D各28位
{
for(int i(0) ; i < 28 ; i ++)
C[i] = key[table1[i] - 1] ;
for(int i(28) , j(0) ; i < 56 ; i++ , j++)
D[j] = key[table1[i] - 1] ;
}
void exchange2(int n)//置换选择2,并输出第n圈的圈密钥
{
printf("K%d:\t" , n);
for(int i = 0 ; i < 48 ; i++)
{
int t = table2[i] - 1 ;
printf("%d" , t > 27 ? D[t-28] : C[t]);
}
puts("\n");
}
void displace(int n , bool *c)//移位操作,n表示第n次移位
{
int p = dis[n];
bool t[p];
for(int i = 0 ; i < p ; i++)
t[i] = c[i];
for(int i = p ; i < 28 ; i++)
c[i-p] = c[i];
for(int i = 28-p ; i < 28 ; i++)
c[i] = t[i-(28-p)];
}
int main()
{
char K[20];
while(scanf("%s" , K) != EOF)//输入16位16进制数(初始密钥)
{
transform16_64(K);//16进制转64进制
exchange1(); //置换选择1
for(int i(0) ; i < 16 ; i++) //进行16圈迭代
{
displace(i , C); //第i圈迭代,进行移位操作
displace(i , D);
exchange2(i+1) ;//置换选择2
}
}
return 0;
}
//K = FEDCBA9876543210 初始密钥 k