OpenSSL 椭圆曲线读取 DER 形式的私钥

Rob*_*ahl 2 openssl

我有一个 DER 形式的 EC 私钥,我想将其转换为 PEM 形式。但我看不懂 DER 表格。

私钥生成如下:

openssl ecparam -param_enc named_curve -check -name "-secp384r1" -genkey -noout -out "params.pem" -outform pem
openssl pkcs8 -in "params.pem" -inform pem -topk8 -nocrypt -out "private.der" -outform der
Run Code Online (Sandbox Code Playgroud)

如果我然后尝试读取私钥

openssl ec -in private.der -inform der 
Run Code Online (Sandbox Code Playgroud)

我收到错误:

read EC key
unable to load Key
4674530924:error:0DFFF0A8:asn1 encoding routines:CRYPTO_internal:wrong tag:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:1144:
4674530924:error:0DFFF03A:asn1 encoding routines:CRYPTO_internal:nested asn1 error:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:717:
4674530924:error:0DFFF03A:asn1 encoding routines:CRYPTO_internal:nested asn1 error:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:646:Field=privateKey, Type=EC_PRIVATEKEY
4674530924:error:10FFF010:elliptic curve routines:CRYPTO_internal:EC lib:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/ec/ec_asn1.c:1353:
Run Code Online (Sandbox Code Playgroud)

如果我尝试:

openssl pkcs8 -in private.der -inform der
Run Code Online (Sandbox Code Playgroud)

然后我得到这些错误:

Error reading key
4460752492:error:0DFFF0A8:asn1 encoding routines:CRYPTO_internal:wrong tag:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:1144:
4460752492:error:0DFFF03A:asn1 encoding routines:CRYPTO_internal:nested asn1 error:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:317:Type=X509_ALGOR
4460752492:error:0DFFF03A:asn1 encoding routines:CRYPTO_internal:nested asn1 error:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/crypto/asn1/tasn_dec.c:646:Field=algor, Type=X509_SIG
Run Code Online (Sandbox Code Playgroud)

请注意,如果我直接生成 PEM 格式:

openssl pkcs8 -in "params.pem" -inform pem -topk8 -nocrypt -out "private.pem" -outform pem
Run Code Online (Sandbox Code Playgroud)

那么我阅读它就没有问题了:

openssl ec -in private.pem -inform pem
Run Code Online (Sandbox Code Playgroud)

Rei*_*eek 6

手册页openssl ec阐明了您所观察到的行为。它提到

OpenSSL 使用“SEC 1:椭圆曲线加密”( http://www.secg.org/ )中指定的私钥格式。要将 OpenSSL EC 私钥转换为 PKCS#8 私钥格式,请使用 pkcs8 命令。

您已使用命令生成 PKCS#8 格式的密钥,但随后尝试使用该openssl ec工具以其他 (SEC 1) 格式读取它们。预计这会失败。您应该使用以下命令openssl pkey代替:

$ openssl pkey -inform DER -in private.der 
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCY6UCzQ6eDGo83UyWc
rCQw4caWF9Ttz/crt0/ba1AwQbJqSIHZIP+7f9HZdSY/VsOhZANiAATYTEaeRFGN
R6/LlKtEDzPHqIK6xr4Qp4Iz+t/ZXLccL3gdedDmtuSUbPiwj8/QI+gpW9MslkYf
c/Rm6OQpn4P1IagR98B+qSNW47olBlzzLP/k/Zqz71x9mgyQrBhYZWw=
-----END PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

但是,openssl ec显然成功读取了 PEM 编码的 PKCS#8 密钥,正如您在“然后我用...读取它没有问题”下提到的那样。问题/惊喜并不是:“为什么openssl ec无法将私钥读取为 DER?”,而是:“为什么能够openssl ec将私钥读取为 PEM?”。答案位于同一手册页中:

PEM 形式是默认格式:它由采用附加页眉和页脚行编码的 DER 格式 base64 组成。如果是私钥,则还接受 PKCS#8 格式。


如果您想深入挖掘,可以从apps/ec.c. 它显示了在 DER 和PEM 情况下如何使用 来d2i_ECPrivateKey_bio()读取密钥。PEM_read_bio_ECPrivateKey()前者是一个简单的反序列化函数。后者包含更多的智能,正如手册中所解释的那样:

读取函数透明地处理传统和 PKCS#8 格式的加密和未加密密钥。

这里的“传统”是指前面提到的 SEC 1 格式。