DES加解密時產(chǎn)生的子密鑰

DES算法共需要進(jìn)行16輪迭代運(yùn)算,每輪迭代運(yùn)算使用一個子密鑰,共需要16個子密鑰。子密鑰是從用戶輸入的初始密鑰產(chǎn)生的,用戶輸入的初始密鑰K64位,其中有8位用于奇偶校驗,分別位于第8,16,24,32,40,48,56,64位。奇偶校驗位用于檢查密鑰K在產(chǎn)生和分配以及存儲過程中可能發(fā)生的錯誤,這樣DES的密鑰實際上只有56位。

加密過程生成的子密鑰

首先密鑰經(jīng)過PC-1表置換后

         Permuted Choice 1 (PC-1)

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

將變換后的密鑰分為兩個部分,開始的28位稱為C[0],最后的28位稱為D[0]

C[i-1],D[i-1]作為下一輪i的輸入(把C[i-1]復(fù)制給C[i],將D[i-1]復(fù)制給D[i]),之后同時將C[i]D[i]左移1位或2位,根據(jù)輪數(shù)值決定左移的位數(shù)。

左移位數(shù): 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1

C[i]D[i]合成CD[i][i]

CD[i] [i]作為一個整體按下表(PC-2)變換,得到48位的K[i]

         Permuted Choice 2 (PC-2)

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

解密過程生成的子密鑰

跟加密時產(chǎn)生子密鑰的算法基本一樣,只是每輪變成想右位移12

右移位數(shù): 0, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1

 

加解密過程

一、取得64位的數(shù)據(jù),如果數(shù)據(jù)長度不足64位,應(yīng)該將其擴(kuò)展為64位

將64位數(shù)據(jù)按下表變換(IP)

