常见密码学编码及加密算法 / Common cryptographic coding and encryption algorithms

10月 14, 2024·
Junhong Liu
Junhong Liu
· 14 分钟阅读时长

目录 / Contents

1. 费诺编码 / Ferno Encoding

此程序为费诺编码的Python实现,但此版本存在缺陷:每个编码符号出现的概率不能相同。该问题在第二个程序得到改进。

第一个程序

'''
All rights reserved by Liu Junhong
Reference books: 《信息论基础》
Completion time:2020-11-24
'''
#import numpy as np
#import pandas
#import time
import math
#import sys

#程序说明
print("-------------------<费诺编码>程序说明-------------------")
print("Designed by Junhong Liu:All rights reserved")
print("Reference books: 《信息论基础》、百度百科-费诺编码 (https://baike.baidu.com/item/%E8%B4%B9%E8%AF%BA%E7%BC%96%E7%A0%81)")
print("Completion time:2020-11-24")
print("Last modification time :2020-11-24")
print("--------------------------------------------------------")
print("\n")

#*******录入数据
N_num = float(input("请输入需要编码字符个数:"))
while(N_num <= 0 or (N_num % 1)):
    N_num = float(input("请输入正整数:"))
N_num = int(N_num)

Dict = {}
probability = 1


while(N_num > 0):
    N_num = N_num-1
    print("\n","------还需输入",N_num,"编码字符信息------")
    print("\n","请输入一个编码字符名:")
    name = str(input())
    Dict.setdefault(name)
    print("请输入小于",probability,"的对应编码字符概率:")
    value = float(input())
    probability = probability - value
    Dict[name] = value

#print(Dict)

#按概率排序
Dict_order=sorted(Dict.items(),key=lambda x:x[1],reverse=True)

#print(Dict_order)
#sys.exit(0)

#编码算法
name = []
value = []
#code = []

#truncation = 0 #保存截断位置
for i in Dict_order:
    name.append(i[0])
    value.append(i[1])
    
Fano_dict_value = {}.fromkeys(value,'')
#print(name)
#print(value)

value_copy = [value]
value_copy_copy = []

while(len(value_copy)>0):
    for k in value_copy:
        if len(k) == 2:
            Fano_dict_value[k[0]] = Fano_dict_value[k[0]] + '0'
            Fano_dict_value[k[1]] = Fano_dict_value[k[1]] + '1'
        else:
            for i in range(len(k)):
                a = sum(k[:i])
                b = sum(k[i:])
                c = sum(k[:(i+1)])
                d = sum(k[(i+1):])
                if abs(a-b)<abs(c-d):
                    if i == 1:
                        Fano_dict_value[k[0]] = Fano_dict_value[k[0]] + '0'
                        value_copy_copy.append(k[1:])
                        for h in k[1:]:
                            Fano_dict_value[h] = Fano_dict_value[h] + '1'
                    else:
                        value_copy_copy.append(k[:i])
                        value_copy_copy.append(k[i:])
                        for j in k[:i]:
                            Fano_dict_value[j] = Fano_dict_value[j] + '0'
                        for h in k[i:]:
                            Fano_dict_value[h] = Fano_dict_value[h] + '1'
                    break
    value_copy = value_copy_copy
    value_copy_copy = []

#输出结果
Fano_dict = dict(zip(name,Fano_dict_value.values()))
print(Fano_dict)

第二个程序

'''
All rights reserved by Liu Junhong
Reference books: 《信息论基础》
Completion time:2020-11-24
'''
import math

#程序说明
print("-------------------<费诺编码>程序说明-------------------")
print("Designed by 刘俊宏:All rights reserved")
print("Reference books: 《信息论基础》、百度百科-费诺编码 (https://baike.baidu.com/item/%E8%B4%B9%E8%AF%BA%E7%BC%96%E7%A0%81)")
print("Completion time:2020-11-24")
print("Last modification time :2020-11-25")
print("--------------------------------------------------------")
print("\n")

#*******录入数据
N_num = float(input("请输入需要编码字符个数:"))
while(N_num <= 0 or (N_num % 1)):
    N_num = float(input("请输入正整数:"))
N_num = int(N_num)

Dict = {}
probability = 1


while(N_num > 0):
    N_num = N_num-1
    print("\n","------还需输入",N_num,"编码字符信息------")
    print("\n","请输入一个编码字符名:")
    name = str(input())
    Dict.setdefault(name)
    print("请输入小于",probability,"的对应编码字符概率:")
    value = float(input())
    probability = probability - value
    Dict[name] = value


#按概率排序
Dict_order=sorted(Dict.items(),key=lambda x:x[1],reverse=True)

#编码算法
name = []
value = []
for i in Dict_order:
    name.append(i[0])
    value.append(i[1])
    
