DES加密详解
DES加密示例:
明文:Your lips are smoother than vaseline
密钥:0E329232EA6D0D73
密文:C0999FDDE378D7ED727DA00BCA5A84EE47F269A4D6438190D9D52F78F5358499CF8700010F88469B
DES具体加密过程
处理密钥
将密钥转换成64位的二进制
1.密钥是16位的16进制
每一位十六进制转换为4位二进制,形成64位二进制(16*4)
bs_64 H_to_bit64(char str[]) {
bs_64 b;
int num = 0, x;
for(int i = 15; i >= 0; --i) {
if(str[i] >= '0' && str[i] <= '9') {
x = str[i] - '0';
}else {
x = str[i] - 'A' + 10;
}
do {
b[num++] = x%2;
x /= 2;
} while (num %4 != 0);
}
return b;
}
key = 0E329232EA6D0D73
变为:
K = 0000111000110010100100100011001011101010011011010000110101110011
2.密钥是8位的任意字符
将每个字符按照ascll码转换为8位的二进制,形成64位二进制(8*8)
bs_64 _8char_to_bit64(char str[]) {
bs_64 b;
int num = 0;
for(char i = 7; i >= 0; --i) {
int x = str[i];
do {
b[num++] = x % 2;
x /= 2;
}while(num %8 != 0);
}
return b;
}
将64位密钥K通过PC1转换为56位K+
8*8变为8*7(去掉8位)
bs_56 getpc1(bs_64 k) {
bs_56 bs56;
for(int i = 55; i >= 0; --i) {
bs56[i] = k[64-PC_1[55-i]];
}
return bs56;
}
K = 0000111000110010100100100011001011101010011011010000110101110011
变为:
k+ = 00010100101100001011101010001001111101100001011100011110
通过K+得到16组最终的48位密钥KK
87变为86
k+分为C0,D0左右两部分
C0 = 0001010010110000101110101000
D0 = 1001111101100001011100011110
将Ci, Di向左移动move_table[i]位,得到Ci+1, Di+1
for(int i = 1; i <= 16; ++i) {
for(int j = 0; j < 28; ++j) {
c[i][(j+move_table[i-1])%28] = c[i-1][j];
d[i][(j+move_table[i-1])%28] = d[i-1][j];
}
}
C1 = 0010100101100001011101010000
D1 = 0011111011000010111000111101
C2 = 0101001011000010111010100000
D2 = 0111110110000101110001111010
C3 = 0100101100001011101010000001
D3 = 1111011000010111000111101001
C4 = 0010110000101110101000000101
D4 = 1101100001011100011110100111
C5 = 1011000010111010100000010100
D5 = 0110000101110001111010011111
C6 = 1100001011101010000001010010
D6 = 1000010111000111101001111101
C7 = 0000101110101000000101001011
D7 = 0001011100011110100111110110
C8 = 0010111010100000010100101100
D8 = 0101110001111010011111011000
C9 = 0101110101000000101001011000
D9 = 1011100011110100111110110000
C10 = 0111010100000010100101100001
D10 = 1110001111010011111011000010
C11 = 1101010000001010010110000101
D11 = 1000111101001111101100001011
C12 = 0101000000101001011000010111
D12 = 0011110100111110110000101110
C13 = 0100000010100101100001011101
D13 = 1111010011111011000010111000
C14 = 0000001010010110000101110101
D14 = 1101001111101100001011100011
C15 = 0000101001011000010111010100
D15 = 0100111110110000101110001111
C16 = 0001010010110000101110101000
D16 = 1001111101100001011100011110
将新得到的Ci,Di重新合并得到CiDi
C1D1 = 00101001011000010111010100000011111011000010111000111101
C2D2 = 01010010110000101110101000000111110110000101110001111010
C3D3 = 01001011000010111010100000011111011000010111000111101001
C4D4 = 00101100001011101010000001011101100001011100011110100111
C5D5 = 10110000101110101000000101000110000101110001111010011111
C6D6 = 11000010111010100000010100101000010111000111101001111101
C7D7 = 00001011101010000001010010110001011100011110100111110110
C8D8 = 00101110101000000101001011000101110001111010011111011000
C9D9 = 01011101010000001010010110001011100011110100111110110000
C10D10 = 01110101000000101001011000011110001111010011111011000010
C11D11 = 11010100000010100101100001011000111101001111101100001011
C12D12 = 01010000001010010110000101110011110100111110110000101110
C13D13 = 01000000101001011000010111011111010011111011000010111000
C14D14 = 00000010100101100001011101011101001111101100001011100011
C15D15 = 00001010010110000101110101000100111110110000101110001111
C16D16 = 00010100101100001011101010001001111101100001011100011110
将CiDi再次经过PC2置换得到最终的16组加密KKi
该过程将8*7变为8*6
KK1 = 001101100001010001100100011110001110000111100001
KK2 = 010000001011110100010001011101101110100011111101
KK3 = 010001011010010001110011001000111001110111011011
KK4 = 111001111100010010000010100011111011010100110011
KK5 = 011110101000001110000010011011110100111101100100
KK6 = 001110001001000000011011010110001100100111011110
KK7 = 001001010000000001011110110001011101010010011101
KK8 = 001001100100100010010100110010110011011011101001
KK9 = 010101000101010101000001011110011111011000110011
KK10 = 010000111100100101000101001111110100110000101110
KK11 = 000010011110000110000111100011000111100111010110
KK12 = 001100010000010110101011101001011110001011110101
KK13 = 111100010000000010100001111100111000111011000011
KK14 = 100100011000101010010100100111101000011100011111
KK15 = 000101000011001010010110000111110111011111000100
KK16 = 011000000110111100000100010011000011101011100111
处理明文
将明文按照ascll码每八位分为一组转换为64位,最后不够的填充零
bs_64 _8char_to_bit64(char str[]) {
bs_64 b;
int num = 0;
for(char i = 7; i >= 0; --i) {
int x = str[i];
do {
b[num++] = x % 2;
x /= 2;
}while(num %8 != 0);
}
return b;
}
0101100101101111011101010111001000100000011011000110100101110000
0111001100100000011000010111001001100101001000000111001101101101
0110111101101111011101000110100001100101011100100010000001110100
0110100001100001011011100010000001110110011000010111001101100101
0110110001101001011011100110010100000000000000000000000000000000
再将转为64位的明文进行IP置换得到MMi
for(int i = 63; i >= 0; --i) {
ip[i] = x[64-IP[63-i]];
}
MM1 = 1110111110001101001001100100011100000000111111100110001100001010
MM2 = 1101110101001001100100001101010100000000111111111000000001001001
MM3 = 1011111110100100100101110001001100000000111111110000101100100011
MM4 = 1111011101010000100101001110001000000000111111110000010101010100
MM5 = 0000111100000000000011010000101000000000000011110000011100000100
开始加密
经过上面的准备得到了16轮的48位加密密钥和分组后的64位明文MMi,接下来将每组明文MMi经过16轮加密形成64位的二进制密文(用8位16进制表示),下面演示一组加密过程:
MM1 = 1110111110001101001001100100011100000000111111100110001100001010
将MM1分为左右两个部分L0R0
L0 =
11101111100011010010011001000111
R0 =
00000000111111100110001100001010
然后再进行16轮函数置换,置换规则如下:
Ln = Rn-1
Rn = Ln-1 + f(Rn-1 ,Kn)
for(int i = 1; i <= 16; ++i) {
tmp = r;
r = l ^ f(r, i);
l = tmp;
}
经过16次的置换之后得到l16,r16,将r16l16拼接成64位的串(注意是l在右边r在左边)再经过IPR逆置换盒生出最终的密文
1100000010011001100111111101110111100011011110001101011111101101
转换为16进制
C0999FDDE378D7ED
至此生成第一组的密文
下面重点介绍f函数的原理f(r, i)
首先回忆一下r是MM的右半部分(32位),i代表使用的是地i个key即KKi(48位)
所以f函数首先将32位的r经过E盒置换为48位
er = 000000000001011111111100001100000110100001010100
将er与KKi异或得到新的Bi(48位)
001101100000001110011000010010001000100110110101
将Bi按照6个一组分为8组,每组j经过S盒Sj进行置换,S盒由4行16列组成,其中每行由0~15乱序组成,例如S1:
列 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | 14 | 4 | 13 | 1 | 2 | 15 | 11 | 8 | 3 | 10 | 6 | 12 | 5 | 9 | 0 | 7 |
01 | 0 | 15 | 7 | 4 | 14 | 2 | 13 | 1 | 10 | 6 | 12 | 11 | 9 | 5 | 3 | 8 |
10 | 4 | 1 | 14 | 8 | 13 | 6 | 2 | 11 | 15 | 12 | 9 | 7 | 3 | 10 | 5 | 0 |
11 | 15 | 12 | 8 | 2 | 4 | 9 | 1 | 7 | 5 | 11 | 3 | 14 | 10 | 0 | 6 | 13 |
Bi第一组为:001101与S1盒置换过程为:
取第一个(0)和最后一个(1)二进制数得到01代表取S1盒的01行,中间四位为0110为二进制的6代表第6列,最终确定出S1盒的01行6列的数13转化为(四位)二进制1101完成6位到4位的置换,同理Bi的第二组与S2盒进行置换也得对应一个4位的二进制数,最终将48位的Bi转化为32位。
S盒置换后的Bi = 11010000010110110101100111011001
然后再将置换后的Bi(32位)经过P盒置换得到新的32位Bi
所以说f函数是一个入口为一个32位的R和48位的KKi,出口为32位的Bi
bs_32 f(bs_32 r, int time) {
bs_48 er;
for(int i = 47; i >= 0; --i) {
er[i] = r[32-E[47-i]];
}
er ^= kk[time];
bs_32 ff;
int t = 0, co = 0;
for(int i = 7; i >= 0; --i) {
int row = er[t+5]*2+er[t];
int col = er[t+4]*8+er[t+3]*4+er[t+2]*2+er[t+1];
int num = S_Box[i][row][col];
do {
ff[co++] = num%2;
num /= 2;
}while(co %4 != 0);
t += 6;
}
bs_32 fff;
for(int i = 31; i >= 0; --i) {
fff[i] = ff[32-P_Table[31-i]];
}
return fff;
}
#1楼 2021年5月20日 17:49 by '"()
1