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 IsValidSignatureEncoding
sie 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?
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
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 habenr
Der folgende Python-Code kann eine gültige DER-codierte Signatur als gegebene und s
als 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
G. Maxwell