Fano_dict = {}.fromkeys(name,'')

value_copy = [value]
value_copy_copy = []
name_copy = [name]
name_copy_copy = []
while(len(value_copy)>0):
    for k in range(len(value_copy)):
        if len(value_copy[k]) == 2:
            Fano_dict[name_copy[k][0]] = Fano_dict[name_copy[k][0]] + '0'
            Fano_dict[name_copy[k][1]] = Fano_dict[name_copy[k][1]] + '1'
        else:
            for i in range(len(value_copy[k])):
                a = sum(value_copy[k][:i])
                b = sum(value_copy[k][i:])
                c = sum(value_copy[k][:(i+1)])
                d = sum(value_copy[k][(i+1):])
                if abs(a-b)<abs(c-d):
                    if i == 1:
                        Fano_dict[name_copy[k][0]] = Fano_dict[name_copy[k][0]] + '0'
                        value_copy_copy.append(value_copy[k][1:])
                        name_copy_copy.append(name_copy[k][1:])
                        for h in name_copy[k][1:]:
                            Fano_dict[h] = Fano_dict[h] + '1'
                    else:
                        value_copy_copy.append(value_copy[k][:i])
                        value_copy_copy.append(value_copy[k][i:])
                        name_copy_copy.append(name_copy[k][:i])
                        name_copy_copy.append(name_copy[k][i:])
                        for j in name_copy[k][:i]:
                            Fano_dict[j] = Fano_dict[j] + '0'
                        for h in name_copy[k][i:]:
                            Fano_dict[h] = Fano_dict[h] + '1'
                    break
    value_copy = value_copy_copy
    name_copy = name_copy_copy
    value_copy_copy = []
    name_copy_copy = []

#输出结果
print(Fano_dict)

2. 哈夫曼编码 / Huffman Encoding

此程序为哈夫曼(Huffman)编码的Python实现

'''
All rights reserved by Liu Junhong
Reference books: 《信息论基础》
Completion time:2020-11-24
'''
import math

#程序说明
print("-------------------<哈夫曼编码>程序说明-------------------")
print("Designed by Junhong Liu:All rights reserved")
print("Reference books: 《信息论基础》、百度百科-哈夫曼编码 (https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E7%BC%96%E7%A0%81/1719730?fr=aladdin)")
print("Completion time:2020-11-24")
print("Last modification time :2020-11-25")
print("--------------------------------------------------------")
print("\n")

#*******录入数据
N_num = float(input("请输入需要编码字符个数:"))
while(N_num <= 0 or (N_num % 1)):
    N_num = float(input("请输入正整数:"))
N_num = int(N_num)

Dict = []
Huffman_dict = {}
probability = 1


while(N_num > 0):
    N_num = N_num-1
    print("\n","------还需输入",N_num,"编码字符信息------")
    print("\n","请输入一个编码字符名:")
    name = str(input())
    Huffman_dict.setdefault(name)
    Huffman_dict[name] = ''
    print("请输入小于",probability,"的对应编码字符概率:")
    value = float(input())
    probability = probability - value
    Dict.append((value,[name]))

#按概率排序
Dict_order=sorted(Dict,reverse=False)

#编码算法
Dict_order_copy = Dict_order
Dict_order_copy_copy = []


while(len(Dict_order_copy)>1):
    for i in range(int(len(Dict_order_copy)/2)):
        if len(Dict_order_copy)-2*(i+1) == 1:
            for j in Dict_order_copy[2*i][1]:
                
                   Huffman_dict[j] =  '0' + Huffman_dict[j]
            for j in Dict_order_copy[2*i+1][1]:
                   Huffman_dict[j] =  '1' + Huffman_dict[j]
               
            Dict_order_copy_copy.append((Dict_order_copy[2*i][0]+Dict_order_copy[2*i+1][0],Dict_order_copy[2*i][1]+Dict_order_copy[2*i+1][1]))
            Dict_order_copy_copy.append((Dict_order_copy[len(Dict_order_copy)-1][0],Dict_order_copy[len(Dict_order_copy)-1][1]))
        else:    
            for j in Dict_order_copy[2*i][1]:
                   Huffman_dict[j] = '0' + Huffman_dict[j]
            for j in Dict_order_copy[2*i+1][1]:
                   Huffman_dict[j] = '1' + Huffman_dict[j]
                   
            Dict_order_copy_copy.append((Dict_order_copy[2*i][0]+Dict_order_copy[2*i+1][0],Dict_order_copy[2*i][1]+Dict_order_copy[2*i+1][1]))
            
    Dict_order_copy = sorted(Dict_order_copy_copy,reverse=False)

    Dict_order_copy_copy = []

