使用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初学者,如果有什么能改进的地方欢迎指正

posted on 2023-03-13 13:47  H4RUH1RO  阅读(215)  评论(0编辑  收藏  举报