【问题标题】:Craking long RSA keys from public key only仅从公钥破解长 RSA 密钥
【发布时间】:2020-08-11 12:58:38
【问题描述】:

对于一场比赛,我正在尝试学习如何在仅给出公钥的情况下破解 RSA 密钥:

  • e = 65537
  • n = 632459103267572196107100983820469021721602147490918660274601

所以我关注了this webpagethis answer。并尝试过:

    >>> n = 632459103267572196107100983820469021721602147490918660274601
    >>> import math
    >>> math.floor(math.sqrt(n))
    795272974058324394239265341440
    >>> c = math.floor(math.sqrt(n))
    >>> for i in range(c-1,c-41,-2):
    ...     if c%i ==0:
    ...         print(i, c%i)
    ...

但它没有给我任何东西。我已经开始了蛮力方法:

>>> print(repr(math.sqrt(n)))
7.952729740583244e+29
>>> c = math.sqrt(n)
>>> int(c)
795272974058324394239265341440
>>> for i in range(c-1, 2, -2):
...     if n%i == 0:
...         print(i, n%i)
...

但是已经运行了半天了。我知道这很愚蠢,因为我正在测试甚至不是素数。有没有更明智的方法?

一开始我从 c 开始,它是一个偶数。我想从偶数减少第 2 步是愚蠢的,因为它只会导致我测试非因式分解器?

更新

在阅读了 Dan 的评论后,我现在正在尝试寻找一个小的因素,而不是从大的因素开始。

>>> for i in range(1,c-1,2):
...     if c%i ==0 and i%2 != 0 and i%5 !=0:
...         print(i, c%i)
...
1 0

【问题讨论】:

  • @orangecaterpillar 的回答很好。要记住的其他几件事...不要费心尝试以 5 结尾的奇数,根据定义(“5”除外),它们不会是素数。此外,如果这是为了比赛,他们可能通过将一个小素数(例如小于 10,000 的东西)乘以一个非常大的素数来创建模数。这不是正常的 RSA 密钥生成的工作方式,但对于比赛,他们可能希望奖励聪明人。所以也许在你从平方根下降之前也尝试一次。
  • @Dan 感谢您的洞察力!但是,我不明白拥有一个小的质数如何更聪明......我肯定错过了一些东西
  • 首先,尽管有各种 cmets 和答案,但在使用二次筛算法的笔记本电脑上,这个数字并不算大。如果您受到启发,您可以尝试自己编写代码。然而,二次筛太复杂了,无法指望参赛者对其进行编程。因此,要么构造模数以使其容易受到一些捷径攻击,要么您遗漏了一些信息,或者您只需上网并找到一个合适的因式分解程序来为您做这件事。您会更好地了解其中的哪一种情况。
  • 嗨@RevolucionforMonica -- 不,你没有错过任何东西,我所说的和总统一样,谁说得最好......“要么模数被构造成容易受到一些捷径攻击”。我的建议是,您的算法(从平方根附近开始)将首先尝试大小相似的因子,然后走向极端……但也许这些因子类似于 107 和 。您的算法只会在最后发现(需要很长时间)。尝试暴力破解前约 10,000 个小素数并查看其中一个是否有效,这并没有什么坏处。
  • @Dan:您的建议总体上是好的。但我已经考虑了这个数字,它有不小的因素。有趣的是,有人编写了一个程序来尝试他们在这些比赛中看到的所有“快捷方式”RSA 攻击。代码是here

标签: python security rsa


【解决方案1】:

TL;DR:破解长 RSA 密钥在计算上很困难(即没有已知的解决方案可以在多项式时间内运行),虽然您的算法可能不是最有效的,但没有人找到可以破解长 RSA 密钥的算法(使用经典计算机 - 量子计算机的Shor's algorithm 可以在多项式时间内破解长 RSA 密钥)。


更长的答案:

为了估计你的程序执行需要多长时间,我编写了以下 python:

import time

n = 632459103267572196107100983820469021721602147490918660274601
c = 795272974058324394239265341440

test_size = 100000

start_time = time.time()

for i in range(c-1, c-test_size, -2):
    if n%i == 0:
        print(i, n%i)

time_elapsed = (time.time() - start_time)

print("Elapsed Time for %i iterations: %f seconds" % (test_size, time_elapsed))
seconds_in_a_year = 31557600
projected_time = time_elapsed * (c / 2 / test_size) / seconds_in_a_year
print("Projected Time for %i iterations: %i years" % (c, projected_time))

当我在我的电脑上运行它时,输出是:

Elapsed Time for 100000 iterations: 0.024008 seconds
Projected Time for 795272974058324394239265341440 iterations: 3025094101018381 years

那是太多年了!

关于您链接到的文章和答案需要注意的一点是,它们提供了带有快捷键的示例。使用 RSA 密码系统并起作用的原因是,当生成足够大的密钥时,使用任何已知程序来确定私钥在计算上是难以处理的(即,即使地球上的所有计算资源一起工作,也需要很多生命周期)给定公钥。随着计算机变得越来越快,被认为足够大的密钥可能会发生一些变化,其他更难破解的公钥密码系统也可以用于更高的安全性,但就目前而言,1,024 到 4,096 位 RSA 被广泛使用在生产环境中。您提供的 n 是 199 位(math.log(n,2)),所以我想它可以在合理的时间内被蛮力强制......只是不使用笔记本电脑而不使用 python(如果您尝试相同的蛮力方法在 C 中它仍然不会在合理的时间内运行 - 但它会比 python 快)。如果您对解决离散对数问题或整数分解的其他算法感兴趣,我对此了解不多,但我可以告诉您对于非量子计算机没有已知的有效算法.

如果我有时间,我会回来用一些 C 代码更新这个答案以进行比较,我只是想指出你没有做错任何事情,你正在尝试解决一个棘手的问题。

【讨论】:

  • "...所以我想它可以在合理的时间内被蛮力强制...只是不使用笔记本电脑..." 我能够在 2 秒内将其计算在内笔记本电脑。
  • @PresidentJamesMoveonPolk 您能否分享有关您的解决方案的更多信息?
猜你喜欢
  • 2011-05-03
  • 2018-12-10
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多