【问题标题】:Use RSA private key to generate public key?使用 RSA 私钥生成公钥?
【发布时间】:2011-07-11 18:37:46
【问题描述】:

这个我不是很懂:

根据https://www.madboa.com/geek/openssl/#key-rsa,您可以从私钥生成公钥。

openssl genrsa -out mykey.pem 1024
openssl rsa -in mykey.pem -pubout > mykey.pub

我最初的想法是它们是成对生成的。

RSA 私钥是否包含总和?还是公钥?

【问题讨论】:

  • 致所有使用 rsa 和 openssl 并希望加密 5 KB 等大文件的人。请记住,公钥的大小应与您要加密的内容成比例或更大,否则您将收到“文件太大无法加密错误”。我总结一下,您生成了一个相当大且严肃的私钥,并从中生成了您的私钥,以便您可以处理大量数据。我告诉了我在 openssl 中认识的人关于这个缺陷的信息,他们应该让它自行循环,否则你将花费大量时间来弄清楚它为什么抱怨大小。
  • Kent Hansen 描述的问题是由于直接在纯文本数据上使用 RSA,出于安全原因,在任何情况下都不应该这样做。而是使用经过充分分析的混合加密方案,例如 RSA-KEM (tools.ietf.org/html/rfc5990#appendix-A),并将经过身份验证的对称加密方案(例如 encrypt-then-HMAC)应用于数据。
  • 这可能会有所帮助:jason4zhu.blogspot.jp/2014/10/…
  • @SteffenUllrich 在此链接中的回答解释了原因:security.stackexchange.com/questions/172274/…

标签: openssl rsa public-key-encryption


【解决方案1】:
openssl genrsa -out mykey.pem 1024

实际上会产生一个公钥 - 私钥对。该对存储在生成的mykey.pem 文件中。

openssl rsa -in mykey.pem -pubout > mykey.pub

将提取公钥并将其打印出来。 Here 是一个可以更好地描述这一点的页面的链接。

编辑:检查示例部分here。仅输出私钥的公共部分:

openssl rsa -in key.pem -pubout -out pubkey.pem

要获取用于 SSH 的可用公钥,请使用 ssh-keygen

ssh-keygen -y -f key.pem > key.pub

【讨论】:

  • 令人困惑的是,各地教程中的每个人都在说使用 openssl genrsa 命令将生成私钥,因为他们忘记了它也在生成公钥
  • @jaime 你真的能怪他们吗?官方文档完全没有提到公钥。 “描述:genrsa 命令生成一个 RSA 私钥。” openssl.org/docs/apps/genrsa.html
  • @jaime,那是因为它没有 - genrsa 只生成私钥,公钥不会被存储。但是,如果您拥有私钥,那么您可以从中计算(派生)公钥 - 这就是上面的第二个命令所做的。它计算而不是提取公钥。
  • @steveayre 据我了解,RSA 密钥只是两个指数(普通文献中的ed)。两者都不是数学上私有或公共的,它们是在创建时任意分配的标签。它们可以很容易地反向分配。从另一个生成一个是一个等效的问题。 .pem 格式包含一大堆信息,包括 both 指数和两个键,对吧?
  • @steveayre 大多是错误的。公共 RSA 密钥组件 (n, e) 生成并嵌入到使用openssl genrsa 命令创建的私有 RSA 密钥文件中。但是,不会在同一步骤中创建单独的公钥文件。要将私钥文件中的公钥提取到单独的公钥文件中,请使用 openssl rsa -in private.pem -pubout -out public.pem 命令。当您以这种方式生成公钥时,它是从私钥文件中提取的,而不是计算出来的。有关详细信息,请参阅下面的答案。
【解决方案2】:

在大多数生成 RSA 私钥的软件中,包括 OpenSSL 的,私钥表示为 PKCS#1 RSAPrivatekey 对象或其一些变体:

A.1.2 RSA 私钥语法

RSA 私钥应该用 ASN.1 类型表示
RSAPrivateKey:

  RSAPrivateKey ::= SEQUENCE {
      version           Version,
      modulus           INTEGER,  -- n
      publicExponent    INTEGER,  -- e
      privateExponent   INTEGER,  -- d
      prime1            INTEGER,  -- p
      prime2            INTEGER,  -- q
      exponent1         INTEGER,  -- d mod (p-1)
      exponent2         INTEGER,  -- d mod (q-1)
      coefficient       INTEGER,  -- (inverse of q) mod p
      otherPrimeInfos   OtherPrimeInfos OPTIONAL
  }

如您所见,这种格式有许多字段,包括模数和公共指数,因此是 RSA public key 中信息的严格超集。

【讨论】:

  • 你的意思是给定一个私钥,生成公钥在数学上是可行的吗? RSA 的优势难道不是因为它在计算上无法在给定另一个密钥的情况下生成一个密钥吗?
  • @Raam:不,RSA 的优势在于无法从公众那里生成私钥。生成私有形式的公共形式是微不足道的。
  • @GregS,为什么?密钥由模数和指数组成。如果可以从这两个数字中计算出另一个指数,那么 RSA 将很容易被破解。那么 OpenSSL 私钥包含的不仅仅是指数和模数吗?
  • @Calmarius:谁说密钥由模数和指数组成?那将是最小的私钥,但通常私钥包括其他组件,例如主要因素。阅读答案了解详情。
  • @JamesKPolk 这不一定是真的。 如果公共指数很大(即具有与私有指数相同的属性),则公共密钥可能无法重建。大多数库不支持这一点,但 RSA 密码系统当然不需要您从私钥重建公钥。
【解决方案3】:

在此代码中,我们首先创建 RSA 密钥,该密钥是私有的,但它也有一对公钥,因此要获取您的实际公钥,我们只需这样做

openssl rsa -in mykey.pem -pubout > mykey.pub

希望你能得到更多信息check this

【讨论】:

    【解决方案4】:

    人们正在寻找 SSH 公钥...

    如果您希望提取用于 OpenSSH 的公钥,则需要稍微不同地获取公钥

    $ ssh-keygen -y -f mykey.pem > mykey.pub
    

    此公钥格式与 OpenSSH 兼容。将公钥附加到remote:~/.ssh/authorized_keys 就可以了


    来自SSH-KEYGEN(1)的文档

    ssh-keygen -y [-f input_keyfile]  
    

    -y 此选项将读取私有 OpenSSH 格式文件并将 OpenSSH 公钥打印到标准输出。

    【讨论】:

    • 这就像一个魅力!它会生成 Github 采用的格式! Github 不采用 PEM 格式。先前的答案建议 openssl rsa -in key.pem -pubout -out pubkey.pem 没有被接受,因为显然它的输出是 pem 格式的公钥。所以我收到了这个错误:“密钥无效。它必须以'ssh-rsa'或'ssh-dss'开头。检查你是否复制了密钥的公共部分”。但是ssh-keygen -y [-f input_keyfile] 会生成 Github 采用的正确格式。
    【解决方案5】:

    公钥并不像某些人认为的那样存储在 PEM 文件中。私钥文件中存在以下 DER 结构:

    openssl rsa -text -in mykey.pem

    RSAPrivateKey ::= SEQUENCE {
      version           Version,
      modulus           INTEGER,  -- n
      publicExponent    INTEGER,  -- e
      privateExponent   INTEGER,  -- d
      prime1            INTEGER,  -- p
      prime2            INTEGER,  -- q
      exponent1         INTEGER,  -- d mod (p-1)
      exponent2         INTEGER,  -- d mod (q-1)
      coefficient       INTEGER,  -- (inverse of q) mod p
      otherPrimeInfos   OtherPrimeInfos OPTIONAL
    }
    

    所以有足够的数据来计算公钥(模数和公共指数),这就是openssl rsa -in mykey.pem -pubout 所做的

    【讨论】:

    • 私钥也是派生出来的,看privateExponent字段。您可以使用 openssl rsa -text -in mykey.pem 查看字段
    • 公钥其实存放在pem中,因为pem还包括e和d,也就是公钥。与离散对数算法不同,RSA 公钥不能仅从私钥 (d,n) 计算得出。它之所以存在只是因为 rsa 规范指示将其与私钥和其他信息一起存储。
    • 是的,这个答案的所有意图和目的错误。公共指数和模数都在那里,所以公钥肯定存在。除了轻松检索其公钥无需任何计算之外,不需要其中的公共指数。
    • @MaartenBodewes:答案是正确的。引用的内容取自相关 RFC,作为 PRIVATE 密钥存储的值。这两个值也/仅用于公钥加密不会改变这是私钥数据。在过去的两天里,我学到了所有这些东西,不是通过提问,而是通过查找和阅读相关标准。我现在了解所有关于 ASN.1、DER、PEM 和 RSA 的知识(也许不是所有关于 RSA)。
    • @AlastairG 如果你知道公共指数是私钥的一部分,那么你就没有理解这门课程。它仅用于方便和/或执行验证(可以作为防御侧通道攻击的一部分)。请注意,接受的答案将文件标识为密钥 pair。过去的 2 天,天哪,我过去的 17 年呢?
    【解决方案6】:

    使用以下命令:

    1. openssl req -x509 -nodes -days 365 -sha256 -newkey rsa:2048 -keyout mycert.pem -out mycert.pem

       Loading 'screen' into random state - done
       Generating a 2048 bit RSA private key
       .............+++
       ..................................................................................................................................................................+++
       writing new private key to 'mycert.pem'
       -----
       You are about to be asked to enter information that will be incorporated
       into your certificate request.
       What you are about to enter is what is called a Distinguished Name or a DN.
       There are quite a few fields but you can leave some blank
       For some fields there will be a default value,
       If you enter '.', the field will be left blank.
      
    2. 如果您检查将有一个由名称创建的文件:mycert.pem

    3. openssl rsa -in mycert.pem -pubout > mykey.txt

      writing RSA key
      
    4. 如果您检查相同的文件位置,则会创建一个新的公钥mykey.txt

    【讨论】:

    • 这很愚蠢;当您想要的只是一个密钥对时,无需付出额外的努力来创建无用的证书。对于您想要证书的其他问题,这可能是一个答案。
    【解决方案7】:

    我下面的答案有点冗长,但希望它提供了以前答案中缺少的一些细节。我将从一些相关的陈述开始,最后回答最初的问题。

    要使用 RSA 算法加密某些内容,您需要模数和加密(公共)指数对(n,e)。那是你的公钥。要使用 RSA 算法解密某些内容,您需要模数和解密(私有)指数对(n,d)。那是你的私钥。

    要使用 RSA 公钥加密某些内容,您将明文视为一个数字并将其提升到 e 模数 n 的幂:

    ciphertext = ( plaintext^e ) mod n
    

    要使用 RSA 私钥解密某些内容,您将密文视为一个数字并将其提升到 d 模数 n 的幂:

    plaintext = ( ciphertext^d ) mod n
    

    要使用 openssl 生成私有 (d,n) 密钥,您可以使用以下命令:

    openssl genrsa -out private.pem 1024
    

    要使用 openssl 从私钥生成公钥 (e,n) 密钥,您可以使用以下命令:

    openssl rsa -in private.pem -out public.pem -pubout
    

    要剖析上述 openssl 命令生成的 private.pem RSA 私钥的内容,请运行以下命令(此处的输出截断为标签):

    openssl rsa -in private.pem -text -noout | less
    
    modulus         - n
    privateExponent - d
    publicExponent  - e
    prime1          - p
    prime2          - q
    exponent1       - d mod (p-1)
    exponent2       - d mod (q-1)
    coefficient     - (q^-1) mod p
    

    私钥不应该只由 (n, d) 对组成吗?为什么有 6 个额外的组件?它包含 e(公共指数),以便可以从 private.pem 私有 RSA 密钥生成/提取/派生公共 RSA 密钥。其余 5 个组件用于加速解密过程。事实证明,通过预先计算和存储这 5 个值,可以将 RSA 解密速度提高 4 倍。没有这 5 个组件,解密也可以工作,但如果你手边有它们,它可以更快地完成。加速算法基于Chinese Remainder Theorem

    是的,private.pem RSA 私钥实际上包含所有这 8 个值;当您运行上一个命令时,它们都不会即时生成。尝试运行以下命令并比较输出:

    # Convert the key from PEM to DER (binary) format
    openssl rsa -in private.pem -outform der -out private.der
    
    # Print private.der private key contents as binary stream
    xxd -p private.der
    
    # Now compare the output of the above command with output 
    # of the earlier openssl command that outputs private key
    # components. If you stare at both outputs long enough
    # you should be able to confirm that all components are
    # indeed lurking somewhere in the binary stream
    openssl rsa -in private.pem -text -noout | less
    

    PKCS#1 v1.5 推荐这种 RSA 私钥结构作为替代 (second) 表示。 PKCS#1 v2.0 标准从替代表示中完全排除了 e 和 d 指数。 PKCS#1 v2.1v2.2 建议通过可选地包括更多与 CRT 相关的组件来进一步更改替代表示。

    要查看 public.pem 公共 RSA 密钥的内容,请运行以下命令(此处的输出被截断为标签):

    openssl rsa -in public.pem -text -pubin -noout
    
    Modulus             - n
    Exponent (public)   - e
    

    这里没有惊喜。正如承诺的那样,它只是 (n, e) 对。

    现在终于回答了最初的问题:如上所示,使用 openssl 生成的私有 RSA 密钥包含公钥和私钥的组成部分等等。当您从私钥生成/提取/派生公钥时,openssl 会将其中两个组件 (e,n) 复制到一个单独的文件中,该文件将成为您的公钥。

    【讨论】:

    • 您写了“从私钥生成公共 (d,n) 密钥...”。不应该是“(e,n)”吗?不过,感谢您的出色回答!
    • 您正在将 v1.5 中的(外部)“语法”与更高版本中的语义进行比较;检查 2.0 #11.1.2 和 2.1 和 2.2 #A.1.2 你会看到 n,e,d 仍然存在。 (正如詹姆斯波尔克的回答已经指出的那样。)
    • 看来公共指数e 总是65537 0x010001。这可能是选择公共指数的事实,这可能就是手册页中的原因,几乎每个地方genrsa 都被解释为to generate the private key。公开的有点明显。
    • 我可以从 (n, d) 中计算出 (n, e) only 吗?
    【解决方案8】:

    首先快速回顾一下 RSA 密钥的生成。

    1. 随机选择两个具有适当大小(p 和 q)的随机可能素数。
    2. 将两个素数相乘以产生模数 (n)。
    3. 选择一个公共指数 (e)。
    4. 对素数和公共指数进行一些数学运算以产生私人指数 (d)。

    公钥由模数和公共指数组成。

    最小的私钥由模数和私有指数组成。从已知模数和私有指数到相应的公共指数,没有计算上可行的万无一失的方法。

    但是:

    1. 实用的私钥格式几乎总是存储多于 n 和 d。
    2. e 通常不是随机选择的,而是使用少数众所周知的值之一。如果 e 是众所周知的值之一,并且您知道 d,那么通过反复试验很容易找出 e。

    所以在大多数实际的 RSA 实现中,您可以从私钥中获取公钥。有可能建立一个基于 RSA 的密码系统,而这是不可能的,但这不是完成的事情。

    【讨论】:

      【解决方案9】:

      似乎是流行的非对称密码学的一个共同特征;公钥/私钥的生成涉及生成私钥,其中包含密钥对:

      openssl genrsa -out mykey.pem 1024
      

      然后发布公钥:

      openssl rsa -in mykey.pem -pubout > mykey.pub
      

      openssl rsa -in mykey.pem -pubout -out mykey.pub
      

      DSA 和 EC 加密密钥具有相同的功能: 例如。

      openssl genpkey -algorithm ed25519 -out pvt.pem
      

      然后

      openssl pkey -in pvt.pem -pubout > public.pem
      

      openssl ec -in ecprivkey.pem -pubout -out ecpubkey.pem
      

      公共部分参与解密,将其作为私钥的一部分保存可以加快解密速度;它可以从私钥中删除并在需要时进行计算(用于解密),作为使用密码/密钥/短语加密或保护私钥的替代或补充。例如。

      openssl pkey -in key.pem -des3 -out keyout.pem
      

      openssl ec -aes-128-cbc -in pk8file.pem -out tradfile.pem
      

      You can replace the first argument "aes-128-cbc" with any other valid openssl cipher name

      【讨论】:

        【解决方案10】:

        名为“私钥”的文件包含比单独的私钥更多的信息,它包含生成私钥/公钥对所需的所有数据(素数、模数、指数等)。

        而且很容易看到这些信息:

        openssl genrsa -out private.pem 1024   #generate private key file
        openssl rsa -in private.pem -text      #view info in the private key file
        openssl rsa -in private.pem -pubout -out public.pem  #extract public key to file
        openssl rsa -in public.pem -pubin -text  #view info in the public key file
        

        您将看到该私钥文件包含素数和所有其他信息,而公共文件仅包含模数和公共指数。

        【讨论】: