【问题标题】:is this a correct way to generate rsa keys?这是生成 rsa 密钥的正确方法吗?
【发布时间】:2011-02-17 11:24:33
【问题描述】:

这段代码是否会为我提供正确的 RSA 密钥值(假设其他功能正确)?我无法让我的程序正确解密,因为某些块没有正确解密

这是在python中:

import random
def keygen(bits):
    p = q = 3
    while p == q:
        p = random.randint(2**(bits/2-2),2**(bits/2))
        q = random.randint(2**(bits/2-2),2**(bits/2))
        p += not(p&1)                             # changes the values from 
        q += not(q&1)                             # even to odd

        while MillerRabin(p) == False:            # checks for primality
            p -= 2
        while MillerRabin(q) == False:
            q -= 2
    n = p * q   
    tot = (p-1) * (q-1)
    e = tot
    while gcd(tot,e) != 1:
        e = random.randint(3,tot-1)
    d = getd(tot,e)                       # gets the multiplicative inverse
    while d<0:                            # i can probably replace this with mod
        d = d + tot
    return e,d,n

生成一组密钥:

e = 3daf16a37799d3b2c951c9baab30ad2d

d = 16873c0dd2825b2e8e6c2c68da3a5e25

n = dc2a732d64b83816a99448a2c2077ced

【问题讨论】:

  • M2Crypto.RSA.gen_key 有什么问题?
  • 在我看来还可以,如果有点奇怪的话。
  • 这只是学术问题吗?你真的不想为真正的代码编写自己的加密货币。
  • 代码风格建议:去掉'== False',把'not'放在你的函数前面。此外,将其重命名为类似 is_prime() 将使代码更具可读性。我怀疑每个人都知道“MillerRabin()”是什么。

标签: python cryptography rsa public-key


【解决方案1】:

我假设您这样做是为了娱乐和学习,而不是为了需要真正的安全性。

以下是我注意到的一些事情(排名不分先后):

  1. 不能保证 n 的长度为 bits。它可能和bits - 4一样短。

  2. random 不是加密安全的随机数生成器。

  3. 选择公共指数 e 到 65537 是很常见的(并且同样安全)。这是一个素数,因此您可以用除数检查替换互素检查。

  4. 通过设置e = tot搜索e有点奇怪(互质检查肯定会失败)。

否则它看起来很好。钥匙似乎也可以正常工作。你有没有正确解密的块的例子吗?请记住,您只能加密小于n 的数据。因此,使用 128 位密钥(如您的示例)您无法加密所有 128 位数字。

【讨论】:

    【解决方案2】:

    在数学上,您的 ned 似乎遵守 RSA 规则(即对于每个素数 rnr2不除nder-1 的倒数)。然而,RSA 不止于此。它还规定了一些填充规则,这些规则控制消息(字节序列)如何转换为整数模n,然后返回。标准填充(请参阅PKCS#1)意味着消息中至少添加了 11 个字节,并且结果必须不再是 n。因此,对于 128 位模数 就像你展示的那样,加密的最大输入消息长度为 5 个字节。

    此外,一些 RSA 实现将拒绝使用对于安全性而言太小的 RSA 密钥。 128 位模数可以在几秒钟内分解(请参阅 this page 了解分解 Java 小程序,它使用 ECM 和二次筛来分解相对较小的数字,例如您的)。当前的因式分解记录是 768 位;为了短期安全,建议使用至少 1024 位的模数长度。典型的 RSA 实现将接受使用 512 位密钥,但许多人会拒绝任何比这更短的密钥。

    另一个可能的问题是 pq 的相对顺序。 PKCS#1 中列出的方程式假设 p > q(否则,在 CRT 部分中需要执行额外的减法)。如果您有 p ,那么某些实现可能会出错(我在 Windows 中使用 Microsoft 的 RSA 标准实现时遇到过这种情况)。只需比较 pq 并在必要时交换它们。

    仍然在实用性层面上,一些广泛的 RSA 实现将拒绝 RSA 密钥,使得公共指数 e 不适合 32 位整数(这包括 Windows 中使用的 RSA 实现,特别是通过 Internet Explorer 连接到 HTTPS 网站——所以当我写“广泛”时,我的意思是)。 RSA 安全性似乎不受 e 选择的影响,因此习惯上选择一个小的 e,这样可以加快使用公钥的部分(即加密,而不是解密,或签名验证,而不是签名生成)。 e = 3 是你能做的最好的,但出于传统原因(包括对所谓的弱点的历史误解),经常使用 e=65537。你只需要让 e 相对于 p-1q-1。在实际实现中,您首先选择 e,然后在 pq 的生成中循环,只要它们不匹配该附加规则.

    从安全角度来看:

    • 您的生成过程并不统一,因为某些素数会比其他素数更频繁地被选择。特别是,使得 p+2 也是素数的素数 p 几乎永远不会被选中。使用适当的模数大小,这应该不是问题(研究了那种特殊的偏见,发现不是大问题)但它仍然是糟糕的公共关系。

    • 你的 n 可能比你的目标尺寸小一点,以防 pq 都接近下限他们的世代范围的界限。避免这种情况的一种简单方法是将两者的范围限制为 [sqrt(2)*2b-1, 2b] em>p 和 q

    • 我不能保证您使用的 random 模块的安全性。 加密安全随机数生成器并非易事。

    • 一般而言,正确实施 RSA 而不通过各种侧通道(时序、缓存内存使用...)泄露机密信息并非易事。如果您希望实际设置中的安全性,您真的应该真的使用现有的包。我相信 Python 有办法与OpenSSL 交互。

    【讨论】:

    • random 在密码学上根本不安全;它使用 Mersenne Twister,可以通过读取几百个值来破解。
    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多