Signature

ECDSA 簽名小於 71 字節的機率是多少

  • March 2, 2022

由於 DER 要求 R 和 s 值是最小編碼的有符號整數,因此它們可能小於預期的 32 個字節。對於任何簽名,R 和 s 之一或兩者小於 32 字節的機率是多少?

以下 Python 程序在計算上盡可能準確地計算所有可能的總長度:

from fractions import Fraction

P = 2**256 - 2**32 - 977
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

def lentable(table, low, high):
   # For every value v in [low, high], increment table[l], where l is the length
   # of the encoding of v. Returns the number of values in range.
   total = 0
   while low <= high:
       lowlen = 1 + (low.bit_length() // 8)
       maxval = 2**(8*lowlen - 1) - 1
       highnow = min(high, maxval)
       while len(table) <= lowlen:
           table.append(0)
       table[lowlen] += highnow - low + 1
       total += highnow - low + 1
       low = highnow + 1
   return total

def analyze(low_r, low_s):
   # Table of probabilities of S length
   slen = []
   stotal = 0
   if low_s:
       stotal = lentable(slen, 1, N // 2)
       # High s (range n/2 + 1 .. N-1) is just mapped to 1 .. N/2 again.
   else:
       stotal = lentable(slen, 1, N-1)

   # Table of probabilities of R length
   rlen = []
   rtotal = 0
   if low_r:
       rtotal = lentable(rlen, 0, 2**255-1)
       # High r cause a retry until one in 0..2**255-1 is hit.
   else:
       rtotal = lentable(rlen, 0, P-1)

   # Table of signature lengths
   dlen = [0 for _ in range(len(slen) + len(rlen) + 5)]
   for sl in range(len(slen)):
       for rl in range(len(rlen)):
           dlen[sl + rl + 6] += Fraction(slen[sl] * rlen[rl], rtotal * stotal)

   return dlen

for low_r in [0, 1]:
   for low_s in [0, 1]:
       print("low_r=%i low_s=%i" % (low_r, low_s))
       for dl, freq in enumerate(analyze(low_r, low_s)):
           print("* siglen=%i: %.15g" % (dl, freq))
       print()

其輸出包含:

低_r=0 低_s=0

  • 擺動 = 64:6.17568333711321e-15
  • 擺動 = 65:1.3553741462502e-12
  • 擺動 = 66:2.8922197969905e-10
  • 擺動 = 67:5.92558535572607e-08
  • 擺動 = 68:1.13845453597605e-05
  • 擺動 = 69:0.00194549560546875
  • 擺動 = 70:0.249996185302734
  • 擺動 = 71:0.498046875
  • 擺動 = 72:0.25

低_r=0 低_s=1

  • 擺動 = 64:1.23444548853768e-14
  • 擺動 = 65:2.7089788745549e-12
  • 擺動 = 66:5.77990988404053e-10
  • 擺動 = 67:1.18395746540045e-07
  • 擺動 = 68:2.27394048124552e-05
  • 擺動 = 69:0.00388339161872864
  • 擺動 = 70:0.498046875
  • 擺動 = 71:0.498046875

低_r=1 低_s=0

  • 擺動 = 64:1.23444548853768e-14
  • 擺動 = 65:2.7089788745549e-12
  • 擺動 = 66:5.77990988404053e-10
  • 擺動 = 67:1.18395746540045e-07
  • 擺動 = 68:2.27394048124552e-05
  • 擺動 = 69:0.00388339161872864
  • 擺動 = 70:0.498046875
  • 擺動 = 71:0.498046875

低_r=1 低_s=1

  • 擺動 = 64:2.46750861930545e-14
  • 擺動 = 65:5.41441891321881e-12
  • 擺動 = 66:1.15507603482001e-09
  • 擺動 = 67:2.36559571931139e-07
  • 擺動 = 68:4.54194378107786e-05
  • 擺動 = 69:0.00775158405303955
  • 擺動 = 70:0.992202758789062

計算使用精確分數完成,但列印為浮點數。如果您想要輸出中的分數,請將“%.15g”更改為“%s”。

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