使用python实现三种素性检验方法
在学习信息安全数学课程时,老师课上要求使用自己熟悉的语言实现课上学习的素性检验方法,正好最近在学python,就用python完成了这次作业。
第一种:Fermat素性检验
关于素性检验的方法我就不细说了,网上都能查得到,而且我的代码写的也不好,这里仅供参考。
import random
import time
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
while n < 3 or n%2 != 1:
print("输入有误,输入的n应 >= 3,且为奇数")
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
t = int(input("请输入安全参数t:\n"))
b = []
start = time.time()
flag = False
for num in range(2,n-1):
for temp in range(2,num + 1):
if num%temp == 0 and n%temp == 0:
flag = True
break
if flag == False:
b.append(num)
else:
flag = False
print("符合条件的b有:",b,"一共",len(b),"个")
for i in range(1,t+1):
x = b[random.randint(0,len(b)-1)]
r = (x ** (n-1)) % n
if r != 1:
print("n为合数")
exit(0)
end = time.time()
print("n为素数")
print(end-start)
不过我的代码有个缺点,在计算b时,我是先将所有符合条件的b都计算出来后,才在b中随机挑选一个对n进行检验,这就导致在对大数进行检验时,会导致程序崩溃,只要改成在合适区间随机挑选b,符合条件再进行判断就能解决问题,但是懒得改,就这样放在这里了
第二种:Miller-Rabin素性检验
直接上代码
import random
import math
import time
#快速求模
def quickmod(b,n,x):
res = 1
b = b % x
while n != 0:
if n & 1:
res = (res * b) % x
n >>= 1
b = (b * b) % x
return res
#函数定义完毕
#求出 n - 1 =t * 2 ^ s中的s与t
def get_ready(n):
s = 1
temp = n - 1
temp1 = temp // 2
t = 1
#n - 1 = 2^s * t
while temp1 % 2 == 0:
temp = temp / 2
temp1 = temp // 2
s += 1
t = temp1
return s,t
#函数定义完毕
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
start = time.time()
hello = get_ready(n)
s = int(hello[0])
t = int(hello[1])
while n < 3 or n%2 != 1:
print("输入有误,输入的n应 >= 3,且为奇数")
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
k = int(input("请输入安全参数k:\n"))
te = 0
while te <= k:
te += 1
b = random.randint(2,n-2)
r = quickmod(b,t,n)
if r == 1 or r == n -1:
continue
else:
miu = 0
r_miu = r
while miu <= s -1:
if miu == s -1:
r_miu = quickmod(r_miu,2,n)
if r_miu != n - 1:
print(n,"为合数")
exit()
r_miu =quickmod(r_miu,2,n)
if r_miu == n - 1:
break
else:
miu = miu + 1
continue
end = time.time()
print(end-start)
print("n是素数")
第三种:Solovay-Stassen素性检验
直接上代码。
import random
import math
import time
#计算雅可比符号,x为b,y为n
def jacobi( x, y):
#b = int(input("b = :"))
#n = int(input("n = :"))
b = x
n = y
#print("b = ",b,"n = ",n)
sym = 1
result = 1
while b != 1 and b != -1 and b != 2:
if b < n:
if b % 2 != 1:
sym = (-1)**((n**2-1)/8) * sym
b = b / 2
else:
sym = (-1)**((n-1)*(b-1)/4) * sym
temp = b
b = n
n = temp
else:
temp = b // n
b = b - temp * n
if b == 2:
result = (-1)**((n**2-1)/8) * sym
elif b == 1 or b == -1:
result = b * sym
return result
#函数定义完毕
#快速幂计算b的(n-1)/2次方
#def ksm(x, n):
# res = 1
# while n > 0:
# # 如果幂为奇数, 把x记录下来,储存在res中
# if n % 2 == 1:
# res *= x
# # 如果幂为偶数 则不记录,只是处理x, n
# x *= x
# n >>= 1
# return res
#函数定义完毕
#快速求模
def quickmod(b,n,x):
res = 1
b = b % x
while n != 0:
if n & 1:
res = (res * b) % x
n >>= 1
b = (b * b) % x
return res
#函数定义完毕
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
start = time.time()
while n < 3 or n%2 != 1:
print("输入有误,输入的n应 >= 3,且为奇数")
n = int(input("请输入要检验的奇整数n,n >= 3:\n"))
t = int(input("请输入安全参数t:\n"))
for i in range(1,t+1):
b = random.randint(2,n-2)
#print("b = ",b)
#print("n = ",n)
r = quickmod(b,(n-1)//2,n)
print("r = ",r)
s = jacobi(b,n)
#print("b = ",b)
#print("n = ",n)
#print("s = ",s)
#print("r = ",r)
if r != 1 and r != n - 1:
#print("s = ",s)
#print("r = ",r)
print("n为合数")
exit(0)
if r == n -1:
#print("转了!")
r = -1
if r != s:
#print("s = ",s)
#print("r = ",r)
print("n为合数")
exit(0)
end = time.time()
print(end-start)
print("n为素数")
以上代码都没有经过仔细推敲,基本上都是草稿,而且我还只是个python初学者,如果有什么能改进的地方欢迎指正