我使用 libressl 3.0 使用曲线生成了一个私钥secp521r1
。
openssl genpkey -aes128 -algorithm EC -pkeyopt ec_paramgen_curve:secp521r1 -pkeyopt ec_param_enc:named_curve
据我所知,该曲线与 ssh-keygen 使用的曲线相同ssh-keygen -t ecdsa -b 521
,并且从文档中我知道 ssh-keygen 现在使用 aes128 来加密私钥。
libressl 私钥的大小为534
, ssh-keygen 私钥的大小为736
。
我的问题是: ssh-keygen 做了什么额外的事情来增加密钥的大小?
另外:两者可以互换吗?其中一个生成的私钥可以转换为另一个吗?
答案1
TLDR:私钥文件有很多不同的格式
这部分取决于您未提供的 OpenSSH 版本。
从历史上看,除了早已过时的协议版本 1(和密钥类型“rsa1”)外,OpenSSH 使用 OpenSSL(其 libcrypto 部分)执行大部分加密操作 - 包括使用SSLeay/OpenSSL 定义的“传统”或“旧式”格式。OpenSSL 还支持“新”的(自 1998 年左右以来!)PKCS8 格式,这些格式(在某种程度上)更安全。因此,OpenSSL 支持 4 种用于“ECDSA”(更确切地说是 X9 风格的 Weierstrass EC,涵盖 X9.62 ECDSA 和 X9.63 ECDH)的 PEM 格式,其中 OpenSSH生成只有 2 个,但(使用 libcrypto)可以读取所有。当ssh-keygen
加密OpenSSL 格式文件,最近的版本确实使用 AES-128-CBC,但这并不总是正确的。
从 2014-01 版 6.5 开始,OpenSSH 添加了自己的“新”文件格式,部分是为了提供比 OpenSSL 传统格式(加密时)更好的安全性,部分是为了支持当时的新算法 Ed25519,而 OpenSSL 当时根本不支持该算法。ssh-keygen
有一个选项-o
可以请求除 ed25519(或 rsa1)以外的任何密钥类型的新格式,您会发现过去几年的许多 Stack 问答都引用并推荐此选项。'新'格式文件默认使用 AES256-CBC 加密,可以用 覆盖-Z ciphername
,但手册页显然没有针对这两种情况进行更新。从 2018-08 的 7.8 版开始,OpenSSH 现在默认所有密钥类型均采用'新'格式,尽管您可以使用 来-m pem
请求除 ed25519 以外的任何格式的 OpenSSL 格式。如果你检查man ssh-keygen
你的系统(除非是 Windows),它应该描述其中一种情况,可能是后者。
(还有 PKCS12 又称 PFX 格式,OpenSSL能用于私钥,但通常仅用于将一个(或多个)私钥与一个或多个 X.509 证书组合在一起,这是不同的情况,不适用于从不使用 X.509 证书的 SSH。其他程序或系统使用其他格式:'商业'/Tectia SSH 有自己的格式,PuTTY 有自己的格式 PPK = PuTTY 私钥。等等,等等,Yul Brynner。所有这些在语义上都是等价的,并且只要有合适的工具就可以相互转换。)
OpenSSH 使用的所有私钥格式都是PEM 风格;二进制数据以 base64 格式编码为文本,标题行和尾行格式如下
-----BEGIN (something)-----
(sometimes some headers here)
(data encoded in base64, broken into lines of 64 characters)
-----END (something)-----
因此,只要查看 dashes-BEGIN 行,即可判断您使用的是哪种格式。请参阅 near-crossdupeshttps://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keys或更简短地https://security.stackexchange.com/questions/129724/how-to-check-if-an-ssh-private-key-has-passphrase-or-not和https://security.stackexchange.com/questions/200935/how-do-i-determine-if-an-existing-ssh-private-key-is-secure(矿)。
差异:ecdsa-p521 密钥的大小为 736 个字符,与 OpenSSH 新格式相匹配未加密- 你是当然你给它设置了密码?——534 与 OpenSSL 1.0.2 创建的 PKCS8 加密格式相匹配,IIRC 是 LibreSSL 分叉时创建的。(OpenSSL 1.1.0 以上版本将 PKCS8 加密更改为使用 PBKDF2 中的 HMAC-SHA256,这会使文件稍微大一些。OpenSSL 1.1.0 以上版本还使 param_enc=named 成为默认值,因此您不再需要指定它。)OpenSSH 新格式比 PKCS8-enc 格式大,主要是因为它存储了公钥值(对于 ECDSA,X9.62 格式的曲线点),原因并不明显两次——一次在为 publickey 指定的文件部分中,并且再次在为私钥指定的部分中。此外,OpenSSH 格式的大部分元数据都是文本字符串,所有长度字段都是 4 个字节,而 PKCS8(与 OpenSSL 传统格式一样)使用 ASN.1,其中可变长度字段大多只有 1 个字节,元数据大多是二进制的,尤其是所用算法的“OID”。)
另外:两者可以互换吗?其中一个生成的私钥可以转换为另一个吗?
是也不是。如前所述,使用 OpenSSL 的 OpenSSH 可以读取(但不能写入)PKCS8,因此ssh-keygen
可以通过对其进行空更改将其转换为 OpenSSH-new,即将密码“更改”为现有值;从 6.5 到 7.7 您必须指定-o
,从 7.8 开始它是默认设置。另一方面,ssh-keygen
可以转换为 OpenSSL-legacy,但不能直接转换为 PKCS8,您需要使用openssl
来执行此操作,要么明确使用pkcs8 -topk8
或在 1.0.0 以上版本中(现在应该是每个人,当然是所有 LibreSSL)只需pkey
。(前者默认为加密,后者默认为未加密,但两者都可以覆盖。)