?? des算法實現過程分析 之 c++實踐篇.txt
字號:
// 標 題: DES算法實現過程分析 之 C++實踐篇
// DES算法實現過程分析
// 引自綠色兵團(http://www.isbase.com)
// dapingguo修改并算法用C++實現
#include <stdio.h>
void expand(const unsigned char in[32],unsigned char out[48])
{
unsigned char table4[48]={ 31, 0, 1, 2, 3, 4,
3, 4, 5, 6, 7, 8,
7, 8, 9, 10, 11, 12,
11, 12, 13, 14, 15, 16,
15, 16, 17, 18, 19, 20,
19, 20, 21, 22, 23, 24,
23, 24, 25, 26, 27, 28,
27, 28, 29, 30, 31, 0 };
for (int i=0;i<48;i++) out[i]=in[table4[i]]; }
void keys(const unsigned char password[8], unsigned char K[16][48])
//根據密鑰password計算16個子密鑰K[16][48]
{
int i,j;
unsigned char key[64];
//1. 處理密鑰:
//1.1 從用戶處獲得64位密鑰.(每第8位為校驗位,為使密鑰有正確的奇偶校
// 驗,每個密鑰要有奇數個'1'位.),得key[64];
for (i=0;i<64;i++) {
int byte=i/8;
int bit=i%8;
int value=password[byte];
value>>=bit; value&=1;
key[i]= value?1:0;
}
//1.2 具體過程:
//1.2.1 對密鑰key[64]實施換位變換得密鑰keyT[56].
// (keyT[i]=key[j]; i=0..55, j值如下表,顯然,忽略了校驗位)
unsigned char keyT[56];
unsigned char table1[56]={56, 48, 40, 32, 24, 16, 8, 0,
57, 49, 41, 33, 25, 17, 9, 1,
58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6,
61, 53, 45, 37, 29, 21, 13, 5,
60, 52, 44, 36, 28, 20, 12, 4,
27, 19, 11, 3 };
for (i=0; i<56; i++) keyT[i]=key[table1[i]];
//1.2.2 把變換后的密鑰等分成兩部分,前28位記為C, 后28位記為D.
unsigned char *C=keyT;
unsigned char *D=keyT+28;
//1.2.3 計算子密鑰(共16個), 從i=0開始。
for (i=0; i<16; i++){
//1.2.3.1 分別對C,D作循環左移
// 每次循環左移位數如下表所示:
// 循環次數i 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15
// 左移位數 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
char loop[16]= {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
unsigned char tmp[28];
int n=loop[i];
int j;
for (j=0; j<28; j++) tmp[j]=C[(j+28-n)%28];
for (j=0; j<28; j++) C[j]=tmp[j];
for (j=0; j<28; j++) tmp[j]=D[(j+28-n)%28];
for (j=0; j<28; j++) D[j]=tmp[j];
//1.2.3.2 串聯C,D,得到一個56位數CD[56],然后對此數作如下換位變換
// 以產生48位子密鑰K[i][48]。
unsigned char *CD=keyT;
unsigned char table2[48]=
{13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
for (j=0;j<48;j++)
K[i][j]=CD[table2[j]];
//1.2.3.3 按以上方法計算出16個子密鑰K[16][48]。
}
}
void des(const unsigned char datain[8], unsigned char dataout[8],
const unsigned char K[16][48], const unsigned char mode)
//根據密鑰K[16][48]和mode加密或解密數據塊data[8],
//處理后的數據放在dataout[8]中
{
//2.對64位數據塊的處理:
//2.1 把數據分成64位的數據塊DATA[64],不夠64位的以適當的方式填補。
unsigned char DATA[64];
int i,j;
for (i=0;i<64;i++) {
int byte=i/8;
int bit=i%8;
int value=datain[byte];
value>>=bit;
value&=1;
DATA[i]= value;
}
//2.2 對數據塊DATA[64]作換位變換為data[64]。
unsigned char data[64];
unsigned char table3[64]= { 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,
56, 48, 40, 32, 24, 16, 8, 0,
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6 };
for (i=0;i<64;i++) data[i]=DATA[table3[i]];
//2.3 將變換后的數據塊等分成前后兩部分,前32位記為L[0],后32位記為R[0]。
unsigned char L[17][32];
unsigned char R[17][32];
for (i=0; i<32; i++) L[0][i]=data[i];
for (i=0; i<32; i++) R[0][i]=data[i+32];
unsigned char s[8][4][16]={
/* 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 };
unsigned char R_[48];
//2.4 用16個子密鑰對數據加密。從i=0開始。
for (i=0; i<16; i++) {
//2.4.1 根據下面表格擴充32位數據R[i]為48位數據R'。
expand(R[i],R_);
//2.4.2 用R'[48]與K[i][48]作異或運算。
for (j=0;j<48;j++)
if (mode) R_[j]^=K[i][j];
else R_[j]^=K[16-1-i][j];
//2.4.3 把所得的48位數分成8個6位數B[8]。
// 1-6位為B[0],7-12位為B[1],……,43-48位為B[7]。
unsigned char B[8];
for (j=0; j<8; j++){ B[j]=0;
for (int k=0; k<6; k++)
B[j]|=(R_[j*6+k]<<(6-1-k));}
//2.4.4 用S密箱里的值替換B[j]。
// 從j=0開始。S密箱里的值為4位數,共8個S密箱
for (j=0; j<8; j++){
//2.4.4.1 取出B[j]的第1和第6位串聯起來成一個2位數,記為m.。
// m即是S密箱里用來替換B[j]的數所在的列數。
//2.4.4.2 取出B[j]的第2至第5位串聯起來成一個4位數,記為n。
// n即是S密箱里用來替換B[j]的數所在的行數。
int m=0; int n=0;
m|=(B[j]&0x1); m|=((B[j]>>4)&0x2);
n=(B[j]>>1); n&=0x0f;
//2.4.4.3 用S密箱里的值S[j][m][n]替換B[j]。
B[j]=s[j][m][n];
//2.4.4.4 返回2.4.4.1直至8個數據塊都被替換。
}
//2.4.5 把B[0]至B[7] 順序串聯起來得到一個32位數tmp[32]。
unsigned char tmp[32];
for (j=0;j<32; j++)
tmp[j]= (B[j/4]>> (4-1-(j%4)))&1;
unsigned char table5[32]={
15, 6, 19, 20, 28, 11, 27, 16,
0, 14, 22, 25, 4, 17, 30, 9,
1, 7, 23, 13, 31, 26, 2, 8,
18, 12, 29, 5, 21, 10, 3, 24};
unsigned char tmp1[32];
// 對tmp[32]做作換位變換為tmp1[32]。
for (j=0;j<32;j++)
tmp1[j]=tmp[table5[j]];
//2.4.6 把得到的結果tmp1[32]與L[i][32]作異或運算。
// 把計算結果賦給R[i+1][32]。
for (j=0;j<32;j++)
R[i+1][j]=L[i][j]^tmp1[j];
//2.4.7 把R[i][32]的值賦給L[i+1][32]。
for (j=0;j<32;j++)
L[i+1][j]=R[i][j];
//2.4.8 從2.4.1循環執行,直到K[15]也被用到。
}
//2.5 把R[16]和L[16] 順序串聯起來得到一個64位數tmp2[64]。
unsigned char tmp2[64];
for (i=0;i<32;i++) tmp2[i]=R[16][i];
for (i=32;i<64;i++)tmp2[i]=L[16][i-32];
// 對這個數實施2.2變換的逆變換得out[64]。
unsigned char out[64];
for (i=0;i<64;i++) out[table3[i]]=tmp2[i];
//2. 6 out[64]即為加密過的64位數據.
for (i=0; i<8;i++){
dataout[i]=0;
for (j=0; j<8; j++)
dataout[i]|=(out[i*8+j]<<j);}
}
//以下是測試部分
void main()
{
unsigned char KEY[8]= "12345678";
unsigned char source[8]="abcdefgh";
unsigned char target[8];
unsigned char K[16][48];
keys(KEY,K);
printf("======================");
printf("\nPassword=%s\n",KEY);
printf("\nSource ");
for (int i=0;i<8;i++)
printf("%02X ",source[i]&0x0ff);
printf("\n ");
for (i=0;i<8;i++)
printf("%c ",source[i]);
#define ENCRYPT 1
des(source, target,K,ENCRYPT);
printf("\nEncrypt ");
for (i=0;i<8;i++)
printf("%02X ",target[i]&0x0ff);
printf("\n ");
for (i=0;i<8;i++)
printf("%c ",target[i]);
#define DECRYPT 0
des(target,source, K,DECRYPT);
printf("\nDecrypt ");
for (i=0;i<8;i++)
printf("%02X ",source[i]&0x0ff);
printf("\n ");
for (i=0;i<8;i++)
printf("%c ",source[i]);
printf("\n");
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -