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

OpenSSL Elliptic Curve reading private key in DER form

我有一个 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

如果我然后尝试使用

读取私钥
openssl ec -in private.der -inform der 

我收到错误:

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:

如果我尝试:

openssl pkcs8 -in private.der -inform der

然后我得到这些错误:

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

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

openssl pkcs8 -in "params.pem" -inform pem -topk8 -nocrypt -out "private.pem" -outform pem

那么我读起来没问题:

openssl ec -in private.pem -inform pem

man page for openssl ec 阐明了您所观察到的行为。它提到

OpenSSL uses the private key format specified in 'SEC 1: Elliptic Curve Cryptography' (http://www.secg.org/). To convert an OpenSSL EC private key into the PKCS#8 private key format use the pkcs8 command.

您已使用命令生成 PKCS#8 格式的密钥,但随后尝试使用 openssl ec 工具将它们读取为另一种 (SEC 1) 格式。预计会失败。你应该使用 the openssl pkey command 代替:

$ 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-----

但是,openssl ec 显然成功读取了 PEM 编码的 PKCS#8 密钥,正如您在 下提到的,那么我可以使用... 读取它。 question/surprise 与其说是:“为什么 openssl ec 不能像 DER 一样读取私钥?”,而是:“为什么 openssl ec 能像 PEM 一样读取私钥?” `. 答案在同一个手册页中:

The PEM form is the default format: it consists of the DER format base64 encoded with additional header and footer lines. In the case of a private key PKCS#8 format is also accepted.


如果你想深入挖掘,你可以按照源代码,从apps/ec.c. It shows the use of d2i_ECPrivateKey_bio() to read the key in the case of DER and PEM_read_bio_ECPrivateKey() in the case of PEM. The former is a simple deserialization function. The latter contains more intelligence though, as explained in the manual开始说:

The read functions transparently handle traditional and PKCS#8 format encrypted and unencrypted keys.

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