是否可以使用ssh密钥对文件签名?


36

我使用SSH(准确地说,是Linux上的OpenSSH 5.5p1)。我有一把钥匙,上面有一个密码短语。我将其用于通常的登录计算机内容。

我也可以用它来签名文件吗?

据我了解,SSH密钥是RSA(或DSA)密钥,在SSH登录过程中,它用于对发送到服务器的消息进行签名。因此,从原理上和实践上,它都可以用来签名事物-确实,这是它的唯一目的。

但据我所知,没有办法使用密钥对任意文件进行签名(例如,使用PGP)。有什么办法可以做到这一点?


OpenSSH不会使用Ed25519作为dat协议吗?似乎只是工具问题。
巴勃罗

Answers:


24

单独使用OpenSSH工具可能无法做到这一点。

但是使用OpenSSL工具可以很容易地完成。实际上,至少有两种方法可以做到这一点。在下面的示例中,~/.ssh/id_rsa是您的私钥。

一种方法是使用dgst

openssl dgst -sign ~/.ssh/id_rsa some-file

另一个正在使用pkeyutl

openssl pkeyutl -sign -inkey ~/.ssh/id_rsa -in some-file

这两个都将二进制签名写入标准输出。dgst带有一个-hex选项,将打印文本表示形式,其中包含有关签名形式的一些详细信息。pkeyutl带有一个-hexdump选项,它的作用不大。两者都将同时接受RSA和DSA密钥。我不知道输出的格式是什么。这两个命令产生不同的格式。我觉得pkeyutldgst更现代。

要验证这些签名:

openssl dgst -verify $PUBLIC_KEY_FILE -signature signature-file some-file

和:

openssl pkeyutl -verify -inkey $PUBLIC_KEY_FILE -sigfile signature-file -in some-file

这里的问题是$PUBLIC_KEY_FILE。OpenSSL无法读取OpenSSH的公钥格式,因此您不能仅使用id_rsa.pub。您有几种选择,都不是理想选择。

如果您具有5.6或更高版本的OpenSSH版本,则可以执行以下操作:

ssh-keygen -e -f ~/.ssh/id_rsa.pub -m pem

它将公共密钥以PEM格式写入标准输出,OpenSSL可以读取。

如果您有私钥,并且它是RSA密钥,则可以从中提取公钥(我假设PEM编码的私钥文件包含公钥的副本,因为无法导出公钥从私钥本身),并使用:

openssl rsa -in ~/.ssh/id_rsa -pubout

我不知道是否有DSA。请注意,此方法需要私钥所有者的一些合作,后者必须提取公钥并将其发送给可能的验证者。

最后,您可以使用由称为Lars的小伙编写的Python程序将公钥从OpenSSH转换为OpenSSL格式。


1
我只想指出,“不可能从私钥本身派生公钥”是不正确的。在实践中(也就是说,在所有实际使用的密码系统中)大多数时候,很容易从私钥派生公钥。
kirelagin 2014年

@kirelagin:我不知道。您能否告诉我或将我链接到有关如何进行的更多信息?
汤姆·安德森

1
我不确定是否有关于该主题的特别读物……让我们考虑一下。采用任何基于离散日志的密码系统(ElGamal)。在这种情况下,私钥是(组大小,生成器,电源),而公钥是(组大小,生成器,发电机^电源)。因此,日志很困难,但功能却并非如此,您只需进行计算即可。
kirelagin 2014年

对于RSA而言,这种转换实际上很困难,但是这里的情况略有不同。公钥是(n,d),私钥是(n,d ^(-1)mod phi(n))。如果您不存储phi(n),则反转d也将很困难,但这是窍门:几乎每个人都使用e = 65537(生成密钥时,可以选择更改此默认值,但是我从未见过)任何人使用它,因为它没有任何实际意义),因此从私有密钥派生出公共密钥是微不足道的。
kirelagin 2014年

使用椭圆曲线,实际上与离散对数和功率相同,因此反转很容易。就是说,我不确定其他密码系统,但是这三个是实际使用的密码系统。
kirelagin 2014年

10

@Tom的答案帮助我入门,但是并没有开箱即用。

这些命令将与:

  • OpenSSL 1.0.1 2012年3月14日
  • 开启SSH_5.9p1

使用pkeyutl

# openssl pkeyutl -sign -inkey ~/.ssh/id_sample -in $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl pkeyutl -verify -pubin -inkey pub -in $1 -sigfile $1.sig
Signature Verified Successfully

使用dgst

# openssl dgst -sign ~/.ssh/id_sample $1 > $1.sig
# ssh-keygen -e -f ~/.ssh/id_sample.pub -m PKCS8 > pub
# openssl dgst -verify pub -signature $1.sig $1
Verified OK

pkeyutl版本只能签名小型文件。尽管dgst可以对任意大文件进行签名,但是dgst在签署结果之前需要进行摘要。


对我来说,Stephen.z的答案也可以直接使用。首先,我一直玩汤姆的答案一段时间,最后发现Stephen.z的答案对我来说非常有效。谢谢Stephen.z!
Grzegorz Wierzowiecki '16


您是否尝试过使用pkeyutl仅对文件的哈希签名?
盖亚

-3

验证那些签名 -更简单的解决方案:

确保签名文档相同的更简单方法是重新生成数字签名文件,然后使用diff检查两个签名文件是否相同。


3
您正在考虑哈希,而不是签名。相似,但不相同:散列仅验证文件未更改;签名还可以验证其来源。
Piskvor 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.