Bitcoind mag kein ECDSA (r, s)-Paar, das von OpenSSL produziert wird

Ich schreibe Transaktionen manuell und bin auf eine ziemlich bizarre Situation gestoßen.

Nur eine von wenigen Transaktionen, die ich an Bitcoin sende, wird akzeptiert, ansonsten erhalte ich eine REJECT_NONSTANDARD(nicht kanonische DER-Signatur).

Also habe ich mir die Hände schmutzig gemacht und verfolgt, dass die Ablehnung von dieser Zeile stammt: https://github.com/bitcoin/bitcoin/blob/9c5f0d542d1db507b3b9c87bd9de6d0d758d51c1/src/script/interpreter.cpp#L163

Ich habe über DER-Codierung gelesen und überprüft, wie IsValidSignatureEncodingsie erzwungen wird, aber ich weiß nicht, warum OpenSSL nicht-DER-kompatible (r, s) Werte generiert?

Wie soll ich das überwinden? Ich denke an etwas in der Art von (Pseudocode):

Pair (r, s);
do
{
   (r, s) = sign(hash, pvtkey);
} while (r[0] >= 128 || s[0] >= 128); // where r[0], s[0] should be the very first byte of each value

Aber ist das nicht überflüssig? Kann ich OpenSSL irgendein Flag geben, um überhaupt ein gültiges DER (R, S)-Paar zu erzeugen?

Verwenden Sie OpenSSL zum Codieren des DER oder haben Sie Ihre eigene DER-Codierungsfunktion geschrieben? Es ist sehr einfach, eine Funktion zu erhalten, die nur für einige Eingaben richtig ist.

Antworten (3)

Ein möglicher Grund ist, dass Bitcoin Core einen niedrigen S-Wert erwartet. Versuchen Sie, s durch Ns zu ändern, wenn s > N/2 (N ist die Kurvenordnung).

Quelle hier

Eigentlich war das nicht mein ursprüngliches Problem, das ist ein völlig anderer Fehlercode, den ich jetzt bekomme ( SCRIPT_ERR_SIG_HIGH_S), nachdem ich meinem fehlerhaften S-Wert ein 0x00-Byte vorangestellt habe (ich habe in einem anderen Thread gelesen, was getan werden sollte, wenn das erste Byte des anfänglichen S > ist = 128). Also ja, wahrscheinlich muss ich jetzt tun, was Sie vorgeschlagen haben

rDer folgende Python-Code kann eine gültige DER-codierte Signatur als gegebene und sals Byte-Objekte erstellen :

def ser_sig_der(r, s):
    sig = b"\x30"

    # Make r and s as short as possible
    ri = 0
    for b in r:
        if b == "\x00":
            ri += 1
        else:
            break
    r = r[ri:]
    si = 0
    for b in s:
        if b == "\x00":
            si += 1
        else:
            break;
    s = s[si:]

    # Make positive of neg
    first = r[0]
    if first & (1 << 7) != 0:
        r = b"\x00" + r
    first = s[0]
    if first & (1 << 7) != 0:
        s = b"\x00" + s

    # Write total length
    total_len = len(r) + len(s) + 4
    sig += struct.pack("B", total_len)

    # write r
    sig += b"\x02"
    sig += struct.pack("B", len(r))
    sig += r

    # write s
    sig += b"\x02"
    sig += struct.pack("B", len(s))
    sig += s
    return sig

Es ist wichtig zu beachten, dass Signaturen in Bitcoin auch ein zusätzliches Byte enthalten, das an die DER-codierte Signatur angehängt ist, das den Sighash-Typ darstellt. Sie müssen dieses Byte selbst hinzufügen.

Das dritte Byte codiert Informationen über die Inhaltslänge. Wenn die Inhaltslänge weniger als 127 Byte beträgt, ist das dritte Byte gleich der Inhaltslänge. Wenn es größer als 127 und kleiner als 255 ist, ist das dritte Byte 0x81. Wenn es größer als 255 ist, ist das dritte Byte 0x82.

Das/die nächste(n) Byte(s) zeigt/zeigen die Inhaltslänge an.

Referenz: https://github.com/openssl/openssl/blob/master/crypto/asn1_dsa.c encode_der_length https://www.itu.int/rec/T-REC-X.690-201508-I/en

Obwohl Bitcoin-Signaturen secp256k1 und Low-S verwenden, wie MikeD bemerkte, überschreiten alle Wertteile niemals 69 Bytes und Ihr zweiter und dritter Fall der Längencodierung treten nie auf. (Der dritte Fall ist tatsächlich >=256 und <65536; für längere Zeit gibt es mehr Längencodierungen, die Sie nicht erwähnen, aber sie werden von dem von Ihnen verlinkten Code nicht unterstützt oder benötigt.)