实验一:密码技术
实验目的:
- 理解同余运算在密码学中的应用,理解中国剩余定理以及二次同余方程平方根求解问题
- 掌握凯撒密码
- 掌握Rabin公钥密码体制
任务1:编程现实凯撒密码
要求如下:
- 输入数据:为自己姓名的拼音字母,例如,李浩,则输入数据为:LIHAO。
- 密钥随机:每个字母移动位数不固定,例如输入字母l可以移动4位,输入字母i可以移动5位。
- 输出加密之后的密文。
- 解密,还原明文,并验证还原的明文是否和输入数据LIHAO相等,如果相等,解密成功。
- 可以对任意输入数据进行加密(选做)
任务2:编程实现Rabin公钥密码体制
要求如下:
- 输入数据:为自己姓名的拼音字母,例如,李浩,则输入数据为:LIHAO。
- 根据ASCII码表,将拼音字母转换为对应十进制数,例如,LIHAO转换为76,73,72,65,79。
- 密钥p和q为素数,满足
。
- 输出加密之后的密文,包括十进制数以及十进制数对应的字符。
- 解密,还原明文,并验证还原的明文是否和输入数据LIHAO相等,如果相等,解密成功。
- 可以对任意输入数据进行加密(选做)
对于这两个任务其实难度并不大,只需要弄清楚公式即可。以及思考一下进位的问题即可。
凯撒密码的公式:
加密公式 f(a)=(a+3) mod 26
解密公式 f(a)=(a+23) mod 26
关于Rabin密码体制的内容,大家可以去这里好好了解认识一下,这里主要针对本次实验,这里就不浪费时间了。密码学之公钥密码体系(4):Rabin公钥密码方案_摆渡沧桑的博客-CSDN博客_rabin密码一、Rabin公钥密码方案Rabin密码体制,被认为是对RSA密码体制的改进,其安全性基于求合数的模平方根的难度。而这个困难性等价于求解因子分解。RSA算法中只要素数被分解,密码就会被破解。而Rabin方案其实可以看做为RSA方案的一个特例,但被证明破译的难度和分解大整数一样难度。Rabin方案的特点:1. Rabin 方案不是一一映射的,对于同一个密文,可能会有多个对应的明文;2. Rabin算法的安全性基于求解合数模平方根困难性问题,破解难度和大整数分解相当;3. Rabin算法可以看做https://blog.csdn.net/vivid117/article/details/124784493现在我们在了解了公式的情况下,我们就可以去用代码实现这些了。
任务1源代码如下:
C++
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include <string.h>
#define N 100
using namespace std;
//凯撒密码
//加密公式 f(a)=(a+3) mod 26
//解密公式 f(a)=(a+23) mod 26
void Encry(char* strI, int numB, int model);//加密公式函数
void Decry(char* strI, int numB, int model);//解密公式函数
int FileOut(char* strI);
int main()
{
char str[N];
int model;
int numB;
while (1)
{
std::cout<< "凯撒密码:请选择模式:\n";
std::cout << "1.加密\n";
std::cout << "2.解密\n";
std::cout << "3.退出\n";
cin >> model;
std::cout << endl;
switch (model)
{
case 1:
std::cout << "请输入要加密的字符串:";
cin >> str;
std::cout << "请输入该密码算法的偏移数量:";
cin >> numB;
Encry(str, numB, model);
std::cout << endl;
break;
case 2:
std::cout << "请输入要解密的字符串:";
cin >> str;
std::cout << "请输入原密码算法的偏移数量:";
cin >> numB;
Decry(str, numB, model);
std::cout << endl;
break;
case 3:
return 0;
break;
default:
break;
}
}
return 0;
}
void Encry(char* strI, int numB, int model)
{//明文串 秘钥 功能模式
if (model == 1)
{
for (int i = 0; i < strlen(strI); i++)
{
if (strI[i] >= 'A' && strI[i] <= 'Z')
{
strI[i] = ((strI[i] - 'A') + numB) % 26 + 'A';
}
else if (strI[i] >= 'a' && strI[i] <= 'z')
{
strI[i] = ((strI[i] - 'a') + numB) % 26 + 'a';
}
}
std::cout << "加密完成:" << strI << endl;
FileOut(strI);
std::cout << "已输出到文件!" << endl;
}
else
{
std::cout << "该模式不支持此项功能!" << endl;
}
}
void Decry(char* strI, int numB, int model)
{
if (model == 2)
{
int num;
num = 26 - numB;
for (int i = 0; i < strlen(strI); i++)
{
if (strI[i] >= 'A' && strI[i] <= 'Z')
{
strI[i] = ((strI[i] - 'A') + num) % 26 + 'A';
}
else if (strI[i] >= 'a' && strI[i] <= 'z')
{
strI[i] = ((strI[i] - 'a') + num) % 26 + 'a';
}
}
std::cout << "解密完成:" << strI << endl;
}
else
{
std::cout << "该模式不支持此项功能!" << endl;
}
}
int FileOut(char* strI)
{
FILE* fp = NULL;
int iWrite = 0;
int len = strlen(strI);
if (strI == NULL || len == 0)
return false;
//! 打开文件句柄
if ((fp = fopen("密文.txt", "w")) == NULL) // 文本模式写
return false;
iWrite = fwrite(strI, 1, len, fp);
fclose(fp);
if (iWrite > 0)
return true;
else
return false;
}
任务2源代码如下:
python
import random
import time
# 判断是否为素数
# 判断可能失效,因为该方法有伪素数存在
def is_prime(n):
if n == 0:
return False
return 1 == square_and_multiply(17, n - 1, n)
# 莫重复平方运算 b^n%m
def square_and_multiply(b, n, m):
bi = b
ai = 1
k = len("{0:b}".format(n))
for i in range(0, k):
if (n >> i & 1) == 1:
ai = ai * bi % m
bi = bi ** 2 % m
return ai
# 拓展欧几里得 , 求逆
def ex_gcd(a, b):
if b == 0:
return 1, 0, a
else:
s, t, r = ex_gcd(b, a % b)
s, t = t, (s - (a // b) * t)
return s, t, r
# 密钥生成
# return p,q,n, (p,q) is private key, n is public key
def key_generator():
p = 0
q = 0
n = 0
while (p - 3) % 4 != 0 or (q - 3) % 4 != 0 or p == q:
random.seed(time.time())
# 可以取非常大的值
p = random.randint(2 * 300, 2 * 400)
q = random.randint(2 * 300, 2 * 400)
while not is_prime(p) or not is_prime(q):
p += 4
q += 4
n = p * q
return p, q, n
# 加密
# m is plaintext, n is public key
# 该算法通过重复明文方法来区分四个解
def encode(m, n):
m1 = str(m)
m1 = int(m1 + m1)
c = m1 ** 2 % n
return c
# 处理4个解的子方法
def sub_handle_decode_res(m):
if len(m) % 2 != 0:
return False
i = 0
while i < len(m) // 2:
if m[i] != m[len(m) // 2 + i]:
return False
i = i + 1
return m[:len(m) // 2]
# 处理4个解的情况
def handle_decode_res(m1, m2, m3, m4):
m1_str = sub_handle_decode_res(str(m1))
m2_str = sub_handle_decode_res(str(m2))
m3_str = sub_handle_decode_res(str(m3))
m4_str = sub_handle_decode_res(str(m4))
if m1_str:
return m1_str
if m2_str:
return m2_str
if m3_str:
return m3_str
if m4_str:
return m4_str
# 解密
def decode(c, p, q, n):
s, t, r = ex_gcd(p, q)
u = square_and_multiply(c, (p + 1) // 4, p)
v = square_and_multiply(c, (q + 1) // 4, q)
m1 = int(u * t * q + v * s * p) % n
m2 = int(u * t * q - v * s * p) % n
return handle_decode_res(m1, n - m1, m2, n - m2)
if __name__ == '__main__':
p, q, n = key_generator()
# 处理公钥私钥。
print("p is {}, q is {}, n is {}".format(p, q, n))
M = input("请输入明文:")
# 转化为数组
result1 = list(M)
result2 = []
result3 = []
result4 = []
for i in range(len(result1)):
# 将字母转化为十进制
m = ord(result1[i])
c = encode(int(m), n)
result2.append(c)
# result3.append(chr(c))
m = decode(c, p, q, n)
result4.append(chr(int(m)))
# print("密文十进制为{}, 字符为{}".format(result2, result3))
print("密文十进制为{}".format(result2))
m = ''.join(result4)
if m == M:
print("解密成功!")
print("明文为 {}".format(m))