Initial Permutation (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

將變換后的數(shù)據(jù)分為兩部分,開始的32位稱為L[0],最后的32位稱為R[0]。用16個子密鑰加密數(shù)據(jù),初始i=1。每輪迭代都利用上一輪的L[i-1],R[i-1]。

L[i] = R[i-1];R[i] = Li-1⊕F(Ri-1,Ki);

二、F(Ri-1,Ki)實現(xiàn)過程:

1、將32位的R[I-1]按下表(E)擴(kuò)展為48位的E[i-1]

Expansion (E)

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

2、異或E[i-1]和K[i],即E[i-1] XOR K[i]

3、S盒替換:將異或后的結(jié)果分為8個6位長的部分,每部分成為S盒的輸入,跟有8個輸入,對應(yīng)8個S盒。如Bi=b1b2b3b4b5b6,將x=b1b6作為行號,y=b2b3b4b5作為列好,在S[i]中查找第x行第y列的值c=S[i][x][y]。將c轉(zhuǎn)化為4為2進(jìn)制,代替原來的Bi。經(jīng)過8個替換后,產(chǎn)生32位比特串。

4、P盒替換:將S盒產(chǎn)生的32位比特串經(jīng)過P盒置換,輸出結(jié)果就為F(Ri-1, Ki);

     Permutation 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

5、與L[i-1]:置換將F(Ri-1, Ki)⊕Li-1得出Ri

三、逆置換IP-1

64位的明文經(jīng)過IP置換、16輪迭代運(yùn)算、逆初始置換IP-1后,得到的結(jié)果極為DES加密的密文輸出。

 

Final Permutation (IP**-1)

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

解密過程跟加密一樣,只是加密時第i輪跟第i個子密鑰異或,而解密時16子密鑰被倒過來異或,只要在產(chǎn)生子密鑰的過程中做文章就可以實現(xiàn)加解密過程一字不差。

以下是S盒:

S盒

         Substitution Box

S[1]

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

 

S[2]

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

 

S[3]

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

 

S[4]

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

 

S[5]

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

 

S[6]

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

 

S[7]

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

 

S[8]

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

 

 

 

 

 

#include <stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
int SubKey[17][48];
int C[17][28], D[17][28], CD[17][56];
int LS[2][16= 
{
    {
1122222212222221},
    {
0122222212222221}
};
int L[17][32], R[17][32];
int en[64];
int PC1[56= 
{   
    
5749413325179,
    
1585042342618,
    
1025951433527,
    
1911360524436,
    
63554739312315,
    
7625446383022,
    
1466153453729,
    
211352820124};
int PC2[48=
{
    
1417112415,
    
3281562110,
    
2319124268,
    
1672720132,
    
415231374755,
    
304051453348,
    
444939563453,
    
464250362932};
int IP[64=
{
    
585042342618102,
    
605244362820124,
    
625446383022146,
    
645648403224168,
    
57494133251791,
    
595143352719113,
    
615345372921135,
    
635547393123157};
int E[48= 
{
    
3212345,
    
456789,
    
8910111213,
    
121314151617,
    
161718192021,
    
202122232425,
    
242526272829,
    
28293031321};
int S[8][4][16= 
{
    
//S[1]
    1441312151183106125907,
    
0157414213110612119538,
    
4114813621115129731050,
    
1512824917511314100613,
 
    
//S[2]
    1518146113497213120510,
    
3134715281412011069115,
    
0147111041315812693215,
    
1381013154211671205149,
     
    
//S[3]
    1009146315511312711428,
    
1370934610285141211151,
    
1364981530111212510147,
    
1101306987415143115212,
    
    
//S[4]
    7131430691012851112415,
    
1381156150347212110149,
    
1069012117131513145284,
    
3150610113894511127214,
    
    
//S[5]
    2124171011685315130149,
    
1411212471315015103986,
    
4211110137815912563014,
    
1181271142136150910453,
    
    
//S[6]
    1211015926801334147511,
    
1015427129561131401138,
    
9141552812370410113116,
    
4321295151011141760813,
     
    
//S[7]
    4112141508133129751061,
    
1301174911014351221586,
    
1411131237141015680592,
    
6111381410795015142312,
     
    
//S[8]
    1328461511110931450127,
    
1151381037412561101492,
    
7114191214206101315358,
    
2114741081315129035611
};
int P[32=
{
    
1672021,
    
29122817,
    
1152326,
    
5183110,
    
282414,
    
322739,
    
1913306,
    
2211425};
int RIP[64=
{
    
408481656246432,
    
397471555236331,
    
386461454226230,
    
375451353216129,
    
364441252206028,
    
353431151195927,
    
342421050185826,
    
33141949175725,
};
void LR(int * inint *outint ls)//將in左移ls位存到out 
{
    
int i;
    
for (i = 0; i < ls; i++)
        
out[28 - ls + i] = in[i];
    
for (i = ls; i < 28; i++)
        
out[i-ls] = in[i];
}
void RR(int * inint * outint ls)//將in右移ls位存到out 
{
    
int i;
    
for (i = 0; i < 28 - ls; i++)
        
out[i+ls] = in[i];
    
for (i = 28 - ls; i < 28; i++)
        
out[i - (28 - ls)] = in[i];
}
//Key是64位密鑰,f為0表示該過程是產(chǎn)生加密的子密鑰,f為1表示該過程是產(chǎn)生解密的子密鑰 
//因為加密過程產(chǎn)生的16個子密鑰,在解密時時倒過來的。之所以會這樣主要是加密過程是左移操作,解密是右移操作 
void CreateSubKey(int * Key, int f)
{
    
int i, j;
    
for (i = 0; i < 56; i++)
        CD[
0][i] = Key[PC1[i]-1];
    
for (i = 0; i < 28; i++)
    {
        C[
0][i] = CD[0][i];
        
//printf("%d", C[0][i]);
    }//printf("--");
    for (i = 28; i < 56; i++)
    {
        D[
0][i-28= CD[0][i];
        
//printf("%d", D[0][i-28]);    
    }//printf("\n");
    for (i = 1; i <= 16; i++)
    {
        
if (f == 0)
        {
            LR(C[i
-1], C[i], LS[f][i-1]);
            LR(D[i
-1], D[i], LS[f][i-1]);
        }
        
else
        {
            RR(C[i
-1], C[i], LS[f][i-1]);
            RR(D[i
-1], D[i], LS[f][i-1]);
        }
    
//    printf("ls%d:", LS[f][i-1]);for (j = 0; j < 28; j++)printf("%d", C[i][j]);
//        printf("--");for (j = 0; j < 28; j++)printf("%d", D[i][j]);printf("\n");
    
        
for (j = 0; j < 28; j++)
        {
            CD[i][j] 
= C[i][j];
            CD[i][j
+28= D[i][j];
        }
        
for (j = 0; j < 48; j++)
        {
            SubKey[i][j] 
= CD[i][PC2[j]-1];
        }
    
//    printf("i=%d:", i);
//        for (j = 0; j < 48; j++)
//        {
//            printf("%d", SubKey[i][j]);
//        }printf("\n");
    }
}
void ip(int *mw)//IP置換,64為明文經(jīng)過IP置換產(chǎn)生L0和R0 
{
    
int i;
    
for (i = 0; i < 64; i++)
    {
        
if (i < 32)
            L[
0][i] = mw[IP[i]-1];
        
else
            R[
0][i-32= mw[IP[i]-1];
    }
}
void ebox(int * inint *out)//e盒,in為輸入,結(jié)果為out 
{
    
int i;
    
for (i = 0; i < 48; i++)
        
out[i] = in[E[i]-1];
}
void xorK(int * key, int * in)//將in與key異或 
{
    
int i;
    
for (i = 0; i < 48; i++)
        
in[i] = in[i] ^ key[i];
}
void sbox(int * inint * out)//s盒,in為輸入,結(jié)果為out 
{
    
int i, x, y, z;
    
for (i = 0; i < 8; i++)
    {
        x 
= (in[0<< 1+ in[5];
        y 
= (in[1<< 3+ (in[2<< 2+ (in[3<< 1+ in[4];
        z 
= S[i][x][y];
    
//    out[0] = z & 1;
//        out[1] = (z >> 1) & 1;
//        out[2] = (z >> 2) & 1;
//        out[3] = (z >> 3) & 1;

        
out[0= (z >> 3& 1;
        
out[1= (z >> 2& 1;
        
out[2= (z >> 1& 1;
        
out[3=  z & 1;
        
in += 6out += 4
    }
}
void pbox(int * inint * out)//P盒置換in為輸入,結(jié)果存于out 
{
    
int i;
    
for (i = 0; i < 32; i++
        
out[i] = in[P[i]-1];
}
void fun(int * ri, int * ki, int * out)//將R[i-1],Key[i]作為輸入進(jìn)行F(Ri-1,Ki)存于out 
{
    
int tmp[48], res[32];
    ebox(ri, tmp);
//將Ri進(jìn)行E盒置換存于tmp 
    xorK(ki, tmp);//將tmp與子密鑰異或仍存于tmp 
    sbox(tmp, res);//將tmp進(jìn)行S盒置換存于res 
    pbox(res, out);//將res進(jìn)行P盒置換存于out 

void xorLi(int * li, int * inint * out)//li為Li-1,將F(Ri-1,Ki)的結(jié)果作為in,out = Li-1 ^ F(Ri-1, Ki); 
{
    
int i;
    
for (i = 0; i < 32; i++)
        
out[i] = in[i] ^ li[i];
}
void Rip(int * l, int * r, int * out)//逆置換IP-1,將L16跟R16作為輸入,結(jié)果存于out中 
{
    
int lr[64], i;
    
for (i = 0; i < 32; i++)
        lr[i] 
= r[i];
    
for (i = 32; i < 64; i++)
        lr[i] 
= l[i-32];
    
for (i = 0; i < 64; i++)
        
out[i] = lr[RIP[i]-1];
}
int Binary_To_Decimal(int *bit, int len)//將一個8位2進(jìn)制轉(zhuǎn)為一個10進(jìn)制數(shù) 
{
    
int sum = 0, i;
    
for (i = 0; i < len; i++)
    {
        sum 
= sum * 2 + bit[i];
    }
    
return sum;
}
void asc(int * w, int len, char * as)//將64bit轉(zhuǎn)化成一字符串 
{
    
int *= w;
    
int i, j;
    
for (i = 0, j = 0; i < 64; i += 8, p += 8, j++)
    {
        
as[j] = Binary_To_Decimal(p, 8);
    }
    
as[j] = 0;
    puts(
as);
}
void OX(int * w, int len, char * ans)//將64bit轉(zhuǎn)化成16進(jìn)制 
{
    
int i, j, k, a;
    
int * p = w;
    
for (i = 0, k = 0; i < len; k++, i = j)
    {
        j 
= i + 4;
        
if (j > len)
        {
            j 
= len;
        }
        a 
= Binary_To_Decimal(p + i, j - i);
        
if (a <= 9)
        {
            ans[k] 
= a + '0';
        }
        
else
        {
            ans[k] 
= a - 10 + 'A';
        }
    }
    ans[k] 
= 0;
    puts(ans);
}
int str_to_bit(char * inint * out)//將字符串in轉(zhuǎn)化為二進(jìn)制數(shù)組,返回二進(jìn)制數(shù)組的長度 
{
    
char tmp[1000];
    
int i, j, len, k;
    strcpy(tmp, 
in);
    len 
= strlen(tmp);
    
if (len % 8 != 0)
    {
        j 
= len / 8 * 8+ 8;//printf("%d ", j);
        for (; len < j; len++)
            tmp[len] 
= ' ';
        tmp[len] 
= 0;
    }
    
//printf("%s_\n", tmp);
    for (i = 0, j = 0; tmp[i]; i++)
    {
        
for (k = 7; k >= 0; k--, j++)
        {
            
out[j] = (tmp[i] >> k) & 1;
        }
    }
    
return j;
}
void cry(int * mw, int * ans)//加解密,結(jié)果為ans 
{
    
int tmp[32];
    
int i, j;
    
char ox[100];
    ip(mw);
    
for (i = 1; i <= 16; i++)
    {
        
for (j = 0; j < 32; j++)
            L[i][j] 
= R[i-1][j];
        fun(R[i
-1], SubKey[i], tmp);
        xorLi(L[i
-1], tmp, R[i]); 
    }
    Rip(L[
16], R[16], ans);
    
for (printf("ans:\n"), i = 0; i < 64; i++)
    {
        
if (i % 8 == 0)printf("\n");
        printf(
"%d", ans[i]);
    }printf(
"\n");
    asc(ans, 
64, ox);
    
//OX(en, 64, ox);
}
void crying(int * mw, int * ans, int len)//加解密,結(jié)果為ans 
{
    
int i;
    
char ox[100];
    
for (i = 0; i < len; i += 64)
    {
        cry(mw, ans);
        mw 
+= 64, ans += 64;
    }
}
/*
learning
computer
*/
int main()
{
    
int key[64= 
    {
        
1,1,0,0,0,1,1,0,
        
1,1,0,1,1,1,1,0,
        
1,1,0,1,1,0,1,1,
        
1,1,1,0,0,0,0,1,
        
1,1,1,0,1,0,1,1,
        
1,1,1,0,1,0,0,0,
        
1,1,0,0,1,0,1,0,
        
1,1,1,0,0,1,0,0};
    
int mw[1000=
    {
        
0,1,1,0,1,1,0,0,
        
0,1,1,0,0,1,0,1,
        
0,1,1,0,0,0,0,1,
        
0,1,1,1,0,0,1,0,
        
0,1,1,0,1,1,1,0,
        
0,1,1,0,1,0,0,1,
        
0,1,1,0,1,1,1,0,
        
0,1,1,0,0,1,1,1
    };
    
int ans[1000], len;
    
char strm[1000], strk[10];
    
while (scanf("%s%s", strm, strk) - EOF)
    {
        len 
= str_to_bit(strm, mw);
        CreateSubKey(key, 
0);
        crying(mw, ans, len);
        CreateSubKey(key, 
1);
        crying(ans, ans, len);
        
//puts(ans);
    }  
    system(
"pause");
}
/*
learinglearingleari
computer
*/