【发布时间】:2021-07-26 05:59:14
【问题描述】:
我在 python 中实现 RSA,最初我使用 Python Multiprocessing 包的并行处理生成素数随机数。我正在使用米勒拉宾算法来检查素数。这个并行实现应该运行得更快,但我不明白为什么不是这样。并行处理需要花费大量时间,即使对于较小的素数大小(如 50 位)也是如此。任何人都可以帮助解决这个问题吗? (P.S. 我是并行处理的初学者)
这是我的python代码(实现函数+RSA算法实现)
所有必需的函数:
# Prime Generation using Parallel Processing (Miller Rabin)
import time
from multiprocessing import Pool
import random
# Prime-Generating-Functions start---
from random import randrange, getrandbits
def is_prime(n, k=128):
# Test if n is not even.
# But care, 2 is prime !
if n == 2 or n == 3:
return True
if n <= 1 or n % 2 == 0:
return False
# find r and s
s = 0
r = n - 1
while r & 1 == 0:
s += 1
r //= 2
flag=1
p=Pool()
results = [p.apply_async(primetest, args=(s,r,n,)) for x in range(k)]
for k in results:
output = [k.get()]
#print("VALUE OF OUTPUT",k.get())
if k.get()==False:
flag=0
break
if flag==0:
p.close()
p.join()
return False
else:
p.close()
p.join()
return True
def primetest(s,r,n):
#for _ in range(k):
#print("Test.value in primetest", test.value)
a = randrange(2, n - 1)
x = pow(a, r, n)
if x != 1 and x != n - 1:
j = 1
while j < s and x != n - 1:
x = pow(x, 2, n)
if x == 1:
return False
j += 1
if x != n - 1:
return False
return True
def generate_prime_candidate(length):
# generate random bits
p = getrandbits(length)
# apply a mask to set MSB and LSB to 1
p |= (1 << length - 1) | 1
return p
def generate_prime_number(length=1024):
p = 4
# keep generating while the primality test fail
while not is_prime(p, 128):
p = generate_prime_candidate(length)
#print("value of p is",p)
return p
# Prime-Generating-Functions end---
# Miscellaneous Functions
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def modInverse(a, m):
m0 = m
y = 0
x = 1
if (m == 1):
return 0
while (a > 1):
# q is quotient
q = a // m
t = m
# m is remainder now, process
# same as Euclid's algo
m = a % m
a = t
t = y
# Update x and y
y = x - q * y
x = t
# Make x positive
if (x < 0):
x = x + m0
return x
RSA 算法从这里开始:
import time
#key gen start----------------------------------------
start_key_gen_time = time.time()
# print("Key Generation:\n");
p = generate_prime_number(50) #Takes the size (eg 50) in bits, and generates random prime of that size
q = generate_prime_number(50)
# print("Is p=",p, "prime ? ", is_prime(p));
# print("Is q=",q,"prime ?",is_prime(q));
n = p*q; # evaluating n
# print("\nn=",n);
phi = (p-1)*(q-1); # evaluating phi
# print("phi=", phi)
e = ZZ.random_element(phi)
while (gcd(e, phi) != 1):
e = ZZ.random_element(phi) #choosing e
# print("\ne=",e);
# print("*e < phi=",e < phi) #checking conditions for e
# print("*gcd(e,phi)=",gcd(e,phi))
# print("*Is e prime ?", is_prime(e))
d = inverse_mod(e, phi) #finding corresponding d, s.t. e*d = 1*mod(phi)
# print("\nd=",d);
# print("*Is d prime ?", is_prime(d))
# print("\npublic key = (",n,", ",e,")"); #Generated Key pairs
# print("private key = (",n,", ",d,")\n");
final_key_gen_time = time.time()
#key gen finish------------------------------------------------
total_key_gen_time = final_key_gen_time - start_key_gen_time
print("\nTotal Key generation time taken in seconds: ", total_key_gen_time )
#Encryption start--------------------------------------------
start_encrypt_time = time.time()
# print("Encryption & Decryption:\n");
m = 59; #print("original msg=",m) #original message m
c = power_mod(m,e,n); #print("encrypted msg=",c) #encrypted message c
finish_encrypt_time = time.time()
#Encryption finish---------------------------------------------
total_encrypt_time = finish_encrypt_time - start_encrypt_time
print("\nTotal encrypt taken in seconds: ", total_encrypt_time )
#Decryption start----------------------------------------------
start_decrypt_time = time.time()
decrypt_msg = power_mod(c,d,n) # decrypting
# print("decrypted msg=",decrypt_msg)# so m was correctly decrypted
finish_decrypt_time = time.time()
#Decryption finish----------------------------------------------
total_decrypt_time = finish_decrypt_time - start_decrypt_time
print("\nTotal decrypt time taken in seconds: ", total_decrypt_time )
total_time_taken = total_key_gen_time + total_encrypt_time + total_decrypt_time
print("\n\nTotal algorithm time taken in seconds: ", total_time_taken)
print("\nIs decrypted msg & original msg same?", (decrypt_msg==m))
【问题讨论】:
-
Stackoverflow 是一个问答系统,因此您的帖子应该包含一个问题。请编辑您的帖子并包含一个有人可以回答的真实问题。
-
我还没有看过代码,但是多处理涉及到每个创建的进程都有一定数量的固定开销,所以进程越长,开销就越不明显。 50 位素数非常小,开销将使运行素数查找算法所需的时间相形见绌。尝试使用 2048 位素数进行测试,以获得更真实的测试。
-
感谢@Robert,我已根据您的建议更新了帖子。
-
@PresidentJamesK.Polk ,我也尝试使用 2048 位素数对其进行测试。但现在,我没有得到任何结果,因为与 50 位相比,时间非常高。
-
你之前问过这个问题,而我之前的评论是成立的。您在并行 Miller-Rabin (MR) 中所做的工作比在串行版本中所做的要多得多,因为您测试的 几乎每个 数字
n都是复合的,并且会失败 您的 128 个 MR 测试中的第一个,使其他 127 个不必要。是的,您对此进行检查并将结果发送给其他进程,但它们不太可能在开始工作之前收到此信号。
标签: python parallel-processing cryptography rsa primes