使用RSA私钥生成公钥?

c2h*_*2h2 368 openssl rsa public-key-encryption

我真的不明白这个:

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

openssl genrsa -out mykey.pem 1024
openssl rsa -in mykey.pem -pubout > mykey.pub
Run Code Online (Sandbox Code Playgroud)

我最初的想法是,它们是一起生成的.RSA私钥是否包含总和?还是公钥?

Raa*_*aam 529

openssl genrsa -out mykey.pem 1024
Run Code Online (Sandbox Code Playgroud)

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

openssl rsa -in mykey.pem -pubout > mykey.pub
Run Code Online (Sandbox Code Playgroud)

将提取公钥并将其打印出来.以下是指向更好地描述此内容的页面的链接.

编辑:在这里查看示例部分.要输出私钥的公共部分:

openssl rsa -in key.pem -pubout -out pubkey.pem
Run Code Online (Sandbox Code Playgroud)

  • @jaime,那是因为它没有 - genrsa只生成私钥,公钥不会被存储.但是,如果你有私钥,那么你可以从中计算(派生)公钥 - 这就是上面的第二个命令.它计算而不是提取公钥. (116认同)
  • 令人困惑的是,每个教程中的每个人都在说使用openssl genrsa命令你会生成私钥,因为他们忘记了它也在生成PUBLIC KEY (47认同)
  • @jaime你能真的怪他们吗?官方文档对公钥一无所知."说明:genrsa命令生成一个RSA私钥." http://www.openssl.org/docs/apps/genrsa.html (13认同)
  • @steveayre我的理解是,RSA密钥只是两个指数(普通文献中的"e"和"d").这些都不是*数学上*私人或公共的,这些是在创建时任意分配的标签.它们可以很容易地反向分配.从另一个生成一个是一个等价的问题.`.pem`格式包含大量信息,包括*两个*exponents,所以两个键,对吧? (13认同)
  • @steveayre大多是错的.公共RSA密钥组件(n,e)DO生成并嵌入到使用`openssl genrsa`命令创建的私有RSA密钥文件中.但是,不会在同一步骤中创建单独的公钥文件.要将公钥从私钥文件中提取到单独的公钥文件中,请使用`openssl rsa -in private.pem -pubout -out public.pem`命令.以这种方式生成公钥时,它是从私钥文件中提取的,而不是计算的.有关详细信息,请参阅下面的答案. (12认同)
  • @FractalSpace,您可以从openssl生成的私钥文件生成公钥,因为它嵌入了公钥组件.如果它只有必要的最小(`n`,`d`)组件,你将无法从私有组件生成公共RSA密钥.另一方面,如果你知道两个初始素数(`p`和`q`),就可以从私有指数`d`和私有指数`d`生成公共指数`e`(和扩展公钥).并且通过扩展私钥)来自公共指数`e`. (5认同)
  • @steveayre部分正确.但是,有一个细微的区别:您可以从给定的私钥生成公钥,但*不是*反向. (2认同)
  • @Raam`openssl genrsa`不生成私有公钥对.它只生成一个私钥.然后使用数学关系从给定私钥"生成"公钥.请参阅https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29 (2认同)

Tha*_*you 266

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

如果您要提取用于OpenSSH的公钥,则需要以不同方式获取公钥

$ ssh-keygen -y -f mykey.pem > mykey.pub
Run Code Online (Sandbox Code Playgroud)

此公钥格式与OpenSSH兼容.附加公钥remote:~/.ssh/authorized_keys,你会很高兴


来自的文档 SSH-KEYGEN(1)

ssh-keygen -y [-f input_keyfile]  
Run Code Online (Sandbox Code Playgroud)

-y此选项将读取私有的OpenSSH格式文件,并将OpenSSH公钥打印到stdout.

  • 这就像一个魅力!它生成Github采用的格式!Github没有采用PEM格式.以前的答案建议`openssl rsa -in key.pem -poutout -out pubkey.pem`没有被接受,因为它的输出显然是一个pem格式的公钥.所以我得到了这个错误:"密钥无效.它必须以'ssh-rsa'或'ssh-dss'开头.检查你是否正在复制密钥的公共一半".但是`ssh-keygen -y [-f input_keyfile]`生成Github采用的正确格式. (3认同)