#输出结果
print(Huffman_dict)

3. 希尔密码 / Hill Cipher

3.1. C++

——————-<希尔密码(MOD27)>程序说明——————-
该程序目前只接受小写英文加密讯息(支持空格)!
每次运行程序,密钥都会改变!
该程序相较python版本有所删减,减小了码符集大小,但完善了密钥矩阵的生成条件,增强了安全性。

/*
All rights reserved by Liu Junhong
Reference books: 百度百科-希尔密码 、https://www.doc88.com/p-58447325494757.html)
Completion time:2021-4-10
*/
#include <iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>

#include <cstdlib>
#include <ctime>

using namespace std;

int p[9]; //P用于储存密钥矩阵

int main()
{
    cout << "Designed by 刘俊宏:All rights reserved" <<endl;
    cout << "Reference books: 百度百科-希尔密码 、https://www.doc88.com/p-58447325494757.html" <<endl;
    cout << "Completion time:2021-4-6" <<endl;
    cout << "Last modification time :2021-4-10" <<endl;
    cout << "-------------------<希尔密码(MOD27)>程序说明-------------------" <<endl;
    cout << "该程序目前只接受小写英文加密讯息(支持空格)!" <<endl;
    cout << "每次运行程序,密钥都会改变!" <<endl;
    cout << "该程序相较python版本有所删减,减小了码符集大小,但完善了密钥矩阵的生成条件,增强了安全性。" <<endl;
    cout << "********************博客网址********************" <<endl;
    cout << "欢迎访问:https://hong-king.github.io/" <<endl;
    cout << "************************************************" <<endl;
    cout << "---------------------------------------------------------------" <<endl;

    /*
    生成符合条件的3*3随机密钥矩阵
    */
    int num;
    srand((int)time(0));   //产生随机种子,把0换成NULL也行
    do
    {
            for (int i = 0; i < 9; i++)
            {
                p[i] = rand()%27+1;  //[1,53]
            }
            num = p[0]*p[4]*p[8] + p[1]*p[5]*p[6] + p[2]*p[3]*p[7] - p[2]*p[4]*p[6] - p[1]*p[3]*p[8] - p[0]*p[5]*p[7];
    }while(num%3 == 0);
    cout << "密钥:" << endl;
        for (int i = 0; i < 9; i++)
    {
        cout << p[i] <<" ";
    }
    cout<<endl;

    /*
    求逆矩阵
    */
    int num_mo;
    for (int i = 1; i < 10000; i++){  //(i < 10000)存在BUG隐患
        if ( (num*i)%27 == 1 || (num*i)%27 == -26 ){
            num_mo = i;
            break;
        }
    }
    int I_p[9]; //P用于储存密钥的逆矩阵(转译矩阵)

    I_p[0] = (((p[4]*p[8] - p[5]*p[7])*num_mo)%27 +27)%27;

    I_p[3] = (((p[5]*p[6] - p[3]*p[8])*num_mo)%27 +27)%27;

    I_p[6] = (((p[3]*p[7] - p[4]*p[6])*num_mo)%27 +27)%27;

    I_p[1] = (((p[2]*p[7] - p[1]*p[8])*num_mo)%27 +27)%27;

    I_p[4] = (((p[0]*p[8] - p[2]*p[6])*num_mo)%27 +27)%27;

    I_p[7] = (((p[1]*p[6] - p[0]*p[7])*num_mo)%27 +27)%27;

    I_p[2] = (((p[1]*p[5] - p[2]*p[4])*num_mo)%27 +27)%27;

    I_p[5] = (((p[2]*p[3] - p[0]*p[5])*num_mo)%27 +27)%27;

    I_p[8] = (((p[0]*p[4] - p[1]*p[3])*num_mo)%27 +27)%27;

    /*
    读取需要加密的信息
    */
    string aaa;

    cout << "请输入需要加密的信息(只能包含空格和小写字母):";
    getline(cin,aaa);   //getline用于读取整行数据
    int g = aaa.length(); // 原始信息字数
    int z = 3 - g%3; // 需要扩充的字数
    if (z == 3)
        z = 0;
    int g_z = g + z;  //扩充后的字数
    int g_z_s = g_z / 3;

    /*
    将加密的信息转换成密文
    */
    int information[g_z] = {0};
    for (int i=0; i <= (g-1); i++)
    {
        if (int(aaa[i])==32)
            information[i] = 0;
        else if (int(aaa[i])>=97 && int(aaa[i])<=122)
        {
            information[i] = int(aaa[i]) - 96;
        }
        else
        {
            cout << "出现违法字符!" << endl;
            break;
            return 0;
        }
    }

    int information_copy[g_z] = {0};
    for (int i=0; i <= (g_z_s-1); i++)
        {
            information_copy[i*3+0] = (information[i*3+0]*p[0] + information[i*3+1]*p[1] + information[i*3+2]*p[2])%27;
            information_copy[i*3+1] = (information[i*3+0]*p[3] + information[i*3+1]*p[4] + information[i*3+2]*p[5])%27;
            information_copy[i*3+2] = (information[i*3+0]*p[6] + information[i*3+1]*p[7] + information[i*3+2]*p[8])%27;
        }

        cout<< "密文:"<<endl;

        for (int i=0; i <= (g_z-1); i++)
        {
            if (information_copy[i]==0)
                cout<<" ";
            else if (information_copy[i]>=1 && information_copy[i]<=26)
            {
                cout << char(information_copy[i]+96);
            }
        }

        /*
        解码
        */
        int information_copy_copy[g_z] = {0};
        for (int i=0; i <= (g_z_s-1); i++)
            {
                information_copy_copy[i*3+0] = (information_copy[i*3+0]*I_p[0] + information_copy[i*3+1]*I_p[1] + information_copy[i*3+2]*I_p[2])%27;
                information_copy_copy[i*3+1] = (information_copy[i*3+0]*I_p[3] + information_copy[i*3+1]*I_p[4] + information_copy[i*3+2]*I_p[5])%27;
                information_copy_copy[i*3+2] = (information_copy[i*3+0]*I_p[6] + information_copy[i*3+1]*I_p[7] + information_copy[i*3+2]*I_p[8])%27;

                if (information_copy_copy[i*3+0]<0)
                    information_copy_copy[i*3+0] = information_copy_copy[i*3+0] + 27;

                if (information_copy_copy[i*3+1]<0)
                    information_copy_copy[i*3+1] = information_copy_copy[i*3+1] + 27;

                if (information_copy_copy[i*3+2]<0)
                    information_copy_copy[i*3+2] = information_copy_copy[i*3+2] + 27;
            }

        cout<< "\n" << "明文:"<<endl;

        for (int i=0; i <= (g_z-1); i++)
        {
            if (information_copy_copy[i]==0)
                cout<<" ";
            else if (information_copy_copy[i]>=1 && information_copy_copy[i]<=26)
            {
                cout << char(information_copy_copy[i]+96);
            }
        }
    return 0;
}

