Home Foren Trezor Wallet Wie entschlüsselt man die 65-Byte-Signatur, die von trezorctl erzeugt wird?

Ansicht von 0 Antwort-Themen
  • Autor
    Beiträge
    • #2576979
      root_s2yse8vt
      Administrator
      Up
      0
      Down
      ::

      Ich versuche, das Ausgabeformat für Trezor-Signaturen zu verstehen, damit ich sie von einer anderen Bibliothek aus programmatisch überprüfen kann. Und ich versuche, trezorctl zu verwenden, um 32-Byte-Nachrichten zu signieren und sie als base64 an den Cli zu übergeben.

      trezorctl get_public_node -n “m/44’/0’/0’/0/0”

      Gibt mir einen richtigen hexadezimal kodierten öffentlichen Schlüssel, den ich richtig dekodieren kann.

      trezorctl sign-message -n “m/44’/0’/0’/0/0” “my_32_byte_b64encoded_message_here”

      Liefert mir eine Ausgabe mit einer Adresse, der Nachricht im kodierten Format und der Signatur ebenfalls im b64-Format.

      Wenn ich die b64-Signatur dekodiere, ist sie 65 Byte lang, und ich erwarte, dass 64 Byte der Signatur-Digest und 1 Byte am Anfang die Wiederherstellungskennung sind (dies war die einzige Information, die ich online finden konnte und die zu stimmen scheint).

      Wiederherstellungskennungen können nur die Werte 0, 1, 2, 3 annehmen, und bei einem anderen Versuch erhielt ich 31 oder 32 zurück.

      Ich habe versucht, alle möglichen Wiederherstellungskennungen zu verwenden und eine Secp256k1-Wiederherstellungsfunktion mit derselben Nachricht zu verwenden, und es wird ein öffentlicher Schlüssel zurückgegeben, der NICHT mit der Ausgabe von get_public_node übereinstimmt.

      Was verstehe ich hier nicht? Ich bin den Python-Code von trezorctl durchgegangen, aber ich kann die Kodierer/Dekodierer dafür nicht finden. Die meisten anderen Bibliotheken für recoveryIds stellen sie einfach als einen Wert mit 4 Möglichkeiten dar.

      Kann mir jemand einen Hinweis darauf geben, wie man diese Signatur in einem kompakten Format dekodiert? Das Problem ist, dass die Signatur in der Bibliothek, die ich verwende (rust bitcoin lib), nicht verifiziert werden kann, so dass ich versucht habe, doppelt zu überprüfen, ob ich die Signatur richtig dekodiere. Wenn ich nur eine Sanity-Check von jemandem, der weiß, was hier los ist und weiß, wie man die wiederherstellbare ID zu dekodieren und / oder erhalten Sie den öffentlichen Schlüssel, um get_public_node übereinstimmen würde es eine Menge helfen. Vielleicht mache ich hier einen trivialen Fehler?

      Ich habe auch versucht, die GUI verify_message mit den Ausgaben es produziert, und es funktionierte völlig, ich glaube nicht, Trezor ist das Problem hier, ich kann nur nicht herausfinden, wie man manuell die Signatur für die Verwendung in einer anderen Bibliothek zu dekodieren.

      **Edit**

      Für den Fall, dass jemand auf das gleiche Problem stößt, verwirrten mich die erforderlichen Header zum Signieren der Nachricht:

      Die Lösung war, eine Funktion wie diese zu verwenden:

      /// Hash der Nachricht für die Signatur unter Verwendung des Bitcoin-Nachrichtensignaturformats
      pub fn signed_msg_hash(msg: &str) -> sha256d::Hash {
      sha256d::Hash::hash(
      &[
      MSG_SIGN_PREFIX,
      &encode::serialize(&encode::VarInt(msg.len() as u64)),
      msg.as_bytes(),
      ]
      .concat(),
      )
      }

      Und damit kann ich dann korrekt verifizieren (kann aber immer noch nicht die Wiederherstellungs-ID-Bits herausfinden).

      Ich fand dies heraus, aus der Python-Firmware-Code für Bitcoin app, die hat:

      if not utils.BITCOIN_ONLY und coin.decred:
      h = utils.HashWriter(blake256())
      sonst:
      h = utils.HashWriter(sha256())
      if not coin.signed_message_header:
      raise wire.DataError(“Empty message header not allowed.”)
      write_compact_size(h, len(münze.signierte_nachricht_kopfzeile))
      h.extend(coin.signed_message_header.encode())
      write_compact_size(h, len(nachricht))
      h.extend(nachricht)
      ret = h.get_digest()
      if coin.sign_hash_double:
      ret = sha256(ret).digest()
      return ret

      Ich konnte den Recovery-Teil nicht herausfinden, habe aber dieses Codefragment hier gesehen:

      seckey = node.private_key()

      digest = message_digest(münze, nachricht)
      Signatur = secp256k1.sign(seckey, digest)

      if script_type == InputScriptType.SPENDADDRESS:
      script_type_info = 0
      elif script_type == InputScriptType.SPENDP2SHWITNESS:
      script_type_info = 4
      elif script_type == InputScriptType.SPENDWITNESS:
      script_type_info = 8
      sonst:
      raise wire.ProcessError(“Unsupported script type”)

      # Fügen Sie dem Wiederherstellungsbyte Informationen zum Skripttyp hinzu.
      if script_type_info != 0 und nicht msg.no_script_type:
      signature = bytes([signature[0] + script_type_info]) + Signatur[1:]

      return MessageSignature(address=address, signature=signature)

      was darauf hinzudeuten scheint, dass das Wiederherstellungsbyte-Präfix geändert wird, bevor es weitergegeben wird, was mir verrückt vorkommt? Ich habe noch nicht herausgefunden, wie ich es genau zurückbekomme.

Ansicht von 0 Antwort-Themen
  • Du musst angemeldet sein, um auf dieses Thema antworten zu können.