1. 程式人生 > >[DESN演算法] 資訊保安概論

[DESN演算法] 資訊保安概論

//通訊雙方同時掌握一個金鑰,加密解密都是一個金鑰完成的。通訊雙方協定一個金鑰,不予公開。通訊雙方掌握不同金鑰,不同方向加解密由
//不同祕鑰完成
//對稱加密演算法代表 DES演算法   
// 利用58+8奇偶校驗位 8,16,24,32,30,48,56,64 位的金鑰對以64位為單位的塊數進行加密。 
#include <iostream>
#include <string>

using namespace std;

//  IP 初始置換表
const static int IP_TABLE[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, 19, 11, 3,
        61, 53, 45, 37, 29, 21, 13, 5,
        63, 55, 47, 39, 31, 23, 15, 7
};

//  E 擴充套件表
const static int E_TABLE[48] = {
        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
};

//  P 盒
const static int P_TABLE[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, 6, 22, 11, 4, 25
};

//  IP 逆置換表
const static int IPR_TABLE[64] = {
        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
};

//  金鑰第一次置換表
const static int PC1_TABLE[56] = {
        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
};

//  金鑰第二次置換表
const int PC2_TABLE[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
};

//  S 盒
const static int S_BOX[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
        }
};

// 生成的 sub key,在第 1、2、9、16 輪迴圈左移 1 位,其他輪迴圈左移 2 位
// 這裡為了使下標對應迴圈次數,在開頭設定一位無用的0
const static int LEFT_SHIFT_TIMES[17] = {
        0, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};

/*
 *  將 char 型轉化為二進位制形式
 */
void char_to_bits(const char input[8], int output[64]) {

    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            output[7 * (i + 1) - j + i] = (input[i] >> j) & 1;
        }
    }
}

/*
 *  將二進位制形式轉化為 char 型
 */
void bits_to_char(const int input[64], char output[8]) {
    for (int i = 0; i < 8; i++) {           
        for (int j = 0; j < 8; j++) {        
            output[i] = (char) (output[i] * 2 + input[8 * i + j]);
        }
    }
}

/*
 *  異或函式
 *  將陣列 arr_1 和 arr_2 進行異或操作,並且儲存在 arr_1 中
 *  op_len 是進行異或的位數
 */
void arr_xor(int *arr_1, const int *arr_2, const int op_len) {
    for (int i = 0; i < op_len; i++) {
        arr_1[i] = arr_1[i] ^ arr_2[i];
    }
}

/*
 *  IP 初始置換函式
 *  IP 根據 IP 初始置換表進行初始置換
 */
void pass_ip(const int input[64], int output[64]) {
    for (int i = 0; i < 64; i++) {
        output[i] = input[IP_TABLE[i] - 1];
    }
}

/*
 *  E 擴充套件置換函式
 *  根據 E 擴充套件表進行擴充套件
 */
void pass_ext(const int input[32], int output[48]) {
    for (int i = 0; i < 48; i++) {
        output[i] = input[E_TABLE[i] - 1];
    }
}

/*
 *  P 置換函式
 *  根據 P 盒進行置換
 */
void pass_p_box(const int input[32], int output[32]) {
    for (int i = 0; i < 32; i++) {
        output[i] = input[P_TABLE[i] - 1];
    }
}

/*
 *  IP 逆置換函式
 *  IP 根據 IP 逆置換表進行置換
 */
void pass_ipr(const int input[64], int output[64]) {
    for (int i = 0; i < 64; i++) {
        output[i] = input[IPR_TABLE[i] - 1];
    }
}

/*
 *  密匙第一次置換函式
 *  根據密匙第一次置換表進行置換
 */
void pass_pc_1(const int input[64], int output[56]) {
    for (int i = 0; i < 56; i++) {
        output[i] = input[PC1_TABLE[i] - 1];
    }
}

/*
 *  密匙第二次置換函式
 *  根據密匙第二次置換表進行置換
 */
void pass_pc_2(const int input[56], int output[48]) {
    for (int i = 0; i < 48; i++) {
        output[i] = input[PC2_TABLE[i] - 1];
    }
}

/*
 *  S 盒壓縮函式
 *  根據 8 個 S 盒進行壓縮
 */
void pass_s_box(const int input[48], int output[32]) {
    int INT[8];
    for (int i = 0, j = 0; i < 48; i = i + 6, j++) {
        int row = (input[i] << 1) + (input[i + 5]);
        int column = (input[i + 1] << 3) + (input[i + 2] << 2) + (input[i + 3] << 1) + (input[i + 4]);
        INT[j] = S_BOX[j][row][column];
    }
    for (int j = 0; j < 8; j++) {
        for (int i = 0; i < 4; i++) {
            output[3 * (j + 1) - i + j] = (INT[j] >> i) & 1;
        }
    }
}

/*
 *  輪迭代函式
*/
void f_func(const int input[32], int output[32], int sub_key[48]) {
    int after_ext[48] = {0};
    int after_s_box[32] = {0};
    pass_ext(input, after_ext);
    arr_xor(after_ext, sub_key, 48);
    pass_s_box(after_ext, after_s_box);
    pass_p_box(after_s_box, output);
}

/*
 *  密匙迴圈左移函式
 *  密匙在不同輪數都要進行不同的左移操作
 */