运行结果示例:

Designed by 刘俊宏:All rights reserved
Reference books: 百度百科-希尔密码 、https://www.doc88.com/p-58447325494757.html
Completion time:2021-4-6
Last modification time :2021-4-10
-------------------<希尔密码(MOD27)>程序说明-------------------
该程序目前只接受小写英文加密讯息(支持空格)!
每次运行程序,密钥都会改变!
该程序相较python版本有所删减,减小了码符集大小,但完善了密钥矩阵的生成条件,增强了安全性。
********************博客网址********************
欢迎访问:https://hong-king.github.io/
************************************************
---------------------------------------------------------------
密钥:
1 14 7 21 19 27 13 10 15
请输入需要加密的信息(只能包含空格和小写字母):asd dfds
密文:
ydtqvv mz
明文:
asd dfds

3.2. Python

此程序为希尔密码(Hill Cipher)的Python实现

'''
All rights reserved by Liu Junhong
Reference books: 《信息论基础》、百度百科-希尔密码 (https://baike.baidu.com/item/%E5%B8%8C%E5%B0%94%E5%AF%86%E7%A0%81/2250150?fr=aladdin)
Completion time:2020-11-27
'''
import math
import numpy as np
import sys

#加/解密算法
def function(matrix):
    List = []
    STR = ''
    for i in message:
        for j in range(len(i)):
            for h in i[j]:
                List.append(letter_dict[h])
            if len(i)- j > 1:
                List.append(letter_dict[' '])
        while(not len(List)%4 == 0):
            List.append(letter_dict[' '])
        B = np.array(List).reshape(-1,4)
        C = np.dot(matrix,np.transpose(B))
        for k in np.transpose(C).reshape(1,-1)[0]:
            STR = STR + num_dict[(round(k))%53]         #round()确保矩阵计算精度
        print(STR)
        List = []     
        STR = ''

#程序说明
print("Designed by 刘俊宏:All rights reserved")
print("Reference books: 《信息论基础》、百度百科-希尔密码 (https://baike.baidu.com/item/%E5%B8%8C%E5%B0%94%E5%AF%86%E7%A0%81/2250150?fr=aladdin)")
print("Completion time:2020-11-27")
print("Last modification time :2020-11-28")
print("\n")
print("-------------------<希尔密码(MOD53)>程序说明-------------------")
print("该程序目前只接受大小写英文加密讯息(支持空格)!")
print("若要结束输入,请按两次回车")
print("每次运行程序,密钥都会改变!")
print("为保证解码顺利,密钥矩阵|A|=+/-1!")
print("\n")
print("********************博客网址********************")
print("欢迎访问:https://hong-king.github.io/")
print("************************************************")
print("---------------------------------------------------------------",'\n')

