如何将ECDSA密钥转换为PEM格式 [英] How to convert an ECDSA key to PEM format
问题描述
我有一个 myetherwallet 的私有原始密钥,并带有一个 passphrase "testwallet",现在我正按照此答案尝试使用OpenSSL将其转换为PEM格式. /p>
echo "a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57" | xxd -r -p - | openssl ec -inform der -pubin -noout -passin pass:testwallet -text
但是出现此错误:
read EC key
unable to load Key
140084694296480:error:0D06B08E:asn1 encoding routines:ASN1_D2I_READ_BIO:not enough data:a_d2i_fp.c:247:
更新: 我没有公钥,相反,我想生成它,因此以后我还可以生成对应的以太坊地址..
您声称您的原始密钥采用OpenSSL的DER格式,并非如此.另外,您还声称私有密钥不是公共密钥,而是声称它是用密码加密的,无论哪种方式都是错误的:公共密钥从不加密,私有密钥在OpenSSL的传统"(也称为旧版")算法中无法加密DER格式(对于ECC,由 SECG SEC1 定义). (虽然PEM更加方便,但可以使用DER或PEM对PKCS8格式的OTOH私钥进行密码加密.并且FWIW PKCS12格式始终对密码进行加密,并且始终对DER.)
ECC(ECDSA,ECDH,ECMQV等)键始终相对于某些曲线"(更确切地说,是具有已标识的生成器即基点的曲线的素数子组).对于比特币,这是 secp256k1 ,但是您的问题并不只限于比特币,而这个答案可能需要使用其他曲线的其他应用程序进行修改.
如果您还具有公共密钥(作为未压缩的点),则可以简单地使用 k06a的答案
中正确显示-
我的中间字符串的第一部分(或我的仅供私人使用的选项的整个后缀)
a00706052b8104000a
是上下文标记,长度为a007
,是OID标记,长度为0605
,其中包含2b8104000a
这是 1.3.132.0.10,即secp256k1 和 -
我的中间字符串
a144034200
的其余部分是上下文标记和长度,其中包含标记长度和BITSTRING的未使用位头,BITSTRING是未压缩的原始公钥.
要改为使用 secp256r1 aka P-256或prime256v1,则需要将AlgId.OID更改为 But this error appears: UPDATE:
I don't have the public key, instead I want to generate it so later I can also generate the Ethereum address corresponds.. You are claiming your raw key is in OpenSSL's DER format, which it isn't. Also you are claming a private key is a public key, which it isn't, and claiming it's password-encrypted which is wrong either way: public keys are never encrypted and private keys in OpenSSL's 'traditional' aka 'legacy' algorithm-specific DER formats (for ECC, defined by SECG SEC1) cannot be encrypted. (OTOH private keys in PKCS8 format can be password-encrypted in either DER or PEM, although PEM is more convenient. And FWIW PKCS12 format is always password-encrypted, and always DER.) An ECC (ECDSA, ECDH, ECMQV, etc) key is always relative to some 'curve' (more exactly, prime-order subgroup over a curve with an identified generator aka base point). For bitcoin this is secp256k1, but your question doesn't say it's limited to bitcoin and this answer would require modification for other applications using other curves. If you also have the public key (as an uncompressed point), you can simply use the solution from https://bitcoin.stackexchange.com/questions/66594/signing-transaction-with-ssl-private-key-to-pem . Concatenate the hex strings: and then either convert the hex to binary and read as DER, or convert the hex (probably via binary) to base64 and wrap with If you don't have the public key, you can modify this slightly. Concatenate the hex strings and convert to binary, then read into ADDED: since you seem not to comprehend the words in the answer, I'll lay this out in as much detail as I can. The value To construct the OpenSSL/SECG representation of a private key with no public key, put the hex string representing the private key -- all of it, without modification -- between the two other hex strings I showed as the second option: Then convert this combined hex string to binary, and read the result into The result is PEM format -- but PEM format not including the public key, which you indicate you want. To see the fields including the derived public key, add Now if you want a PEM-format key including the public key, take both the hex strings for the private key (all 64 digits) AND the newly-shown hex value for the public key, and plug them in to my first option. Also note an ECC public key is a curve point which can be in two forms, compressed or uncompressed; the form generated here is uncompressed. If you need compressed, I'll add that later. A secp256k1 point in uncompressed form is 65 bytes, represented in hex as 130 hex digits. (Which
ADDED 2019-02 for DavidS: as correctly shown in k06a's answer the first part of my midstring (or the entire suffix for my private-only option) the remainder of my midstring To do secp256r1 aka P-256 or prime256v1 instead, you need to change the AlgId.OID to 1.2.840.10045.3.1.7 which is encoded as
这篇关于如何将ECDSA密钥转换为PEM格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!echo "a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57" | xxd -r -p - | openssl ec -inform der -pubin -noout -passin pass:testwallet -text
read EC key
unable to load Key
140084694296480:error:0D06B08E:asn1 encoding routines:ASN1_D2I_READ_BIO:not enough data:a_d2i_fp.c:247:
a pre_string : 30740201010420
the privkey : (32 bytes as 64 hexits)
a mid_string : a00706052b8104000aa144034200 (identifies secp256k1)
the pubkey : (65 bytes as 130 hexits)
-----BEGIN/END EC PRIVATE KEY-----
lines to make it PEM.302e0201010420 privkey_32bytes_64hexits a00706052b8104000a
openssl ec -inform d
. Note OpenSSL will derive the public key from the private key given the curve, but not actually store it in the PEM output, so reading with software other than OpenSSL is not guaranteed. You might need to use openssl ec -text [-noout]
(on either PEM or DER input as convenient) to get the public key value, then go back and create the fuller encoding that includes the public key as above.
a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57
is the raw private key represented in hex. A secp256k1 private value is 32 bytes in binary; when binary is represented in hex each byte takes two hex digits, so 32 bytes takes 64 hex digits. All of this value is the raw private key. There is no part consisting of 25 digits OR 25 bytes that has any useful meaning whatever. Do not take any 25-anything part of this value. 302e0201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000a
openssl ec -inform d
:$ echo 302e0201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000a | xxd -r -p >48101258.1
$ openssl ec -inform d <48101258.1
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MC4CAQEEIKFAvVB6VzYOL6UDKYwDWFTw3LJIvtq756FNs5IKqs9XoAcGBSuBBAAK
-----END EC PRIVATE KEY-----
-text
; to see only the fields and not the PEM output, add -noout
:$ openssl ec -inform d <48101258.1 -text -noout
read EC key
Private-Key: (256 bit)
priv:
a1:40:bd:50:7a:57:36:0e:2f:a5:03:29:8c:03:58:
54:f0:dc:b2:48:be:da:bb:e7:a1:4d:b3:92:0a:aa:
cf:57
pub:
04:20:ea:6d:8c:e7:bc:bb:48:33:69:b2:91:1c:75:
e5:60:2a:34:28:be:44:96:e9:7f:14:ad:52:fd:4a:
6a:a0:e3:60:83:9c:6e:db:32:2a:22:55:7c:70:1e:
d0:fa:1e:06:cf:57:4f:be:17:bd:6a:85:51:69:c5:
65:96:72:cf:a9
ASN1 OID: secp256k1
openssl ec
formats as 4 lines each of 15 bytes with 5 bytes left over.)$ echo 30740201010420 a140bd507a57360e2fa503298c035854f0dcb248bedabbe7a14db3920aaacf57 a00706052b8104000aa144034200 \
> 04:20:ea:6d:8c:e7:bc:bb:48:33:69:b2:91:1c:75: e5:60:2a:34:28:be:44:96:e9:7f:14:ad:52:fd:4a: \
> 6a:a0:e3:60:83:9c:6e:db:32:2a:22:55:7c:70:1e: d0:fa:1e:06:cf:57:4f:be:17:bd:6a:85:51:69:c5: \
> 65:96:72:cf:a9 | xxd -r -p >48101258.2
$ # note xxd -r -p ignores the colons; other hex programs may need them removed instead
$ openssl ec -inform d <48101258.2
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIKFAvVB6VzYOL6UDKYwDWFTw3LJIvtq756FNs5IKqs9XoAcGBSuBBAAK
oUQDQgAEIOptjOe8u0gzabKRHHXlYCo0KL5Elul/FK1S/UpqoONgg5xu2zIqIlV8
cB7Q+h4Gz1dPvhe9aoVRacVllnLPqQ==
-----END EC PRIVATE KEY-----
a00706052b8104000a
is a context-tag and length a007
for an OID tag and length 0605
containing 2b8104000a
which is 1.3.132.0.10 which is secp256k1 and a144034200
is a context tag and length containing the tag length and unused-bits header for a BITSTRING which is the raw publickey as an uncompressed point.a00a 0608 2a8648ce3d030107
. The privatekey and publickey values for p256r1 are the same sizes as for p256k1, but the AlgId is longer, so you also need to change the length of the outer SEQUENCE giving30770201010420 privatekey32bytes # note 77
a00a06082a8648ce3d030107 a144034200 publicpoint65bytes