void rotate_left_shift(const int input[28], int output[28], int leftCount) {
    for (int i = 0; i < 28; i++) {
        output[i] = input[(i + leftCount) % 28];
    }
}

/*
 *  子密匙生成函式
 *  生成 subKey,在第 1、2、9、16 輪迴圈左移 1 位,其他輪迴圈左移 2 位
 */
void gen_sub_key(const int input[64], int sub_keys[16][48]) {
    int c[28], d[28];
    int pc_1[56] = {0};
    int pc_2[16][56] = {0};
    int rotate_l_c[16][28] = {0};
    int rotate_l_d[16][28] = {0};

    // 經過第一次 pc 置換
    pass_pc_1(input, pc_1);
    for (int i = 0; i < 28; i++) {
        c[i] = pc_1[i];
        d[i] = pc_1[i + 28];
    }

    // 迴圈左移
    for (int i = 1; i < 17; i++) {
        rotate_left_shift(c, rotate_l_c[i - 1], LEFT_SHIFT_TIMES[i]);
        rotate_left_shift(d, rotate_l_d[i - 1], LEFT_SHIFT_TIMES[i]);
    }

    // 合併
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 28; j++) {
            pc_2[i][j] = rotate_l_c[i][j];
            pc_2[i][j + 28] = rotate_l_d[i][j];
        }
    }

    // 經過第二次 pc 置換
    for (int i = 0; i < 16; i++) {
        pass_pc_2(pc_2[i], sub_keys[i]);
    }
}

/*
 *  DES 加密函式
 *  傳入明文 input 和密匙 inKey,獲取 64 位二進位制密文 output
 */
void encrypt(const char input[8], char key[8], int output[64]) {
    int ip[64] = {0};
    int output_1[64] = {0};
    int sub_keys[16][48];
    int char_to_bit[64] = {0};
    int bin_key[64];
    int l[17][32], r[17][32];

    char_to_bits(input, char_to_bit);
    pass_ip(char_to_bit, ip);
    char_to_bits(key, bin_key);
    gen_sub_key(bin_key, sub_keys);

    for (int i = 0; i < 32; i++) {
        l[0][i] = ip[i];
        r[0][i] = ip[32 + i];
    }
    for (int j = 1; j < 17; j++) {
        for (int k = 0; k < 32; k++) {
            if (j == 16) {    //  第 16 輪迭代特殊處理
                r[j][k] = r[j - 1][k];
            } else {
                l[j][k] = r[j - 1][k];
            }
        }
        if (j == 16) {    //  第 16 輪迭代特殊處理
            f_func(r[j - 1], l[j], sub_keys[j - 1]);
            arr_xor(l[j], l[j - 1], 32);
        } else {
            f_func(r[j - 1], r[j], sub_keys[j - 1]);
            arr_xor(r[j], l[j - 1], 32);
        }
    }

    for (int t = 0; t < 32; t++) {
        output_1[t] = l[16][t];
        output_1[32 + t] = r[16][t];
    }
    pass_ipr(output_1, output);
}

/*
 *  DES 解密函式
 *  傳入 64 位二進位制密文 input 和密匙 key 獲取明文 output
 */
void decrypt(const int input[64], const char key[64], char output[64]) {
    int after_ip[64] = {0};
    int output_1[64] = {0};
    int output_2[64] = {0};
    int sub_keys[16][48];
    int bin_key[64];
    int l[17][32], r[17][32];

    pass_ip(input, after_ip);
    char_to_bits(key, bin_key);
    gen_sub_key(bin_key, sub_keys);
    for (int i = 0; i < 32; i++) {
        l[0][i] = after_ip[i];
        
        r[0][i] = after_ip[32 + i];
    }

    // 16次迭代處理
    for (int j = 1; j < 17; j++) {
    	
        for (int k = 0; k < 32; k++) {
            if (j == 16) {    //  第 16 輪迭代特殊處理
                r[j][k] = r[j - 1][k];
            } else {
                l[j][k] = r[j - 1][k];
            }
        }
        if (j == 16) {    //  第 16 輪迭代特殊處理
            // 解密時,子金鑰反過來用
            f_func(r[j - 1], l[j], sub_keys[16 - j]);
            arr_xor(l[j], l[j - 1], 32);
        } else {
            // 解密時,子金鑰反過來用
            f_func(r[j - 1], r[j], sub_keys[16 - j]);
            arr_xor(r[j], l[j - 1], 32);
        }
    }

    for (int t = 0; t < 32; t++) {
        output_1[t] = l[16][t];
        output_1[32 + t] = r[16][t];
    }
    pass_ipr(output_1, output_2);
    bits_to_char(output_2, output);
}


int main() {

    int encrypted[64] = {0};
    // 字元陣列最後要有一個'\0' 因此長一位
    char origin[9] = {0};
    char key[9] = {0};

    cout << "請輸入8位明文: " << endl;
    cin >> origin;
    cout << "請輸入8位金鑰: " << endl;
    cin >> key;

    encrypt(origin, key, encrypted);

    cout << "加密後: " << endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 16; j++) {
            cout << encrypted[i * 4 + j];
        }
        cout << endl;
    }

    decrypt(encrypted, key, origin);

    cout << "解密後: " << endl;
    cout << origin;

    return 0;
}