#创建码符集
letter = [' ']+[chr(i) for i in range(97, 123)] + [chr(i) for i in range(65, 91)]
letter_dict = dict(zip(letter,range(len(letter))))
num_dict = dict(zip(range(len(letter)),letter))
                   
#*******录入数据
print("请输入需要加密的英文讯息:")
message = []
try:
    while True:
        m = sys.stdin.readline().strip() #若是多输入,strip()默认是以空格分隔,返回一个包含多个字符串的list。
        if m == '':
            break
        m = list(m.split())
        message.append(m)
except:
    pass

print("正在加密,请稍后....")

#生成随机4阶可逆矩阵(密钥)
'''
为减小运算压力,设随机矩阵大小为4*4,随机整数元素区间为[1,10]
'''
A = np.random.randint(1, 10, size=(4,4)) #生成[1,10]区间的整数随机矩阵(密钥)
while (not abs(np.linalg.det(A)) == 1 ): #该条件用于保证密钥的逆矩阵为整数
    A = np.random.randint(1, 10, size=(4,4))
A_Inv = np.linalg.inv(A)

print("-------------------密钥-------------------")
print(A)
print("-------------------密文-------------------")
function(A)

print("\n","****************解码****************")
print("请输入密文:")
message = []
try:
    while True:
        m = sys.stdin.readline().strip() #若是多输入,strip()默认是以空格分隔,返回一个包含多个字符串的list。
        if m == '':
            break
        m = list(m.split())
        message.append(m)
except:
    pass

print("正在解密,请稍后....")
print("-------------------原文-------------------")
function(A_Inv)

4. 香农编码 / Shannon Encoding

此程序为香农编码的Python实现

'''
All rights reserved by Junhong Liu
Reference books: 《信息论基础》
Completion time:2020-11-23
'''
#import numpy as np
#import pandas
#import time
import math
#import sys

#程序说明
print("-------------------<香农编码>程序说明-------------------")
print("Designed by Junhong Liu:All rights reserved")
print("Reference books: 《信息论基础》、百度百科-香农编码 (https://baike.baidu.com/item/%E9%A6%99%E5%86%9C%E7%BC%96%E7%A0%81/22353186?fr=aladdin)")
print("Completion time:2020-11-23")
print("Last modification time :2020-11-23")
print("--------------------------------------------------------")
print("\n")

#*******录入数据
N_num = float(input("请输入需要编码字符个数:"))
while(N_num <= 0 or (N_num % 1)):
    N_num = float(input("请输入正整数:"))
N_num = int(N_num)

Dict = {}
probability = 1

while(N_num > 0):
    N_num = N_num-1
    print("\n","------还需输入",N_num,"编码字符信息------")
    print("\n","请输入一个编码字符名:")
    name = str(input())
    Dict.setdefault(name)
    print("请输入小于",probability,"的对应编码字符概率:")
    value = float(input())
    probability = probability - value
    Dict[name] = value

#print(Dict)
    
#按概率排序
Dict_order=sorted(Dict.items(),key=lambda x:x[1],reverse=True)

#print(Dict_order)
#sys.exit(0)

#编码算法
Q = 0  #累加概率
Shannon_dict = {}
for i in Dict_order:
    P = i[1]    #字符概率
    L = math.ceil(-math.log(P,2)) #码长
    Autoregressive_variable = 0
    num = Q
    word = ""   #码字
    while(Autoregressive_variable < L):
        if int(num) < int(2*num):
            word = word + '1'
            num = 2*num - int(2*num)
        else:
            word = word + '0'
            num = 2*num
        Autoregressive_variable = Autoregressive_variable+1
    Shannon_dict.setdefault(i[0])
    Shannon_dict[i[0]] = word
    Q = Q + P
    
print("Shannon_dict编码结果:",Shannon_dict)
#sys.exit(0)

5. DES 加密算法 / Data Encryption Standard (DES) Algorithm

程序说明 Reference books: https://blog.csdn.net/m0_37962600/article/details/79912654 Completion time:2021-4-20 Last modification time :2021-4-20

'''
此方法支持256种字符
参考文献:https://blog.csdn.net/m0_37962600/article/details/79912654
Completion time:2021-4-20

'''
import sys

#程序说明
print("-------------------<DES编码>程序说明-------------------")
print("All rights reserved")
print("Reference books: https://blog.csdn.net/m0_37962600/article/details/79912654)")
print("Completion time:2021-4-20")
print("Last modification time :2021-4-20",'\n')
print("--------------------------------------------------------")

