目前我尝试使用NIST的FIPS186-4(附录B3.2.1)中显示的算法实现generate_random_prime() - 函数,请参阅here。
但是步骤4.4似乎有一个大问题(如果p< sqrt(2)*(2 **((nlen / 2)-1)),因为Python的精确性。
显示我的代码的相关部分和问题,请参阅此示例:
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不是最好的发电机 - 我后来会使用一个批准的发电机......在测试阶段我认为应该是可以接受的......
结果总是&#34; True&#34; - 所以算法永远不会离开步骤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
它被围捕了! - 这是永远真实结果的原因吗?我认为在这种情况下,永远不可能得到小于Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)
我该如何解决这个问题?
__
编辑:发现一个错误:
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')
答案 0 :(得分:2)
您不断在浮点数,整数和Decimal
之间进行转换。放弃使用float
;这包括不使用生成float
值的函数,例如math.sqrt()
。
改为坚持Decimal
个对象,只将最终值转换为整数:
int(Decimal(2).sqrt() * 2 ** ((nlen // 2) - 1))
注意//
的使用,使用整数除法,而不是真正的除法(再次产生浮动)。