实验一:经典加密算法的实现与破解
1、 实现凯撒加密、暴力破解凯撒加密
2、 选取k值,编译凯撒加密算法
3、 编写算法尝试暴力破解凯撒加密
实验二:大素数生成算法,不同素数生成算法优劣
1、 使用费马小定理素数判定法生成大素数
2、 使用米勒拉宾素数判定算法生成大素数
3、 总结出两种算法特点
一、实现凯撒加密
在密码学中,恺撒密码(英语:Caesar cipher),或称恺撒加密、恺撒变换、变换加密,是一种最简单且最广为人知的加密技术。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。这个加密方法是以罗马共和时期恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。
Encrypt:
def encrypt():
global result
for word in message:
if word in dic:
num = dic.find(word)
offset = (num + key) % 26
word = dic[offset]
result = result + word
Decrypt:
def decrypt():
global result
for word in message:
if word in dic:
num = dic.find(word)
offset = num - key
if offset < 0:
offset = offset + 26
word = dic[offset]
result = result + word
The_fu11_scr1pt:
dic = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
result = ''
message = input('Please input the message:')
mode = input('Please input the mode:')
key = input('Please input the key:')
key = int(key)
def encrypt():
global result
for word in message:
if word in dic:
num = dic.find(word)
offset = (num + key) % 26
word = dic[offset]
result = result + word
def decrypt():
global result
for word in message:
if word in dic:
num = dic.find(word)
offset = num - key
if offset < 0:
offset = offset + 26
word = dic[offset]
result = result + word
def main():
if mode == 'encrypt':
encrypt()
if mode == 'decrypt':
decrypt()
print(result)
if __name__ == '__main__':
main()
笔者这里写的较为简单,仅考虑了大写字母,如过想要涵盖小写字母甚至特殊字符的话,可以使用python自带的string模块,或者根据ascii进行编写。
print [chr(i) for i in range(65,91)] #所有大写字母
print [chr(i) for i in range(97,123)] #所有小写字母
print [chr(i) for i in range(48,58)] #所有数字
import string #导入string这个模块
print string.digits #输出包含数字0~9的字符串
print string.letters #包含所有字母(大写或小写)的字符串
print string.lowercase #包含所有小写字母的字符串
print string.uppercase #包含所有大写字母的字符串
print string.punctuation #包含所有标点的字符串
print string.ascii_letters #与string.letters一样
二、暴力破解凯撒加密
dic = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
message = input('Please input the message:')
def decrypt(key):
global result
result = ''
for word in message:
if word in dic:
num = dic.find(word)
offset = num - key
if offset < 0:
offset = offset + 26
word = dic[offset]
result = result + word
def main():
for key in range(1,27):
decrypt(key)
print('key:' + str(key) + '\t result:' + result)
if __name__ == '__main__':
main()
一、使用费马小定理素数判定法生成大素数
费马小定理(Fermat’s little theorem)是数论中的一个重要定理,在1636年提出。如果p是一个质数,而整数a不是p的倍数,则有 a^(p-1) ≡ 1 (mod p)。
由上述公式得,p = a^(p-1) * p + 1。我们令 a = p-1 以取得较大的p值,算法实现如下:
# include
# include
using namespace std;
int main()
{
long long a,t,p;
cout<<"Please enter an integer:";
cin>>p;
a = p-1;
t = pow(a,a);
p = t*p + 1;
//cout<<"p = "<
cout<<"The large prime number is:"<<p<<endl;
}
运行结果如下:
但当结果过于大以至于超出了long long的范围时,我们就必须要采用其他方法来实现运算了。比如用数组或字符串来表示数值,然后再构造函数从而实现大数的运算。
C++大整数运算的实现可以参考以下文章:
https://www.cnblogs.com/yilis/p/10680176.html
https://blog.csdn.net/Ring_k/article/details/80615561
https://www.cnblogs.com/youngforever/articles/3262043.html
二、使用米勒-拉宾素数判定法生成大素数
p是质数一定满足费马小定理,但满足费马小定理的数并一定是质数。有些数虽然满足费马小定理但并不是质数,他们叫做伪质数(Carmichael),伪质数的个数是无穷的。所以说如果我们用费马小定理来生成大素数,是会一定几率出错的。那么这个出错的概率是多大呢?在一定范围内又有多少个数是伪素数呢?这个和 a 的取值有关。当 a = 2 时,前十亿个正整数中能满足费马小定理且不是素数的数有5597个,也就是说出错的概率是0.011%。虽然它的错误率不高,但是无法否认的是,仍存在一定数量的伪素数是费马小定理无法检测出来的。因此我们需要一个方法来尽可能的筛查出这些伪素数,这也就是米勒拉宾算法的核心部分二次探测。
虽然我们遍历 x 让它 mod p 的结果有很多种,但我们需要的仅是那些能使 x^2 ≡ 1 (mod p) 成立的 x。那我们反过来,把所有能使 x^2 ≡ 1 (mod p) 成立的 x 取出来,看他们是否等于 p - 1 或 1 即可。不过如何不经过计算快速找出这些能使等式成立的 x 呢?我们再看下刚才的费马素性检测。 所有的质数都是奇数,任何一个偶数都可以写成 2^s * t 的形式 ,比如 6 = 2^1 * 3 a^(p-1) ≡ 1 (mod p) => a^(2^s * t) ≡ 1 (mod p) => (a^t)^(2^s) ≡ 1 (mod p),令 a^t = k (a^t)^(2^s) ≡ 1 (mod p) => k^(2^s) ≡ 1 (mod p) => (k * k * …… * k)^2 ≡ 1 (mod p) => x^2 ≡ 1 (mod p) 综上,遍历 x 就相当于遍历 k,遍历 k 就相当于遍历 a( t 为可计算的常数,计算方法见下文)。米勒拉宾算法其实就是随机取一定数量的不同的 a,从而得到不同的 k ,再对 k 不断地平方进行二次探测(进行 s 次),判断是否等于 1 或 p-1。多尝试几个 k 即多尝试几个a,这个算法的错误概率就可以降低到忽略不计。 t 的计算方法: 以 72 为例,72 = 1001000 = 8 * 9 = 2^3 * 9,1001000 中最低位起不间断得 0 的个数为3,故 t = 3。 又如 28 = 11100 = 4 * 7 = 2^2 * 7,t = 2。 快速积: 3 * 7 => 3 * (111) => 3 * (2^0 + 2^1 +2^2) => 3 * (1 + 2 + 4) 令 res=3,res = res + res = 3 * 2 = 6 => res = res + res = 3 * 4 = 12…… 快速幂: 3^5 => 3^(101) => 3^(2^0 + 2^2) => 3^(1 + 4) => 3^1 * 3^4 令 res = 3,res = res * res = 9 (第二位为0,故9不参与运算)=> res = res * res = 81 = 3^4…… 米勒-拉宾素性检验: 结合费马小定理与米勒-拉宾素性检验,构造大素数生成代码: 运行结果如下: 费马素数判定与米勒-拉宾素数判定均属于随机性测试。这类测试方法一般比较快,但无法完全证明一个数是否为素数。在米勒-拉宾算法中,随着测试成功次数的增加,合数的概率会呈指数式下滑,素数的可信度越来越大(但不完全可信)。一旦测试失败,则表明该数为一定为合数。 https://blog.csdn.net/qq_42146775/article/details/102562329
因此,如果我们要判断 p 是否为素数,可以根据二次探测定理遍历 x 的值(0
long long Quick_Multiply(int a,int b,int c)
{
long long ans=0,res=a;
while(b)
{
if(b&1) //低位是否为1
ans=(ans+res)%c;
res=(res+res)%c;
b>>=1; //左移一位,即去除最低位
}
return ans;
}
long long Quick_Power(int a,int b,int c)
{
int ans=1,res=a;
while(b)
{
if(b&1)
ans=Quick_Multiply(ans,res,c);
res=Quick_Multiply(res,res,c);
b>>=1;
}
return ans;
}
bool Miller_Rabin(long long x)
{
long long i,j,k;
long long s=0,t=x-1;
//cout<
#include
可以看出当输入的整数为 11 时,程序运行至 x 越界也没能生成素数。大质数可在此查找:大质数表0x03 Summary
0x04 Reference
https://blog.csdn.net/forever_dreams/article/details/82314237
https://blog.csdn.net/holly_Z_P_F/article/details/85197424