print("请选择加密OR解密,加密输入0;解密输入1:")
aaaaa = input()
if (aaaaa != '0' and aaaaa != '1'):
    print("输入有无!")
    sys.exit(1)

#***************************************创建码符集
letter = [chr(i) for i in range(256)]
letter_dict = dict(zip(letter,['{:08b}'.format(i) for i in range(len(letter))]))
num_dict = dict(zip(['{:08b}'.format(i) for i in range(len(letter))],letter))

#***************************************生成16个子钥C,D(48位)(先假设密码为'12345678')
key = '12345678'
key_bin = ''
for i in key:
    key_bin = key_bin+letter_dict[i]

#key_bin = '0001001100110100010101110111100110011011101111001101111111110001'
#----------------------------------------------------步骤一
EX = [57,49,41,33,25,17,9, #交换规则表(8*7)
      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]
key_bIR  = ''
for i in range(len(EX)):
    key_bIR = key_bIR + key_bin[(EX[i]-1)]
#----------------------------------------------------步骤二
C = []
D = []
C.append(key_bIR[:28])
D.append(key_bIR[28:])

YW = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1] #移位规则表(1*16)
for i in range(16):
    C.append(C[i][YW[i]:] + C[i][:YW[i]])
    D.append(D[i][YW[i]:] + D[i][:YW[i]])
#----------------------------------------------------步骤三
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]
K  = []
for i in range(len(C)-1):
    K_copy = C[i+1] + D[i+1]
    K_IV = ''
    for j in range(len(PC_2)):
        K_IV = K_IV + K_copy[(PC_2[j]-1)]
    K.append(K_IV)

#***************************************用得到的子密钥对64位数据加密
if (aaaaa == '0'):
    print("请输入需要加密的英文讯息:")
else:
    print("请输入需要解密的英文讯息:")
m = input()
if(len(m)%8 != 0):
    m = m + num_dict['00000000']*(8 - len(m)%8)
M = []
for i in range(int(len(m)/8)):
    M.append(m[i*8:i*8+8])

Ciphertext = ''
for i in M:
    m = i
    word_bin = ''
    for i in m:
        word_bin = word_bin+letter_dict[i]

    #word_bin = '0000000100100011010001010110011110001001101010111100110111101111'
    #----------------------------------------------------步骤一
    IP = [58,50,42,34,26,18,10,2, #初始置换IP,得到word_bIR置换后的字符串
          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]
        
    word_bIR  = ''
    for i in range(len(IP)):
        word_bIR = word_bIR + word_bin[(IP[i]-1)]

    #初始置换IP,得到word_bIR
    R = []
    L = []
    L.append(word_bIR[:32])
    R.append(word_bIR[32:])
    #----------------------------------------------------步骤二
    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]

    for i in range(16):
        L.append(R[i])
        R_IV = ''
        for j in range(len(E)):
            if (aaaaa == '0'):
                if ( R[i][(E[j]-1)] == K[i][j] ):
                    R_IV = R_IV + '0'
                else:
                    R_IV = R_IV + '1'
            else:
                if ( R[i][(E[j]-1)] == K[15-i][j] ):
                    R_IV = R_IV + '0'
                else:
                    R_IV = R_IV + '1'
        S1 = [14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, #S核
              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]
        S = [S1,S2,S3,S4,S5,S6,S7,S8]

        R_IV_2 = ''
        for j in range(8):
            IV = R_IV[j*6:j*6+6]
            hang = IV[0]+IV[5]
            hang = int(hang,2)
            lie = IV[1:5]
            lie = int(lie,2)
            num = S[j][hang*16+lie]
            R_IV_2 = R_IV_2 + '{:04b}'.format(num)
    #----------------------------------------------------步骤三
        P = [16,7,20,21,   #P核
             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]
        R_IV_3 = ''
        for j in range(len(P)):
            if ( R_IV_2[(P[j]-1)] == L[i][j] ):
                 R_IV_3 = R_IV_3 + '0'
            else:
                R_IV_3 = R_IV_3 + '1'
        R.append(R_IV_3)

    #***************************************密文的生成
    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]
    RL = R[16] + L[16]

    Ciphertext_bin = ''
    for i in range(len(IP_1)):
        Ciphertext_bin = Ciphertext_bin + RL[(IP_1[i]-1)]

    for j in range(8):
        Ciphertext = Ciphertext + num_dict[Ciphertext_bin[j*8:j*8+8]]
    

if (aaaaa == '0'):
    print("密文为:"+Ciphertext)
else:
    print("明文为:"+Ciphertext)

6. ElGamal 加密算法 / ElGamal Public-key Cryptosystem

