Segregated-Witness

BIP143 中的範例簽名無效?

  • June 18, 2021

BIP143中,第一個範例有見證簽名,但它似乎無法驗證/正確?!我寫了一個超級簡單的python程序來展示

import ecdsa
import asn1

#Importing the 3 pieces of data from the example to byte arrays
pub = bytearray.fromhex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357")
sighash = bytearray.fromhex("c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670")
dersigscript = bytearray.fromhex("304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee")

#deocding the DEC encoding
decoder = asn1.Decoder()
decoder.start(bytes(dersigscript))
tag, sigscript = decoder.read()

#stripping off the script  potion so we just have a signature
sig = bytearray(sigscript)[2:66]

vk = ecdsa.VerifyingKey.from_string(pub,  curve=ecdsa.SECP256k1)
vk.verify(sig, sighash)

如果有人可以闡明我在做什麼愚蠢的事情,或者可以將其分解的範例參考,那麼它會起作用,那將非常有幫助。我還嘗試在 3 個輸入的所有 8 個組合上反轉字節順序。話雖如此,我已經使用發布的私鑰和公鑰來進行我自己的簽名/驗證,所以我相當有信心它們的順序是正確的,只是對簽名不太確定。

謝謝!!

—-編輯—–

只是想列出為了完整性而嘗試過的其他事情

  1. 正如 pieter 指出的那樣,我錯誤地解碼了私鑰。S 和 R 分為 2 個不同的變數
304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d467eed
變成
3044 02 20 **3609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a** 02 20 **573a954c4518331561406f90300e8f3358f51928d4632cbeee1**
所以原始的 64 字節 sig 是 609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a573a954c4518331561406f90300e8f3358f51928d467c212a8caedebee02
不幸的是,這仍然沒有用

另外我嘗試使用pythons native der style ecdsa,但仍然沒有成功
從 ecdsa.util 導入 sigencode_der, sigdecode_der
vk.verify(字節(sig),字節(sighash),sigdecode = sigdecode_der)
和
vk.verify(字節(sig),字節(sighash),hashlib.sha256,sigdecode=sigdecode_der)
其中 sig 以 0x30 開頭:
3044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f6467e3622ad4010fe9dc6870540b6

有趣的是,python 庫除了簽名錯誤之外沒有給我任何錯誤。所以我似乎找不到任何關於如何使用標準庫來做到這一點的線索。如果我弄清楚了,我會發布答案

使用這個庫:

from cryptotools import Signature, PublicKey, hex_to_bytes

pub = PublicKey.from_hex('025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357')
sig = Signature.from_hex('304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee')
sighash = hex_to_bytes('c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670')

>>> sig.verify_hash(sighash, pub)
True

好的,多虧了 PieterWuille,我(我們)能夠弄清楚為什麼我的程式碼無法正常工作以及如何使用標準的 python 或 openssl 庫。

這些是以下問題

  1. python 庫的 DER 解碼使用不正確。我們需要遍歷所有變數並分別提取簽名的兩個部分(r 和 s)並重新組合它們。
  2. 因為標準簽名庫在簽名/驗證中內置了雜湊,而比特幣使用雙重雜湊,要使其與標準庫一起使用,您需要手動雜湊 1 次,然後將其提供給庫以執行第二次雜湊。這意味著我們不能使用 sigHash 作為輸入,而必須使用雜湊 preImage。下面發布的是關於最短的 Python 腳本,展示如何使用原始格式和 DER 編碼格式給出的範例驗證簽名:
進口ecdsa
導入 asn1
導入雜湊庫
#用於der版本
從 ecdsa.util 導入 sigencode_der, sigdecode_der

#將範例中的3條數據導入字節數組
pub = bytearray.fromhex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357")
DerEncodedSig = bytearray.fromhex "
prehashimage = bytearray.fromhex(“0100000096b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd3752b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3bef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a010000001976a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac0046c32300000000ffffffff863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e51100000001000000”)

#deocding DEC 編碼
解碼器 = asn1.Decoder()
解碼器.start(字節(DerEncodedSig))
標籤,sigder = 解碼器.read()

sig1 = sigder [2:34]
sig2 = sigder [36:68]
信號 = 信號 1 + 信號 2

#現在我們需要獲取原像的單個sha256雜湊
m = hashlib.sha256()
m.update (prehashimage)
singlesighash = m.digest()

#我們不會使用雙雜湊進行驗證,但這表明它與 bip143 中的 sigHash 相同
n = hashlib.sha256()
n.update(singlesighash)
sigHash = n.digest

vk = ecdsa.VerifyingKey.from_string(字節(pub),曲線=ecdsa.SECP256k1)
#我們必須提供雜湊庫,因為預設不是sha256
結果 = vk.verify(字節(sig),字節(singlesighash),hashlib.sha256)
列印(結果)
#這是der原生方式,不需要我們對簽名進行der解碼,但兼容openssl
結果 = vk.verify(bytes(DerEncodedSig), bytes(singlesighash), hashlib.sha256, sigdecode=sigdecode_der)
列印(結果)

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