Elliptic Curve Private Key Format:
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
所以publicKey 是OPTIONAL 理论上可以忽略。
这是我的 DER secp256k1 私钥的示例:
30740201 01042092 E768CB72 0DC16924 27D156DB 39630748 0D1507B9 A4958450
2574B9A0 922F4BA0 0706052B 8104000A A1440342 00041954 9737B704 D1789A57
82E3430E 8259F904 71326081 054854D2 A5D096F9 686D05B0 30D98BA3 C60C056E
204CEF61 C0AC5B53 A9A6B9A0 5AFF9DA2 6CA4B65B 2E84
试图分解:
$ openssl asn1parse -inform DER -in <(echo "30740201 01042092 E768CB72 0DC16924 27D156DB 39630748 0D1507B9 A4958450 2574B9A0 922F4BA0 0706052B 8104000A A1440342 00041954 9737B704 D1789A57 82E3430E 8259F904 71326081 054854D2 A5D096F9 686D05B0 30D98BA3 C60C056E 204CEF61 C0AC5B53 A9A6B9A0 5AFF9DA2 6CA4B65B 2E84" | xxd -r -p)
ASN.1解析结果:
0:d=0 hl=2 l= 116 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
5:d=1 hl=2 l= 32 prim: OCTET STRING [HEX DUMP]:92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B
39:d=1 hl=2 l= 7 cons: cont [ 0 ]
41:d=2 hl=2 l= 5 prim: OBJECT :secp256k1
48:d=1 hl=2 l= 68 cons: cont [ 1 ]
50:d=2 hl=2 l= 66 prim: BIT STRING
详细(见https://bitcoin.stackexchange.com/a/66622/22979):
30 - ASN.1
74 - Length of all following bytes (116 bytes)
02 - Type (integer)
01 - Length of integer (1 byte)
01 - Value of integer (1)
04 - Type (octet string)
20 - Length of string (32 bytes)
92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B - Private Key
A0 - Tag 0
07 - Length of tag (7 bytes)
06 - Type (Object ID)
05 - Length of the Object ID (5 bytes)
2b 81 04 00 0a - The object ID of the curve secp256k1
A1 - Tag 1
44 - Length of tag (68 bytes)
03 - Type – Bit string
42 - Length of the bit string (66 bytes)
00 - ???
04 - Uncompressed Public Key
19549737B704D1789A5782E3430E8259F90471326081054854D2A5D096F9686D - Public Key X coord
05B030D98BA3C60C056E204CEF61C0AC5B53A9A6B9A05AFF9DA26CA4B65B2E84 - Public Key Y coord
我删除了公钥对象并将 ASN.1 长度从 116 字节 (0x74) 固定为 46 字节 (0x2e):
$ openssl asn1parse -inform DER -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)
得到结果:
0:d=0 hl=2 l= 46 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :01
5:d=1 hl=2 l= 32 prim: OCTET STRING [HEX DUMP]:92E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4B
39:d=1 hl=2 l= 7 cons: cont [ 0 ]
41:d=2 hl=2 l= 5 prim: OBJECT :secp256k1
尝试获取公钥:
$ openssl ec -inform DER -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)
结果:
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MC4CAQEEIJLnaMtyDcFpJCfRVts5YwdIDRUHuaSVhFAldLmgki9LoAcGBSuBBAAK
-----END EC PRIVATE KEY-----
再试一次:
$ openssl ec -inform DER -text -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)
结果:
read EC key
Segmentation fault: 11
我使用的是 OSX 系统 openssl - 看起来是 LibreSSL 2.2.7。
添加: 向 LibreSSL 报告了一个错误:https://github.com/libressl-portable/portable/issues/395
更新:在最新的 macOS 10.15.1 中预装的 openssl (LibreSSL 2.8.3) 已修复此错误。
然后我安装了最新的openssl:brew install openssl
/usr/local/Cellar/openssl/1.0.2n/bin/openssl ec -inform DER -text -noout -in <(echo "302E020101042092E768CB720DC1692427D156DB396307480D1507B9A49584502574B9A0922F4BA00706052B8104000A" | xxd -r -p)
得到:
read EC key
Private-Key: (256 bit)
priv:
00:92:e7:68:cb:72:0d:c1:69:24:27:d1:56:db:39:
63:07:48:0d:15:07:b9:a4:95:84:50:25:74:b9:a0:
92:2f:4b
pub:
04:19:54:97:37:b7:04:d1:78:9a:57:82:e3:43:0e:
82:59:f9:04:71:32:60:81:05:48:54:d2:a5:d0:96:
f9:68:6d:05:b0:30:d9:8b:a3:c6:0c:05:6e:20:4c:
ef:61:c0:ac:5b:53:a9:a6:b9:a0:5a:ff:9d:a2:6c:
a4:b6:5b:2e:84
ASN1 OID: secp256k1
最终解决方案:
$ /usr/local/Cellar/openssl/1.0.2n/bin/openssl ec -inform DER -text -noout -in <(cat <(echo -n "302e0201010420") <(echo -n "***") <(echo -n "a00706052b8104000a") | xxd -r -p) 2>/dev/null | tail -6 | head -5 | sed 's/[ :]//g' | tr -d '\n' && echo
用十六进制私钥替换***。