程序说明 ElGamal加密算法 Reference books: 《现代密码学(第二版)》 Reference books: https://blog.csdn.net/qq_41491942/article/details/103200388 Reference books: https://www.cnblogs.com/mx-lqk/p/10315789.html Completion time:2021-6-5 Last modification time :2021-6-5

import secrets

print("************程序功能************")
print("ElGamal加密算法")
print("********************************")
print("Reference books: 《现代密码学(第二版)》")
print("Reference books: https://blog.csdn.net/qq_41491942/article/details/103200388")
print("Reference books: https://www.cnblogs.com/mx-lqk/p/10315789.html")
print("Completion time:2021-6-5")
print("Last modification time :2021-6-5",'\n')
print("--------------------------------------------------------")

#高幂模
def gaomimo(a,b,P):
    c = 1
    if (b == 0):
        return (c)
    while(1):
        if (b%2 != 0):
            b = b-1
            c = (c*a) % P
            if (b == 0):
                return (c)
        else:
            b = b//2
            a = (a*a) % P
    

#米勒-拉宾素性检验
def judge_sushu(P):
    if (P==2 or P==3):
        return (1)

    s = 1
    while(1):
        if((P-1)%(2**s) == 0):
            s = s+1
        else:
            s = s-1
            break
    m = (P-1)//(2**s)

    judge = 0
    for b in range(1,(P-1),int((P-1)/10)):
        r = 0
        z = gaomimo(b,m,P)
        if(z == 1 or z == P-1):
            judge = judge + 1
            continue
        else:
            while(1):
                if (r == s-1):
                    return(0)
                else:
                    r = r+1
                    z = gaomimo(z,2,P)
                    if(z == P-1):
                        continue
    return(1)

#生成大素数p
q = secrets.randbelow(2**256)
if (q%2 == 0):
        q = q+1
while(judge_sushu(q) == 0):
                q = q+2
p = 2*q+1

print("生成大素数p中......")
while(judge_sushu(p) == 0):
        q = q+2
        while(judge_sushu(q) == 0):
                q = q+2
        p = 2*q+1

#p = 2579

#生成本原元g
print("\n","生成本原元g中......")
oula = p-1
g = 0
for i in range(secrets.randbelow(2**64),p):
        g = i
        if (gaomimo(g,1,p) == 1):
                continue
        else:
                if (gaomimo(g,2,p) == 1):
                        continue
                else:
                        if (gaomimo(g,q,p) == 1):
                                continue
                        else:
                                if (gaomimo(g,oula,p) == 1):
                                        break

#g = 2

#生成公钥y及私钥x
print("\n","生成公钥y及私钥x中......")
x = secrets.randbelow(2**256)
while (not( 1<x and x<(p-2) )):
        x = secrets.randbelow(2**256)
y = gaomimo(g,x,p)

#x = 765
#y = 949

#加密密文
print("\n","加密中......")
M = 1299  #明文M

k = secrets.randbelow(2**256)
while (not( 1<k and k<(p-2) ) or k==2 or k==q):
        k = secrets.randbelow(2**256)

#k = 853
y1 = gaomimo(g,k,p)
U = gaomimo(y,k,p)
y2 = gaomimo(U*M,1,p)
print("密文:(",y1,",",y2,")")

#解密
print("\n","解密中......")
V =  gaomimo(y1,x,p)

while(y2%V != 0):    #用于修正参数,防止无法正确得到明文
        y2 = y2 + p
