Transactions

使用 Openssl 簽署交易遺產

  • February 17, 2020

我想了解比特幣如何使用 Openssl 簽署交易。我看到了這篇文章,但我有一些問題。

在我的私鑰和公鑰之上。

私鑰:

$ cat chiave_priv_3.pem 

   -----BEGIN EC PARAMETERS-----
   BgUrgQQACg==
   -----END EC PARAMETERS-----
   -----BEGIN EC PRIVATE KEY-----
   MHQCAQEEIOLcjvH4RhZFl1hthXl7DD3MHXUCWKiI2b/zoYlvBmKboAcGBSuBBAAK
   oUQDQgAE3Qc0PacS/HmhnZjIot48dZ++rvh121Rq+xjreFKrf/QCl2sDXTncDbe0
   wcCtq4yaUpdbmzV9OgrP94EFsEC/1w==
   -----END EC PRIVATE KEY-----

公鑰壓縮

$ cat chiave_pubblica_compressa_3.txt 
03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4

我正在做 regtest,我的 UTXO 是:

{
   "txid": "0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d",
   "vout": 0,
   "address": "myiGTzGG8rJikr2HcVyPYqprh6Ds1kdY7v",
   "label": "",
   "scriptPubKey": "76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac",
   "amount": 49.99900000,
   "confirmations": 6,
   "spendable": true,
   "solvable": true,
   "desc": "pkh([c7960220]03dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4)#5c03vyak",
   "safe": true
 },

我可以使用以下參數創建交易數據:

TXID=0c647aadcb4028260ecb753c727e0237658873a0cbdbeb5695b8cb85ea87f98d
VOUT=0
AMOUNT=49.998
ADDR_MITT=msPjuNgbmbRSkNGJPvquKJRRmrbzS96s62

bitcoin-cli createrawtransaction '[{"txid":"'$TXID'","vout":'$VOUT'}]' '[{"'$ADDR_MITT'":'$AMOUNT'}]'

02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c0000000000ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000

現在我得到 scriptPubKey 並放入 ScriptSig 並在 little endian 中添加 SIGHASH。

02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000

在哪裡

02000000 
01
8df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c
00000000
19 76a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588ac
ffffffff
01
c0e4022a01000000
19 76a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac
00000000
01000000

Sha256 兩次

$ printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | awk '{ print $1 }' > a.txt
daac47088b7eba5593282013442dbcba59556d095982d470f0a02972269bc0e1 

使用 chiave_priv_3.pem 簽名

$ openssl dgst -sha256 -hex -sign chiave_priv_3.pem a.txt | sed 's/^.* //'                                                           
304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e

在簽名末尾添加01並檢查長度

printf 304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e01 | wc -c
142

142 char is 47

調試 DER 簽名

30 DER prefix
44 Length of rest of Signature
02 Marker for r value
20 Length of r value
r = 7071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c2
02 Marker for s value
20 Length of s value
s = 308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e
01 SIGHASH_ALL

與壓縮的公鑰連接

47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4

整個 scriptSig 長度是:6A (212 char hex) 現在我可以建立我的交易:

02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000

發送交易

bitcoin-cli sendrawtransaction 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000006A47304402207071c9fd7341a15cacfea72e215b44bed42d1a00c7fc5bfed5e01d36acd953c20220308e45aedd080ba65993b69b4c82cc928db8c3e70a6f402fe0258157a4690c6e012103dd07343da712fc79a19d98c8a2de3c759fbeaef875db546afb18eb7852ab7ff4ffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac00000000
error code: -26
error message:
mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation) (code 16)`

問題是您正在執行所有散列(並將其放入十六進制),然後讓 OpenSSL 再次對其進行散列。openssl dgst將在簽名之前對消息進行雜湊處理,但這對於比特幣是不正確的。傳統上,在 ECDSA 中,消息被雜湊一次然後簽名。但是對於比特幣,它實際上被雜湊了兩次。另一種思考方式是消息是散列。

所以你已經對交易進行了雙重雜湊處理。但是 OpenSSL 會再次對其進行雜湊處理,使其經過三次雜湊處理,這意味著您簽署了不同的消息。此外,OpenSSL 會將您的消息作為二進制數據讀取,而不是解釋您提供的十六進制數據。所以真的你的散列命令應該是

printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p > a.txt

這將對 sighash 消息進行一次雜湊處理,並將二進制數據放入 a.txt。

然後你就可以像以前那樣簽名了。


或者,OpenSSL 有一個pkeyutl工具,它不對要簽名的數據進行任何額外的雜湊處理,而是希望您已經對其進行了雜湊處理。你可以改用它,但你仍然需要你的雜湊是二進製而不是十六進制。所以你可以做

printf 02000000018df987ea85cbb89556ebdbcba073886537027e723c75cb0e262840cbad7a640c000000001976a914c79602205abbe1d35ee6dcb4a19791cbd5a26e1588acffffffff01c0e4022a010000001976a914824441111b374bec1952a5b3fa9dd4e3ed679b3888ac0000000001000000 | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | xxd -r -p > a.txt

獲得雙重雜湊。然後做

openssl pkeyutl -inkey chiave_priv_3.pem a.txt -sign -in a.txt -pkeyopt digest:sha256 | xxd -p -c 256

簽署。

引用自:https://bitcoin.stackexchange.com/questions/93342