Signieren Sie ein TX mit dem Wert „low s“ mit OpenSSL

Ich versuche derzeit, ein tx mit OpenSSL zu signieren. Nach einigem Herumbasteln denke ich, dass ich die meisten Sender richtig hinbekommen habe, aber Electrum beschwert sich mandatory-script-verify-flag-failed (Non-canonical signature: S value is unnecessarily high), was wahrscheinlich an BIP62 liegt .

Gibt es eine Möglichkeit, mit OpenSSL ordnungsgemäße Signaturen zu erstellen, außer zu versuchen und zu hoffen, einen kleinen sWert zu erhalten?

Der Rest meines Codes befindet sich in Golang und ich konnte kein geeignetes Paket für die verwendete ECDSA-Kurve finden und habe daher OpenSSL umschlossen.

Antworten (3)

Alternativ könnten Sie libsecp256k1 verwenden . Dies ist der Code, der von Bitcoin Core zum Signieren verwendet wird und automatisch Low-S-Signaturen erstellt (Haftungsausschluss: Ich bin der Hauptautor dieser Bibliothek). Vielleicht existiert ein Go-Wrapper.

Wenn Sie sich an OpenSSL halten, ist es möglich, den S-Wert nach dem Signieren manuell anzupassen. Dies ist, was Bitcoin Core vor v0.10 getan hat. Hier ist, was es früher gemacht hat: https://github.com/bitcoin/bitcoin/blob/v0.9.0/src/key.cpp#L204L224

Allerdings so ein Haftungsausschluss.

Open SSL wird es nicht erzwingen, Sie müssen es selbst tun. Von GIP 62:

Der Wert S in Signaturen muss zwischen 0x1 und 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0 (einschließlich) liegen. Wenn S zu hoch ist, ersetzen Sie es einfach durch S' = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 - S.

Quelle

Die Frage ist dann: Wie kann ich diesen Wert mit OpenSSL setzen? Einen Parameter zum Einstellen habe ich nicht gefunden
@soupdiver: Diese Zahlen sind nicht zufällig die Reihenfolge der Gruppe für secp256k1 und die Hälfte der Reihenfolge (abgerundet). Wenn Sie eine EC_GROUP für secp25k1 haben, verwenden Sie EC_GROUP_get[0]_order; Wenn Sie einen EC_KEY haben, verwenden Sie zuerst EC_KEY_get0_group. Sobald Sie die Reihenfolge BN_dup BN_rshift1 BN_cmp und BN_sub haben, sollte der Wert aus der ECDSA_SIG ausreichen.
Ich verstehe den letzten Kommentar nicht ganz
@soupdiver Sie müssen es nicht in OpenSSL festlegen, Sie verwenden es einfach, der s-Wert ist eine Komponente der endgültigen Signatur.
ja ich verstehe das. Ich frage mich, ob es eine Möglichkeit gibt, diesen Wert festzulegen, wenn er zu groß ist und daher vom Netzwerk abgelehnt wird
@soupdiver Ich habe erklärt, was zu tun ist, den niedrigen s-Wert berechnet, wie ich es in meiner Frage erklärt habe, und ihn in die Bitcoin-Transaktionssignatur eingefügt. Das ist alles, was Sie tun müssen

Gibt es eine Möglichkeit, mit OpenSSL ordnungsgemäße Signaturen zu erstellen, außer zu versuchen und zu hoffen, einen kleinen s-Wert zu erhalten?

Wenn die Geschwindigkeit nicht von Bedeutung ist, ist dies keine schlechte Idee.

Update: Nehmen Sie etwas Pseudocode:

while ( true )
{
  signature = createOpenSslSignature ( params );
  if ( !signature.toHex ( ).contains ( "022100" ) )
    return signature;
}
Ich würde es vorziehen, "richtige" Signaturen direkt zu erstellen und es nicht brutal erzwingen zu müssen :)
Antwort aktualisiert. Dies ist kein Brute-Force. und das ist nicht die beste Lösung. aber das ist die einfachste Implementierung :)