Jam*_*olk 67

在大多数生成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
  }
Run Code Online (Sandbox Code Playgroud)

如您所见,此格式包含许多字段,包括模数和公共指数,因此是RSA公钥中信息的严格超集.

  • @Raam:不,RSA的优势在于从公众生成私钥是不可行的.生成私有的公共形式是微不足道的. (30认同)
  • @JamesKPolk 这不一定是真的。*如果*公共指数很大(即与私有指数具有相同的属性),那么公共密钥“可能”无法重建。大多数库不支持这一点,但 RSA 密码系统当然不要求您从私钥重建公钥。 (2认同)

gol*_*lem 25

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

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

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

ciphertext = ( plaintext^e ) mod n
Run Code Online (Sandbox Code Playgroud)

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

plaintext = ( ciphertext^d ) mod n
Run Code Online (Sandbox Code Playgroud)

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

openssl genrsa -out private.pem 1024
Run Code Online (Sandbox Code Playgroud)

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

openssl rsa -in private.pem -out public.pem -pubout
Run Code Online (Sandbox Code Playgroud)

要剖析由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
Run Code Online (Sandbox Code Playgroud)

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

是的,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
Run Code Online (Sandbox Code Playgroud)

PKCS私有密钥的这种结构由PKCS#1 v1.5推荐作为替代(第二)表示.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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 看起来公共指数“e”始终是 65537“0x010001”。这可能是选择公共指数的事实,这可能就是为什么在手册页中,几乎所有“genrsa”都被解释为“生成私钥”。公共的就很明显了。 (2认同)
  • 我可以从 (n, d) **仅** 计算出 (n, e) 吗? (2认同)

Uxi*_*xio 21

有些人认为公钥不存储在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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 私钥也派生,请查看privateExponent字段。您可以在mykey.pem中使用openssl rsa -text-查看字段 (2认同)
  • 公钥其实是存放在pem里面的,因为pem里面还包括e和d,也就是公钥。与离散对数算法不同,rsa 公钥不能仅根据私钥 (d,n) 计算。它存在只是因为 rsa 规范指示将其与私钥和其他信息一起存储。 (2认同)
  • 是的,这个答案在所有意图和目的上都是**错误**。公共指数和模数都在那里,因此公钥肯定存在。除了轻松检索其公钥(无需任何计算)之外,不需要其中的公共指数。 (2认同)
  • @AlastairG 如果您了解到公共指数是私钥的一部分,那么您就没有理解该课程。它仅可用于方便和/或执行验证(这可以是防御侧通道攻击的一部分)。请注意,接受的答案将文件标识为密钥*对*。最后的两天,天啊,我最后的17年呢? (2认同)
  • @Maarten 公钥不作为公钥存在,即作为单独的实体存在。说公钥存在就像说一个装有鸡蛋、糖、面粉和各种其他成分的购物篮里有一个蛋糕。我同意您不需要计算这些值,但您不能仅仅因为作者使用了“计算”一词而不是“生成”一词,就认为答案是错误的(以粗体大写字母表示)。 (2认同)

Rdx*_*Rdx 8

在这个代码中首先我们创建RSA密钥,这是私有的,但它也有一对公钥,所以为了得到你的实际公钥我们只是这样做

openssl rsa -in mykey.pem -pubout > mykey.pub
Run Code Online (Sandbox Code Playgroud)

希望你得到更多信息检查这一点


plu*_*ash 6

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

  1. 随机选择两个随机大小合适的素数(p和q)。
  2. 将两个素数相乘以产生模数(n)。
  3. 选择一个公共指数(e)。
  4. 用素数和公共指数做一些数学运算以产生私有指数(d)。

公用密钥由模数和公用指数组成。

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

然而:

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

因此,在大多数实际的RSA实现中,您可以从私钥中获取公钥。在这不可能的情况下,有可能构建基于RSA的密码系统,但这并不是一成不变的事情。


Men*_*rel 6

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

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

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
Run Code Online (Sandbox Code Playgroud)

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