注: 下述全部加法均爲模二加, 即爲亦或運算c++
接下來咱們以輸入的祕鑰爲"0x123456789abcdeff"
爲例, 及二進制編碼爲:算法
"0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 1111"
編碼圖1.2.1 初始祕鑰K_0
接下來咱們利用PC-1表
生成新祕鑰K_1
加密
圖1.2.2 挑出的56位二進制串
"1111 0000 1100 1100 1010 1010 1111"和"1101 0101 1110 0110 1111 1000 1111"
spa兩邊各是28位, 共56位code
對於從1.2得來的一串56位二進制碼
, 咱們將其拆分紅兩串28位二進制碼
, 即爲:blog
左半部分的
"1111 0000 1100 1100 1010 1010 1111"
, 並將其命名爲C_0ip右半部分的
"1101 0101 1110 0110 1111 1000 1111"
, 並將其命名爲D_0字符串
接下來, 咱們利用下表, 進行循環左移, 規則以下:it
以後咱們按照上面的規則, 展現子祕鑰k_1
是如何生成的:
- 將C_0和D_0分別循環左移1位, 獲得
C_1-"1110 0001 1001 1001 0101 0101 1111"
以及D_1-"1010 1011 1100 1101 1111 0001 1111"
(PS:循環左移1位就是將首位移動到最後末尾)- 將C_1即D_1拼接起來, 獲得
"1110 0001 1001 1001 0101 0101 1111 1010 1011 1100 1101 1111 0001 1111"
- 利用PC-2表從拼接獲得的字符串中挑選出
子祕鑰k_1
, 相似於"利用PC-1表的過程"圖1.3.2 從C_0和D_0中生成的子祕鑰k_0
- 因此
子祕鑰k_1爲"0001 1011 0000 0010 1110 1111 1111 1100 0111 1001 0111 0110"
按照一樣的邏輯, 在C_0和D_0已被循環左移的基礎上, 重複上述步驟, 咱們獲得以下16個子祕鑰:
PS: 上述輸出爲本身寫的代碼, 在文末會進行展現.
獲得了這16個子祕鑰後, 咱們就能夠對明文進行加密了, 咱們繼續!
咱們以輸入的明文爲"0x0123456789abcdef"
爲例, 即二進制編碼爲:
"0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111"
通過變換後,獲得:
"1100 1100 0000 0000 1100 1100 1111 1111 1111 0000 1010 1110 1111 0000 1010 1010"
將其拆分爲L_0及R_0, 各32位
L_0:
"1100 1100 0000 0000 1100 1100 1111 1111"
R_0:
"1111 0000 1010 1110 1111 0000 1010 1010"
對R_0使用以下規則擴展成48位:
圖2.2.1 R_0擴展成48位規則 PS: 綠色的標出的位數即爲擴展出的12位
所以, 獲得RExtend(8個6位):
"011110 100001 010101 011101 011110 100001 010101 010101"
將其與子祕鑰
"0001 1011 0000 0010 1110 1111 1111 1100 0111 1001 0111 0110"
亦或得S盒
"0110 0001 0001 0111 1011 0010 1000 0110 0110 1100 0010 0011"
爲何上面S盒要備註8個6位呢? 緣由就是要以8個6位爲輸入, 分別通過S1-S8盒的運算,獲得8個4位輸出, 也就變成了32位.
圖2.3.1 S1-S8表 咱們的S盒長這樣
"011000 010001 011110 110010 100001 100110 110000 100011"
以第一個6位
"011000"
爲輸入, 代入到S1表變換以
"011000"
的首位和末尾拼起來的數字爲行號, 中間4位爲列號(固然都是二進制的), 即第0(00b)行, 第15(1100b)列, 查詢S1表, 爲S1(0, 12) = 5 = 0101b這樣就能夠獲得第一個4位的輸出, 按照這樣的方式能夠獲得8個4位的輸出, 合在一塊兒就是一個32位的輸出, 通過運算是
"0101 1100 1000 0001 1011 0101 1010 0001"
咱們已經獲得通過"擴位"和"縮位"
的變換, 如今要按照P表進行簡單的位置變換:
圖2.4.1 P表 圖2.4.2 32位輸出的每一位狀況 照着P表生成新的32位輸出
"1010 0001 0000 1000 1010 1101 1001 1011"
再將輸出與L_0相加, L_0:
"1100 1100 0000 0000 1100 1100 1111 1111"
獲得結果:
"0110 1101 0000 1000 0110 0001 0110 0100"
如題, 獲得最終結果:
"1110 1100 1010 1001 0011 1101 1001 1100 1110 0100 1101 1001 1001 1001 1100 1110"
/* * @Description: * @Autor: Shmily * @Date: 2021-03-01 23:40:00 * @LastEditTime: 2021-03-02 22:35:49 */ #include <bits/stdc++.h> using namespace std; const int8_t PC_1[56] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 28, 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 }; const int8_t PC_2[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 }; const int8_t left_move[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; const int8_t S8[8][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} } }; const int8_t PTable[32] = { 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, 4, 22, 11, 4, 25 }; const int8_t IP[2][64] = { { 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, 16, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }, { 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 } }; void out_int8_t(int8_t* out, int len) { for (int i = 0; i < len; i++) { printf("%d", out[i]); if ((i + 1) % 4 == 0) cout << " "; } cout << endl; } void fun_left_move(int8_t* C_0, int8_t* D_0, int times_left) { for (int i = 0; i < times_left; i++) { int8_t temp1 = C_0[0]; int8_t temp2 = D_0[0]; for (int j = 1; j < 28; j++) { C_0[j - 1] = C_0[j]; D_0[j - 1] = D_0[j]; } C_0[27] = temp1; D_0[27] = temp2; } } void Extend32To48(int8_t (*R) [32], int8_t (*RExtend) [48], int times) { RExtend[times][0] = R[times][31]; RExtend[times][47] = R[times][0]; for (int i = 1; i < 47; i++) { // 6個位一組, 即爲一行 int LineNumber = (int)(i / 6); RExtend[times][i] = R[times][i - 1 - LineNumber*2]; } } void XOR(int8_t (*RExtend) [48], int8_t (*k) [48], int8_t (*S) [48], int times) { for (int i = 0; i < 48; i++) { // 進行模二加運算 S[times][i] = (RExtend[times][i] + k[times][i]) % 2; } } void XOR(int8_t (*L) [32], int8_t (*Pchanged) [32], int8_t (*R) [32], int times) { for (int i = 0; i < 32; i++) { R[times + 1][i] = (L[times][i] + Pchanged[times][i]) % 2; } } void UseS48To32(int8_t (*S) [48], int8_t (*P) [32], int times) { for (int i = 0; i < 8; i++) { int line = 0, row = 0; // 計算出行號及列號 line = line + S[times][i*6]*2 + S[times][5 + i*6]; row = row + S[times][1 + i*6]*8 + S[times][2 + i*6]*4 + S[times][3 + i*6]*2 + S[times][4 + i*6]; // 從S表中挑出答案 int8_t ans = S8[i][line][row]; for (int j = 0; j < 4; j++) { int subtrahend = pow(2, (3 - j)); if (ans - subtrahend >= 0) { P[times][j + i*4] = 1; ans -= subtrahend; } else P[times][j + i*4] = 0; } } } void UsePChangeP(int8_t (*P) [32], int8_t (*PChanged) [32], int times) { for (int i = 0; i < 32; i++) { PChanged[times][i] = P[times][PTable[i] - 1]; } } void UseIPChange(int8_t* in, int8_t* out, int8_t choice) { for (int i = 0; i < 64; i++) { out[i] = in[IP[choice][i] - 1]; } } int main(void) { // 對祕鑰進行處理 // 輸入爲64位祕鑰, 輸出位16個32位子祕鑰 int8_t K_0[64], K_1[56], k[16][48]; // 祕鑰爲"0x123456789abcdeff" char in[] = "0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 1111"; int len = strlen(in); // 將輸入的祕鑰存儲到K_0中 for (int i = 0, j = 0; i < len; i++) { if (in[i] == '0') K_0[j++] = 0; else if (in[i] == '1') K_0[j++] = 1; } // 利用PC-0表, 從K_0中取出K_1 for (int i = 0; i < 56; i++) { // 注意-1 K_1[i] = K_0[PC_1[i]-1]; } // 上述完成了第一步利用PC-1表 // 接下來利用PC-2表 int8_t C_0[28], D_0[28]; // 將K_1拆分 for (int i = 0; i < 56; i++) { if (i < 28) C_0[i] = K_1[i]; else D_0[i - 28] = K_1[i]; } // 循環16次生成16個子祕鑰 for (int i = 0; i < 16; i++) { int8_t times_left = left_move[i]; fun_left_move(C_0, D_0, times_left); for (int j = 0; j < 48; j++) { int8_t sub = PC_2[j] - 1; if (sub < 28) k[i][j] = C_0[sub]; else k[i][j] = D_0[sub - 28]; } // printf("子祕鑰k[%.2d]: ", i + 1); // out_int8_t(k[i], 48); } // 對明文進行處理 // 明文爲"0x0123456789abcdef" char in_text[] = "0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111"; int8_t PlainText[64], IP_PlainText[64], EnchiperTextInitial[64], EnchiperText[64]; int8_t L[17][32], R[17][32], RExtend[16][48], S[16][48], P[16][32], PChanged[16][32]; int len_text = strlen(in_text); // 64位明文存儲到PlainText中 for (int i = 0, j = 0; i < len; i++) { if (in_text[i] == '0') PlainText[j++] = 0; else if (in_text[i] == '1') PlainText[j++] = 1; } // 使用IP對PlainText進行變換 UseIPChange(PlainText, IP_PlainText, 0); // 將PlainText分左右存儲到L_0及R_0中 for (int i = 0; i < 64; i++) { if (i < 32) L[0][i] = IP_PlainText[i]; else R[0][i - 32] = IP_PlainText[i]; } // 循環16次 for (int times = 0; times < 16; times++) { // L_n = R_n-1 for (int i = 0; i < 32; i++) { L[times + 1][i] = R[times][i]; } // L_n = L_n-1 + f(R_n-1, k_n) // 對R進行擴展 Extend32To48(R, RExtend, times); // 將RExtend與k_n-1模二加 XOR(RExtend, k, S, times); // 使用S表將S盒48位壓縮成32位 UseS48To32(S, P, times); // 使用P表對P進行位置變換 UsePChangeP(P, PChanged, times); // 生成的PChanged就是通過f以後的 // 模二加後放入R_n XOR(L, PChanged, R, times); } for (int i = 0; i < 64; i++) { if (i < 32) EnchiperTextInitial[i] = R[16][i]; else EnchiperTextInitial[i] = L[16][i - 32]; } // 使用IP^-1對EnchiperTextInitial的進行變換獲得Enchiper UseIPChange(EnchiperTextInitial, EnchiperText, 1); //最終結果輸出 out_int8_t(EnchiperText, 64); return 0; }