ECDSA 簽名和“z”值
如果給定兩個相同的“R”值,以下連結包含有關如何反轉 ECDSA 簽名的詳細資訊。
<http://www.nilsschneider.net/2013/01/28/recovering-bitcoin-private-keys.html>
我已閱讀此內容,其中有一部分我不明白;他是如何得到“z”值的。
將“OP_DUP OP_HASH160 70792fb74a5df745bac07df6fe020f871cbb293b OP_EQUALVERIFY OP_CHECKSIG”(減去引號)複製並粘貼到ripemod-160散列函式中是否會產生該結果?
他是否必須複製並粘貼其他一些字元串?他只是成熟的mod還是sha 256d?他必須不止一次這樣做嗎?
我已經閱讀了這些東西,但我只是無法破譯他們關於如何做到這一點的程式描述。非程式描述沒有顯示“嘿,這個 ‘xyzx’ 就是我所說的’要簽名的消息’”或其他任何內容。該頁面和
<https://blockchain.info/tx/9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1>
似乎它們可以充分地描述為“要簽名的消息”,除了我不知道正在應用什麼類型的雜湊甚至將我的計算與第一個連結上顯示的計算進行比較。
對於普通的 Joe 來說,計算 Z 值相當複雜,所以我已經建立了一個網站來為你做這件事。
上述範例的 Z 值可在此頁面上找到。
<https://2xoin.com/tx/9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1>
我還分離了 R 和 S 值,以方便您使用。
您可以在此站點上找到所有比特幣交易的 R、S 和 Z 值。
其他例子,
<https://2xoin.com/tx/9312ccafb8aa624afe7fb7b4201a0ccc2a14ca2b8b8a3253093b975a6a85a280>
<https://2xoin.com/tx/a963c57ba8a384bf708d5cf83c932e9174ebd0f82f3820e25dcc8a3d508aed54>
<https://2xoin.com/tx/19d66411a5aa716a04b37197c11c93c9446a54694a2d2302093d8b0a93ed5d83>
<https://2xoin.com/tx/9778355a53f295a4ffd592af170badda4e9ad3153e15a4afd76655dac387abb2>
該響應返回您在比特幣核心客戶端中找到的標準 JSON 響應,以及我添加的一些額外位,這些位顯示每個交易輸入的 R、S 和 Z 值。
例如,請參閱下面的 SizR、SigS 和 SigZ 節點。
{ "rawtx": "01000000028370ef64eb83519fd14f9d74826059b4ce00eae33b5473629486076c5b3bf215000000008c4930460221009bf436ce1f12979ff47b4671f16b06a71e74269005c19178384e9d267e50bbe9022100c7eabd8cf796a78d8a7032f99105cdcb1ae75cd8b518ed4efe14247fb00c9622014104e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6cffffffffb0385cd9a933545628469aa1b7c151b85cc4a087760a300e855af079eacd25c5000000008b48304502210094b12a2dd0f59b3b4b84e6db0eb4ba4460696a4f3abf5cc6e241bbdb08163b45022007eaf632f320b5d9d58f1e8d186ccebabea93bad4a6a282a3c472393fe756bfb014104e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6cffffffff01404b4c00000000001976a91402d8103ac969fe0b92ba04ca8007e729684031b088ac00000000" } { "txid": "82e5e1689ee396c8416b94c86aed9f4fe793a0fa2fa729df4a8312a287bc2d5e", "version": 1, "locktime": 0, "vin": [ { "txid": "15f23b5b6c0786946273543be3ea00ceb4596082749d4fd19f5183eb64ef7083", "vout": 0, "scriptSig": { "asm": "30460221009bf436ce1f12979ff47b4671f16b06a71e74269005c19178384e9d267e50bbe9022100c7eabd8cf796a78d8a7032f99105cdcb1ae75cd8b518ed4efe14247fb00c9622[ALL] 04e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6c", "hex": "4930460221009bf436ce1f12979ff47b4671f16b06a71e74269005c19178384e9d267e50bbe9022100c7eabd8cf796a78d8a7032f99105cdcb1ae75cd8b518ed4efe14247fb00c9622014104e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6c" }, "sequence": 4294967295, "n": 0, "addr": "1KtjBE8yDxoqNTSyLG2re4qtKK19KpvVLT", "valueSat": 2500000, "value": 0.025, "doubleSpentTxID": null, "sigR": "009bf436ce1f12979ff47b4671f16b06a71e74269005c19178384e9d267e50bbe9", "sigS": "00c7eabd8cf796a78d8a7032f99105cdcb1ae75cd8b518ed4efe14247fb00c9622", "sigZ": "9f4503ab6cae01b9fc124e40de9f3ec3cb7a794129aa3a5c2dfec3809f04c354" }, { "txid": "c525cdea79f05a850e300a7687a0c45cb851c1b7a19a4628565433a9d95c38b0", "vout": 0, "scriptSig": { "asm": "304502210094b12a2dd0f59b3b4b84e6db0eb4ba4460696a4f3abf5cc6e241bbdb08163b45022007eaf632f320b5d9d58f1e8d186ccebabea93bad4a6a282a3c472393fe756bfb[ALL] 04e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6c", "hex": "48304502210094b12a2dd0f59b3b4b84e6db0eb4ba4460696a4f3abf5cc6e241bbdb08163b45022007eaf632f320b5d9d58f1e8d186ccebabea93bad4a6a282a3c472393fe756bfb014104e3896e6cabfa05a332368443877d826efc7ace23019bd5c2bc7497f3711f009e873b1fcc03222f118a6ff696efa9ec9bb3678447aae159491c75468dcc245a6c" }, "sequence": 4294967295, "n": 1, "addr": "1KtjBE8yDxoqNTSyLG2re4qtKK19KpvVLT", "valueSat": 2500000, "value": 0.025, "doubleSpentTxID": null, "sigR": "0094b12a2dd0f59b3b4b84e6db0eb4ba4460696a4f3abf5cc6e241bbdb08163b45", "sigS": "07eaf632f320b5d9d58f1e8d186ccebabea93bad4a6a282a3c472393fe756bfb", "sigZ": "94bbf25ba5b93ba78ee017eff80c986ee4e87804bee5770fae5b486f05608d95" } ], "vout": [ { "value": "0.05000000", "n": 0, "scriptPubKey": { "hex": "76a91402d8103ac969fe0b92ba04ca8007e729684031b088ac", "asm": "OP_DUP OP_HASH160 02d8103ac969fe0b92ba04ca8007e729684031b0 OP_EQUALVERIFY OP_CHECKSIG", "addresses": [ "1G3BjSLWsWH6tbPYs29fYMYaz9k8EStQM" ], "type": "pubkeyhash" }, "spentTxId": "9778355a53f295a4ffd592af170badda4e9ad3153e15a4afd76655dac387abb2", "spentIndex": 0, "spentHeight": 175915 } ], "blockhash": "00000000000006467ae1708979d38dcb6d6fcafbab4c6eccf7414da950379243", "blockheight": 175915, "confirmations": 309447, "time": 1334602008, "blocktime": 1334602008, "valueOut": 0.05, "size": 405, "valueIn": 0.05, "fees": 0 }
當我研究這個執行緒上的所有資訊時,我創建了一些我在實驗時大量使用的小輔助方程。
K = ((Z + (X * R)) / S) % N
X = (((S * K) - Z) / R) % N
Z = ((S * K) - (X * R)) % N
S = ((Z + (X * R)) / K) % N
R = (((S * K) - Z) / X) % N
在我上面的方程式中,
X 是私鑰十六進制,
K 乘以 sep256k1 G 值產生一個 ECPoint,其 x 值 = R
所以從R中,你可以驗證你有正確的K值,如果你有正確的K值,那麼你就可以得到正確的X值,也就是交易輸入中地址的私鑰的十六進制。
這是一些範例 C# 程式碼。
使用系統; 使用 System.Linq; 使用 Org.BouncyCastle.Math; 命名空間 SeansECDSAtest { 課堂節目 { 靜態無效主要(字元串 [] 參數) { BigInteger R = new BigInteger(StringToByteArray("00d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1")); BigInteger S = new BigInteger(StringToByteArray("0044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e")); BigInteger Z = new BigInteger(StringToByteArray("00c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e")); BigInteger X = new BigInteger(StringToByteArray("00c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96")); BigInteger K = new BigInteger(StringToByteArray("007a1a7e52797fc8caaa435d2a4dace39158504bf204fbe19f14dbb427faee50ae")); BigInteger N = new BigInteger(StringToByteArray("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")); //證明 R = (((S * K) - Z) / X) % N var verifyR = S.Multiply (K) .Subtract (Z) .Multiply (X.ModInverse (N)). Mod (N); Console.WriteLine("R = " + string.Concat(verifyR.ToByteArrayUnsigned().Select(b => b.ToString("X2")))); //證明 S = ((Z + (X * R)) / K) % N var verifyS = Z.Add (X.Multiply (R)). Multiply (K.ModInverse (N)). Mod (N); Console.WriteLine("S = " + string.Concat(verifyS.ToByteArrayUnsigned().Select(b => b.ToString("X2")))); //證明 Z = ((S * K) - (X * R)) % N var verifyZ = S.Multiply(K).Subtract(X.Multiply(R)).Mod(N); Console.WriteLine("Z = " + string.Concat(verifyZ.ToByteArrayUnsigned().Select(b => b.ToString("X2")))); //證明 X = (((S * K) - Z) / R) % N var verifyX = S.Multiply (K) .Subtract (Z) .Multiply (R.ModInverse (N)). Mod (N); Console.WriteLine("X = " + string.Concat(verifyX.ToByteArrayUnsigned().Select(b => b.ToString("X2")))); //證明 K = ((Z + (X * R)) / S) % N var verifyK = Z.Add (X.Multiply (R)). Multiply (S.ModInverse (N)). Mod (N); Console.WriteLine("K = " + string.Concat(verifyK.ToByteArrayUnsigned().Select(b => b.ToString("X2")))); Console.ReadLine(); } 公共靜態字節[] StringToByteArray(字元串十六進制) { 返回 Enumerable.Range(0, hex.Length) .哪裡(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); } } }
和python中的相同程式碼
def extended_gcd(aa, bb): lastremainder, remainder = abs(aa), abs(bb) x, lastx, y, lasty = 0, 1, 1, 0 while remainder: lastremainder, (quotient, remainder) = remainder, divmod(lastremainder, remainder) x, lastx = lastx - quotient*x, x y, lasty = lasty - quotient*y, y return lastremainder, lastx * (-1 if aa < 0 else 1), lasty * (-1 if bb < 0 else 1) def modinv(a, m): g, x, y = extended_gcd(a, m) if g != 1: raise ValueError return x % m R = 0x00d47ce4c025c35ec440bc81d99834a624875161a26bf56ef7fdc0f5d52f843ad1 S = 0x0044e1ff2dfd8102cf7a47c21d5c9fd5701610d04953c6836596b4fe9dd2f53e3e Z = 0x00c0e2d0a89a348de88fda08211c70d1d7e52ccef2eb9459911bf977d587784c6e X = 0x00c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96 K = 0x007a1a7e52797fc8caaa435d2a4dace39158504bf204fbe19f14dbb427faee50ae N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 #proving R = (((S * K) - Z) / X) % N print hex((((S * K) - Z) * modinv(X,N)) % N) #proving S = ((Z + (X * R)) / K) % N print hex(((Z + (X * R)) * modinv(K,N)) % N) #proving Z = ((S * K) - (X * R)) % N print hex(((S * K) - (X * R)) % N) #proving X = (((S * K) - Z) / R) % N print hex((((S * K) - Z) * modinv(R,N)) % N) #proving K = ((Z + (X * R)) / S) % N print hex(((Z + (X * R)) * modinv(S,N)) % N)