Signature
如何確定簽名(消息簽名)的第一個字節(恢復 ID)?
我確實意識到,在比特幣中,當我們返回對消息進行簽名的簽名結果時,第一個字節包含用於恢復使用如下公式進行驗證所需的公鑰的資訊:
27 + (4 if comp. 0 if not) + (0<=num<=3)
我正在努力解決的是我們如何確定這個
num
數字?根據SEC:1的第 4.1.6 節恢復公鑰:
x = r + jn
Q
根據R
是否無效移動到下一個計算- 計算
Q
依據-R
由於 j(secp256k1 的輔因子)是 0 和 1,並且 R 有兩個值。所以應該有 4 個可能的公鑰。
num
在達到正確的公鑰之前我們拒絕的公鑰數量是多少?因為這是我根據我在使用 Electrum 生成的簽名和我自己使用 SEC1 完成的公鑰恢復之間所做的比較得出的唯一解釋。額外問題:為什麼選擇 27?
FWIW這就是我發現的關於這個問題的內容。基本上有兩種方法可以找到庫稱為“recid”或恢復 ID。他們中的大多數人使用第一種方法,但還有另一種方法:
方法一:
- 僅需要
r
,s
因此只要您有簽名和已簽名的“消息”,任何人都可以執行。- 它慢得多,因為它有 3 個標量乘法,並且基於所使用的橢圓曲線的輔因子,整個操作可能會重複 2*(h+1) 次,對於具有 secp256k1 曲線的比特幣來說,最多 4 次(99%時間是 1 或 2 次)。
這些步驟在SEC:1的 4.1.6 節中進行了說明,這裡不再贅述。
要找到
recid
您使用給定的公鑰或其雜湊檢查計算的公鑰,並將被拒絕的公鑰的數量報告為recid
. 例如 ifx=r+(0*order)
andQ
was used thenrecid=0
和 if-Q
was used thenrecid=1
等等。方法二:
- 它需要完整的
r
,因此只能在簽名時完成(需要擁有私鑰)。R=(xR, yR)
- 它要快得多,因為沒有額外的計算。它只需要快速的值檢查。
- 這通常
v
在庫中被稱為
byte v = if(R.X > curve.N) then 2 else 0) | (if R.Y.IsEven then 0 else 1);
基本上檢查是否大於曲線階數(N)以及是偶數還是奇數。不應該忘記的事情是“翻轉”,它是基於簽名中使用的以及是否用於
xR``yR``s``s``-s
if s > curve.N/2 then v^=1 else do nothing
** 請注意,最後您需要計算以下內容:
recid = 27 + v + (if compressed 4 else 0)