M = gaomimo(y2//V,1,p)
print("明文为:",M)

print("\n","私钥x为:",x)
print("\n","公钥:")
print("p:",p)
print("\n","g:",g)
print("\n","y:",y)

7. RSA 加密算法 / RSA algorithm

程序说明 Reference books: 《现代密码学(第二版)》 Reference books: https://blog.csdn.net/jijianshuai/article/details/80582187 Reference books: https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95/263310?fromtitle=RSA&fromid=210678&fr=aladdin#reference-[5]-10613-wrap Completion time:2021-6-4 Last modification time :2021-6-4

import secrets

print("************程序功能************")
print("求RSA加密算法")
print("********************************")
print("Reference books: 《现代密码学(第二版)》")
print("Reference books: https://blog.csdn.net/jijianshuai/article/details/80582187")
print("Reference books: https://baike.baidu.com/item/RSA%E7%AE%97%E6%B3%95/263310?fromtitle=RSA&fromid=210678&fr=aladdin#reference-[5]-10613-wrap")
print("Completion time:2021-6-4")
print("Last modification time :2021-6-4",'\n')
print("--------------------------------------------------------")

P = secrets.randbelow(2**1024)
if (P%2 == 0):
        P = P+1
Q = secrets.randbelow(2**1024)
if (Q%2 == 0):
        Q = Q+1

#求模逆
def moni(X,Y):
    #第1步
    n1 = Y
    n2 = X
    b1 = 0
    b2 = 1

    #第2步
    q = n1//n2   #注意用//表示整数除法
    r = n1-q*n2

    #第3步
    while (r != 0):
        n1 = n2
        n2 = r
        t = b2
        b2 = b1-q*b2
        b1 = t

        q = n1//n2
        r = n1-q*n2

    #第4步
    ans = b2 % Y
    if (n2 == 1):
        return (ans)
    else:
        return (0)
        
#高幂模
def gaomimo(a,b,P):
    c = 1
    if (b == 0):
        return (c)
    while(1):
        if (b%2 != 0):
            b = b-1
            c = (c*a) % P
            if (b == 0):
                return (c)
        else:
            b = b//2
            a = (a*a) % P
    

#米勒-拉宾素性检验
def judge_sushu(P):
    if (P==2 or P==3):
        return (1)

    s = 1
    while(1):
        if((P-1)%(2**s) == 0):
            s = s+1
        else:
            s = s-1
            break
    m = (P-1)//(2**s)

    judge = 0
    for b in range(1,(P-1),int((P-1)/10)):
        r = 0
        z = gaomimo(b,m,P)
        if(z == 1 or z == P-1):
            judge = judge + 1
            continue
        else:
            while(1):
                if (r == s-1):
                    return(0)
                else:
                    r = r+1
                    z = gaomimo(z,2,P)
                    if(z == P-1):
                        continue
    return(1)

print("生成大素数中......")
while(judge_sushu(P) == 0):
    P = P+2
while(judge_sushu(Q) == 0):
    Q = Q+2
#print(P,"\n",Q)


#计算公共模数
N = P * Q

#欧拉函数
oula = (P-1)*(Q-1)

print("分配公钥及私钥中......")
#计算公钥E
E = min(P,Q)

D = 0
while(D == 0):
    E = E - 2
    while(judge_sushu(E) == 0):
        E = E-2

    #计算私钥D
    D = moni(E,oula)
#print(D)

print("加密中......")
#公钥加密
M = 2
C = gaomimo(M,E,N)

#私钥加密
M = gaomimo(C,D,N)

print("初始明文为:2",'\n')
print("公钥为:",E,'\n')
print("私钥为:",D,'\n')
print("公共模数为:",N,'\n')
print("密文为:",C)

8. 高幂模求解 / High Power Modular Exponentiation Solution

程序说明 Reference books: https://www.cnblogs.com/linyujun/p/5194170.html Reference books: https://baike.baidu.com/item/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0/1944850?fr=aladdin#3_6 Completion time:2021-5-25 Last modification time :2021-5-25

import sys
import math

#参考文献:https://www.cnblogs.com/linyujun/p/5194170.html

print("************程序功能************")
print("求 【X^Y mod Z】 的值")
print("********************************")

print("Reference books: https://www.cnblogs.com/linyujun/p/5194170.html")
print("Reference books: https://baike.baidu.com/item/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0/1944850?fr=aladdin#3_6")
print("Completion time:2021-5-25")
print("Last modification time :2021-5-25",'\n')
print("--------------------------------------------------------")

print("请输入X:")
X = input()
X = int(X)

print("请输入Y:")
Y = input()
Y = int(Y)

print("请输入Z:")
Z = input()
Z = int(Z)

judge = 0 #接受Z是否为素数指令,0表示Z为素数,1表示Z不为素数

#判断Z是否为素数,并求出素数个数
def judge_sushu(P):
    if (P==2 or P==3):
        return (0)
    dim = int(P**0.5)+1 #必须使用+1,不能使用ceil,否则4时出错
    for i in range(2,dim):
        if (P%i != 0 and i<(dim-1)):
            continue
        elif(P%i!=0 and i==(dim-1)):
            return (0)    #返回1说明P为素数
        else:
            return (i)

Prime_matrix = []

P = Z
Factor = judge_sushu(P)
if (Factor != 0):
    judge = 1
    while(1):
        Prime_matrix.append(int(Factor))
        P = P/Factor
        if (judge_sushu(P) == 0):
            Prime_matrix.append(int(P))
            break
        else: 
            Factor = judge_sushu(P)
else:
    Prime_matrix.append(int(Z))

#求结果
Prime_set = list(set(Prime_matrix))
phi = Z
for i in range(len(Prime_set)):
    phi = phi-phi/Prime_set[i] #欧拉函数值

ans = (int(X%Z)**int(phi+(Y%phi)))%Z #必须加上int,否则会转换成float类型,超出限制
print("结果为:")
print(ans)