📜  如何为RSA算法生成大素数

📅  最后修改于: 2021-04-29 05:40:49             🧑  作者: Mango

RSA算法的安全性基于分解非常大的数字的难度。 RSA密码系统的建立涉及两个大质数的生成,例如pq ,由此得出的RSA模数为n = p * q 。模数大小越大,RSA系统的安全级别就越高。对于大多数设置,建议的RSA模数大小为2048位至4096位。因此,要生成的素数需要为1024位至2048位长。为了合成如此大的素数,我们不依赖于确定性方法,而是寻找具有令人满意的高概率水平的素数。

大型素数生成程序:

  • 目标是有效地计算具有指定位大小的非常大的随机素数。手动实现随机素数生成器的标准方法如下:
    1. 预选具有所需位大小的随机数
    2. 确保所选的数字不能被前几百个素数整除(这些是预先生成的)
    3. 根据可接受的错误率,应用一定数量的Rabin Miller Primality Test迭代,以获得一个可能是质数的数
大型素数生成过程

图1:生成RSA的大素数的步骤

以下是实现上述过程的步骤:

  1. 选择一个随机的主要候选人
    • 具有n位的随机数的生成意味着该随机数在0到0的范围内(2^n-1) 。生成随机数的一些注意事项是:
      1. 必须避免选择小质数,例如3、5、7…,因为RSA模数的因式分解将变得微不足道。因此,必须注意不要有太多的前导零。这可以通过始终使最高位= 1来完成
      2. 由于所有质数(> 2)均为奇数,因此为了获得更好的性能,可以选择仅奇数
    • 因此,我们选择范围内的任何随机数(2^{n-1} + 1, 2^n - 1)
    def nBitRandom(n):
      
        # Returns a random number
        # between 2**(n-1)+1 and 2**n-1'''
        return(random.randrange(2**(n-1)+1, 2**n-1))
    
  2. 与原质相除(低级素性测试)
    • 此步骤是一个低级素数测试,需要预先计算前几百个素数(使用Eratosthenes筛子)。
    • 素数候选项除以预先生成的素数以检查可除性。如果可以将这些主要生成的素数中的任何一个完全分解为主要素数,则该测试将失败,因此必须选择并测试一个新的主要素数。只要找到与生成的素数列表中所有素数互质的值,便会重复执行此操作
    def getLowLevelPrime(n):
        '''Generate a prime candidate divisible
          by first primes'''
      
        # Repeat until a number satisfying
        # the test isn't found
        while True: 
      
            # Obtain a random number
            prime_candidate = nBitRandom(n) 
      
            for divisor in first_primes_list: 
                if prime_candidate % divisor == 0 
                and divisor**2 <= prime_candidate:
                    break
                # If no divisor found, return value
                else: return prime_candidate 
    
  3. Rabin Miller原始性测试(高级原始性测试)
    • 然后,通过Rabin Miller Primality测试再次测试通过低级测试的主要候选人。
    • 对于非常大的数字(例如RSA中使用的数字),对所选值是否为质数进行确定性测试非常不切实际,因为它需要不合理数量的计算资源。
    • 因此,概率方法是优选的。如果输入的值通过Rabin Miller测试的单个迭代,则该数字为素数的概率为75%
    • 因此,经过足够次数的考试的候选人可以被认为是具有令人满意的概率的素数。
    • 通常,在商业应用中,我们要求错误概率小于{1/2}^{128}
    def isMillerRabinPassed(miller_rabin_candidate):
        '''Run 20 iterations of Rabin Miller Primality test'''
      
        maxDivisionsByTwo = 0
        evenComponent = miller_rabin_candidate-1
      
        while evenComponent % 2 == 0:
            evenComponent >>= 1
            maxDivisionsByTwo += 1
        assert(2**maxDivisionsByTwo * evenComponent == miller_rabin_candidate-1)
      
        def trialComposite(round_tester):
            if pow(round_tester, evenComponent, 
                   miller_rabin_candidate) == 1:
                return False
            for i in range(maxDivisionsByTwo):
                if pow(round_tester, 2**i * evenComponent,
                       miller_rabin_candidate) 
                == miller_rabin_candidate-1:
                    return False
            return True
      
        # Set number of trials here
        numberOfRabinTrials = 20 
        for i in range(numberOfRabinTrials):
            round_tester = random.randrange(2,
                           miller_rabin_candidate)
            if trialComposite(round_tester):
                return False
        return True
    
  4. 结合以上步骤生成代码
    • 最后,我们可以结合以上功能来创建一个三步过程来生成大素数。步骤将是
      1. 通过调用nBitRandom( bitsize )生成随机数
      2. 通过调用getLowLevelPrime( prime_candidate )进行基本除法测试
      3. 通过调用isMillerRabinPassed( prime_candidate )进行Rabin Miller测试
    • 如果所选的随机值通过所有素数测试,则将其作为n位素数返回。否则,在测试失败的情况下,将选择一个新的随机值并测试素数。重复该过程,直到找到所需的底漆为止。

以下是上述方法的完整实施

# Large Prime Generation for RSA
import random
  
# Pre generated primes
first_primes_list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
                     31, 37, 41, 43, 47, 53, 59, 61, 67, 
                     71, 73, 79, 83, 89, 97, 101, 103, 
                     107, 109, 113, 127, 131, 137, 139, 
                     149, 151, 157, 163, 167, 173, 179, 
                     181, 191, 193, 197, 199, 211, 223,
                     227, 229, 233, 239, 241, 251, 257,
                     263, 269, 271, 277, 281, 283, 293,
                     307, 311, 313, 317, 331, 337, 347, 349]
  
def nBitRandom(n):
    return random.randrange(2**(n-1)+1, 2**n - 1)
  
def getLowLevelPrime(n):
    '''Generate a prime candidate divisible 
    by first primes'''
    while True:
        # Obtain a random number
        pc = nBitRandom(n) 
  
         # Test divisibility by pre-generated 
         # primes
        for divisor in first_primes_list:
            if pc % divisor == 0 and divisor**2 <= pc:
                break
        else: return pc
  
def isMillerRabinPassed(mrc):
    '''Run 20 iterations of Rabin Miller Primality test'''
    maxDivisionsByTwo = 0
    ec = mrc-1
    while ec % 2 == 0:
        ec >>= 1
        maxDivisionsByTwo += 1
    assert(2**maxDivisionsByTwo * ec == mrc-1)
  
    def trialComposite(round_tester):
        if pow(round_tester, ec, mrc) == 1:
            return False
        for i in range(maxDivisionsByTwo):
            if pow(round_tester, 2**i * ec, mrc) == mrc-1:
                return False
        return True
  
    # Set number of trials here
    numberOfRabinTrials = 20 
    for i in range(numberOfRabinTrials):
        round_tester = random.randrange(2, mrc)
        if trialComposite(round_tester):
            return False
    return True
  
if __name__ == '__main__':
    while True:
        n = 1024
        prime_candidate = getLowLevelPrime(n)
        if not isMillerRabinPassed(prime_candidate):
            continue
        else:
            print(n, "bit prime is: \n", prime_candidate)
            break
输出:

注意: Python中大型素数的库生成

pycrypto库是安全哈希函数和各种加密算法的全面集合。它还包括加密/解密设置中通常需要的基本功能,例如随机数生成和随机素数生成。使用pycrypto getPrime模块可以实现生成具有指定位大小的随机素数的目标。
生成随机n位素数的语法为:

from Crypto.Util import number
number.getPrime(n)