从私钥生成的公钥在 2 种情况下不同

Posted

技术标签:

【中文标题】从私钥生成的公钥在 2 种情况下不同【英文标题】:Generated public key from private key different in 2 cases 【发布时间】:2019-09-15 02:03:09 【问题描述】:

我正在尝试生成私钥和公钥对。我想使用私钥对我的 JWT 进行签名并将公钥发送给第 3 方以解码我的 JWT。

在我的 mac os 终端上,我生成了这样的密钥:

ssh-keygen -m PEM -t rsa -b 2048

现在我将 pkey 和 pkey.pub 分别作为私钥和公钥。现在在我的 Rails 控制台中,我尝试像这样获取私钥,效果很好:

rsa_private = OpenSSL::PKey::RSA.new(File.read("/path/to/private/key/pkey"))

rsa_private.to_s "-----BEGIN RSA PRIVATE KEY-----\nCONTENTS_OF_PKEY_FILE\n-----END RSA PRIVATE KEY-----\n"

现在在 Rails 中,我可以像这样从生成的私钥中获取公钥:

pub_key = rsa_private.public_key

但是当我尝试打印它的内容时,它与我运行 ssh-keygen 命令时生成的 pkey.pub 中的内容不同。

pub_key 看起来像这样:

"-----BEGIN PUBLIC KEY-----\nSOME_CONTENT\n-----END PUBLIC KEY-----\n"

但是我的 pkey.pub 文件看起来不一样,像这样:

ssh-rsa SOME_OTHER_CONTENT user@user.local

那么,我的问题是,我怎样才能为同一个私钥获得 2 个不同的公钥?我使用哪一个来解码我的 JWT?

【问题讨论】:

【参考方案1】:

密钥应该相同,但编码不同。

一个 RSA 密钥对由多个数字组成,私钥就是所有这些数据,公钥与删除的私钥相同。

数字可以以不同的顺序书写,以不同的格式编码。还可以使用密码加密密钥以进行存储(不是这种情况)。因此,具有相同键的文件看起来可能完全不同。

PEM 格式(带有BEGIN PUBLIC KEY 和 Base64 数据的格式)更常见于通用键,因此最好使用它。

更新: PEM 格式是带有页眉和页脚的 base64 编码的 DER。 DER 又是 ASN.1 的二进制表示。但是 SSH 使用了一种直接的密钥编码格式 (RFC4716)

例子:

% ssh-keygen -m PEM -t rsa -N '' -b 1024 -f ./rsa

% cat rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDRNFYxsULk6x90T0EE8iS3skfJJ407ef3WJJClre0k2sLJUJX6/Xbc3ObxNjixXcgIXp2H4oVOnNpujqFF/XM81zlpLjGT/4igtK1FjIHIaFyRheGuwplgwCkXlxAe/oH1Bb4nFXlD/kORmGgSfSE9BpH+HQU3IzyU1i0X9K828Q== vasfed@Vasiliys-MacBook-Pro.local

% ssh-keygen -e -m PEM -f ./rsa.pub
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBANE0VjGxQuTrH3RPQQTyJLeyR8knjTt5/dYkkKWt7STawslQlfr9dtzc
5vE2OLFdyAhenYfihU6c2m6OoUX9czzXOWkuMZP/iKC0rUWMgchoXJGF4a7CmWDA
KReXEB7+gfUFvicVeUP+Q5GYaBJ9IT0Gkf4dBTcjPJTWLRf0rzbxAgMBAAE=
-----END RSA PUBLIC KEY-----

% ssh-keygen -e -m PKCS8 -f ./rsa.pub
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRNFYxsULk6x90T0EE8iS3skfJ
J407ef3WJJClre0k2sLJUJX6/Xbc3ObxNjixXcgIXp2H4oVOnNpujqFF/XM81zlp
LjGT/4igtK1FjIHIaFyRheGuwplgwCkXlxAe/oH1Bb4nFXlD/kORmGgSfSE9BpH+
HQU3IzyU1i0X9K828QIDAQAB
-----END PUBLIC KEY-----

以上是同一密钥的 3 种不同编码,这里是后两者的 ASN 解码版本(通过 https://lapo.it/asn1js):

PEM,最低限度(模数和指数,无元数据):

SEQUENCE (2 elem)
  INTEGER (1024 bit) 146908353891476107599563957703741990254320034409224509383359005248419…
  INTEGER 65537

PKCS8,在这里我们看到完全相同的数字,但这次带有一些元数据:

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
    NULL
  BIT STRING (1 elem)
    SEQUENCE (2 elem)
      INTEGER (1024 bit) 146908353891476107599563957703741990254320034409224509383359005248419…
      INTEGER 65537

【讨论】:

虽然您的答案可能是非常笼统的,但 BEGIN PUBLIC KEY.pub 格式都使用相同的编码,所以它们应该是相同的(除了 BEGIN PUBLIC KEY 有标题/trailer 并换行,而 .pub 没有)。 @MartinPrikryl SSH 使用 RFC4716,而 ruby​​ 使用 PKCS 编码,请参阅更新示例 好的。与.pub使用相同编码的多行格式为BEGIN SSH2 PUBLIC KEY

以上是关于从私钥生成的公钥在 2 种情况下不同的主要内容,如果未能解决你的问题,请参考以下文章

从私钥派生 ECDSA 公钥

sh 从私钥生成rsa公钥

sh 从私钥生成rsa公钥

PHP:从私钥字符串/文件中获取 RSA 公钥

OpenSSL生成公私钥

生成公钥步骤