【发布时间】:2018-05-04 18:34:28
【问题描述】:
目前我尝试从 NIST(附录 B3.2.1)的 FIPS186-4 中显示的算法实现 generate_random_prime() 函数,请参阅 here。
但由于 Python 的精度,步骤 4.4 似乎存在很大问题(如果 p
要显示我的代码的相关部分和问题,请参见以下示例:
import os
from decimal import Decimal
import math
for i in range(100):
nlen = 2048 #my key-size should be 2048bit
p = int.from_bytes(os.urandom(int(2048/2/8)), byteorder = "little") #see Ann1 and Ann2
print(p < Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)
Ann1: 2048/2/8 因为字节 Ann2:我知道 os.urandom 不是最好的生成器——我稍后会使用一个经过批准的生成器……对于测试阶段,我认为它应该是可以接受的……
结果总是“真”——所以算法永远不会离开步骤 4.4。
我认为问题是Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1),因为它的结果是Decimal('2.542322012307292741109308792E+308')。通过int(Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1))转换为int,结果为
254232201230729274110930879200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
四舍五入! - 这是总是 True 结果的原因吗?我认为在这种情况下,永远不可能得到小于Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)的p
我该如何解决这个问题?
__
编辑:发现一个错误:
Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1) 应该是 Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2-1)))),所以这个结果应该是 Decimal('1.271161006153646370554654396E+308') 而不是 Decimal('2.542322012307292741109308791E+308')
【问题讨论】:
-
你为什么要使用十进制?
-
我不是一个非常高级的python程序员......但在某些情况下我会因为大整数和小数而出错,所以我在任何情况下都尝试使用小数......
-
该算法中的每个步骤,包括步骤 4.4,都假定使用整数实现。不是浮点数,不是十进制,只是整数。您不需要对 sqrt(2)*(...) 进行高度准确的近似,您只需要一个可以快速计算的相当准确的 上限。或者您可以为常见的素数大小(如 1024 位和 2048 位)预先计算此值。
标签: python math int decimal primes