Ecdsa

您如何使用python從簽名中找出r和s

  • November 28, 2018

ECDSA r, s 編碼為簽名

這個連結似乎沒有加起來,有什麼建議嗎?

DER 編碼的 ECDSA 簽名的結構如下:

在此處輸入圖像描述

30標識SEQUENCEASN1編碼中的a,後跟z(序列)的長度。r並且s可以是 32 或 33 字節長,具體取決於 DER 編碼值的大小。r並且s總是以 開頭02,它在 ASN1 中標識一個整數值。最後,tailing ( ht) 字節代表 hashtype

為了解析簽名以提取兩個值,您應該檢查它們的長度,該長度始終為 1 字節長,並根據結果提取值。這是執行此操作的程式碼:

def parse_element(hex_str, offset, element_size):
   """
   :param hex_str: string to parse the element from.
   :type hex_str: hex str
   :param offset: initial position of the object inside the hex_str.
   :type offset: int
   :param element_size: size of the element to extract.
   :type element_size: int
   :return: The extracted element from the provided string, and the updated offset after extracting it.
   :rtype tuple(str, int)
   """

   return hex_str[offset:offset+element_size], offset+element_size


def dissect_signature(hex_sig):
   """
   Extracts the r, s and ht components from a Bitcoin ECDSA signature.
   :param hex_sig: Signature in  hex format.
   :type hex_sig: hex str
   :return: r, s, t as a tuple.
   :rtype: tuple(str, str, str)
   """

   offset = 0
   # Check the sig contains at least the size and sequence marker
   assert len(hex_sig) > 4, "Wrong signature format."
   sequence, offset = parse_element(hex_sig, offset, 2)
   # Check sequence marker is correct
   assert sequence == '30', "Wrong sequence marker."
   signature_length, offset = parse_element(hex_sig, offset, 2)
   # Check the length of the remaining part matches the length of the signature + the length of the hashflag (1 byte)
   assert len(hex_sig[offset:])/2 == int(signature_length, 16) + 1, "Wrong length."
   # Get r
   marker, offset = parse_element(hex_sig, offset, 2)
   assert marker == '02', "Wrong r marker."
   len_r, offset = parse_element(hex_sig, offset, 2)
   len_r_int = int(len_r, 16) * 2   # Each byte represents 2 characters
   r, offset = parse_element(hex_sig, offset, len_r_int)
   # Get s
   marker, offset = parse_element(hex_sig, offset, 2)
   assert marker == '02', "Wrong s marker."
   len_s, offset = parse_element(hex_sig, offset, 2)
   len_s_int = int(len_s, 16) * 2  # Each byte represents 2 characters
   s, offset = parse_element(hex_sig, offset, len_s_int)
   # Get ht
   ht, offset = parse_element(hex_sig, offset, 2)
   assert offset == len(hex_sig), "Wrong parsing."

   return r, s, ht


example_sig = None  # insert_sig_here
r, s, ht = dissect_signature(example_sig)
print "r: %s\ns: %s\nht: %s\n" % (r, s, ht)

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