为什么这个提交将RSA公共指数设置为1有问题?

时间:2013-07-05 13:39:52

标签: security cryptography salt-stack

我在Hacker News的this commit中看到了SaltStack,但我并不确切地知道它的作用或原始版本为何会出现加密错误。 (我也不太了解密码学的具体细节如何工作。)

-    gen = RSA.gen_key(keysize, 1, callback=lambda x, y, z: None)
+    gen = RSA.gen_key(keysize, 65537, callback=lambda x, y, z: None)

有人可以详细解释为什么选择“1”被替换了吗?为什么“65537”更好?

1 个答案:

答案 0 :(得分:64)

你基本上问了三个问题:

  • 这段代码在做什么?
  • 为什么1不好?
  • 为何将其替换为65537

听起来你没有很多加密背景,所以我也会尝试填补其中的一些空白。

这段代码在做什么?

要理解为什么1的原始值是一个破碎的选择,您必须了解RSA的工作原理。

RSA是密码系统 - 一种执行密钥生成,加密和解密的方式 - 这样您就可以安全地将消息发送给其他人。 RSA是名为 公钥密码系统 的类的成员,因为用于加密邮件的密钥是 public 可以被大家自由地知道。用于解密使用公钥加密的邮件的密钥是秘密的,只有您自己知道,因此我们将其称为 私钥

如果您将挂锁和钥匙想象为公钥和私钥的模拟,您可以看到这可能如何与真实世界的消息一起使用:

  • 鲍勃给爱丽丝一个挂锁(他的公钥)并保持钥匙锁(他的私钥)。
  • 现在,如果Alice想给Bob发一条消息,她会在一个盒子里放一条消息,把挂锁放在一个盒子上,然后把盒子发给他。
  • 只有Bob有钥匙,所以只有Bob可以解锁挂锁并进入包装盒内。

要实际生成密钥,RSA需要三个重要数字:

  • “N”,两个非常大的素数p和q
  • 的乘积
  • “e”,“公众指数”
  • “d”,“私人指数”

RSA的很大一部分安全性来自这样一个事实:鉴于dNe应该很难找出<N,e>。 RSA中的公钥由两个数字组成:<N,d>,而私钥为1

换句话说,如果我知道鲍勃的挂锁是什么样的,那么应该非常困难来反向设计一个可以打开鲍勃挂锁的钥匙。

为什么1不好?

def gen_keys(keydir, keyname, keysize, user=None): # Generate a keypair for use with salt # ... gen = RSA.gen_key(keysize, 1, callback=lambda x, y, z: None) 是一个糟糕的选择,因为它会使非常容易对可以打开Bob挂锁的密钥进行反向工程,这与我们想要的相反。

完整有问题的部分如下所示:

e = 1

这是一个Python片段,它使用N生成一个RSA密钥。

edd*e = 1 mod (p-1)(q-1) 之间的关系由:

e = 1

但是等一下:如果你选择d = 1 mod (p-1)(q-1) ,就像SaltStack那样,那你就有问题了:

d

现在你有了私钥!安全性被破坏,因为您可以找出m是什么。所以你可以解密每个人的传输 - 你已经做到这一点,以便你可以通过挂锁轻松获得Bob的钥匙。糟糕。

实际上比这更糟糕。在RSA中,加密意味着您有一条消息<N,e>要使用公钥c传输您要加密的消息。加密消息 c = m^e (mod N) 计算如下:

e = 1

所以,如果是m^e = m,那么c = m mod N,你有m < N

但是如果m mod N,那么m就是 c = m 所以你有:

1

加密文本与消息文本相同,因此根本不会发生加密! Double oops。

希望明确为什么65537是一个糟糕的选择!

为什么e = 3更好?

65537似乎是一个不寻常的,随意的选择。你可能想知道为什么,例如,我们不能只选择e。较低的 c = m^e (mod N) 是加密速度加快,因为加密我们必须执行的任何事情:

m^e

,当e很大时,e = 3可能是一个非常大的数字。

事实证明,65537主要是出于与现有硬件和软件兼容的原因,以及其他一些原因。 This Cryptography StackExchange answer详细解释了这一点。

使用合适的随机填充方案,您可以选择几乎任何高于1的奇数,而不会影响安全性,因此{{1}}是最大化性能的选择。