Wie funktioniert der ECDSA-Verifizierungsalgorithmus während der Transaktion?

Ich verstehe das Grundkonzept ECDSA, wo Bob, wenn er eine Nachricht signieren möchte, eine Zufallszahl n generiert, multipliziere sie mit dem secp256k1, r = dem x-Wert, s = (H(x) d r)*n^-1 mod q . Auch die Verifizierung erfolgt durch P=u1(G)+u2(P), wobei G der Erzeugungspunkt und P der öffentliche Schlüssel von Bob ist.

Ich ging durch die Transaktionsseite von Wiki. Mein Verständnis ist, dass ECDSA irgendwo im Abschnitt scriptSig/scriptPubKey stattfindet.

Wenn Bob die nicht ausgegebene Transaktionsausgabe ausgeben möchte, muss Bob ein Signaturskript erstellen, das auf frühere Transaktionen verweist, und auch seinen vollständigen öffentlichen Schlüssel bereitstellen, der dann gehasht wird, um mit früheren Transaktionen als Empfänger übereinzustimmen, den Bob ebenfalls generieren muss eine Signatur, um zu beweisen, dass der öffentliche Schlüssel von seinem öffentlichen Schlüssel stammt.

Es lässt mich mit vielen Fragen zurück, wie den Transaktionsverifizierungsschritten: OP_CHECKSIG, wo ich vermute, dass die meisten Schritte versuchen, den Hash abzugleichen, und schließlich in Schritt 10 die ECDSA-Verifizierung durchführt.

Folgt es immer noch dem Grundkonzept, das u1, u2 berechnet und den vollständigen öffentlichen Schlüssel verwendet, der von Bob bereitgestellt wird, um am Ende zu versuchen, den r-Wert abzugleichen? Oder macht es etwas ganz anderes? Ich kann verstehen, warum pubKeyStr und sigStr für die ECDSA-Überprüfung erforderlich sind, aber es nimmt auch sha256 ^ 2 auf, was meiner Meinung nach doppeltes Hashing mit (verifThisStr) ist. Ich verstehe überhaupt nicht, woher das kommt.

Was würde bei der Berechnung von s in die gehashte Nachricht H(x) eingesetzt? Und wählt Bob zufällig eine Variable aus, nur um die Signatur zu generieren, als er aufgefordert wurde, die nicht ausgegebene Transaktion zu beanspruchen?

Antworten (2)

Nehmen wir „Pizza-Transaktion“ https://blockchain.info/tx/cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79

01000000018dd4f5fbd5e980fc02f35c6ce145935b11e284605bf599a13c6d415db55d07a1000000008b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabbffffffff0200719a81860000001976a914df1bd49a6c9e34dfa8631f2c54cf39986027501b88ac009f0a5362000000434104cd5e9726e6afeae357b1806be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce3388fa1abd0fa88b06c44ce81e2234aa70fe578d455dac00000000


// decoded by https://blockchain.info/decode-tx
{
   "lock_time":0,
   "size":300,
   "inputs":[
      {
         "prev_out":{
            "index":0,
            "hash":"a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d"
         },
         "script":"4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb"
      }
   ],
   "version":1,
   "vin_sz":1,
   "hash":"cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79",
   "vout_sz":2,
   "out":[
      {
         "script_string":"OP_DUP OP_HASH160 df1bd49a6c9e34dfa8631f2c54cf39986027501b OP_EQUALVERIFY OP_CHECKSIG",
         "address":"1MLh2UVHgonJY4ZtsakoXtkcXDJ2EPU6RY",
         "value":577700000000,
         "script":"76a914df1bd49a6c9e34dfa8631f2c54cf39986027501b88ac"
      },
      {
         "script_string":"04cd5e9726e6afeae357b1806be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce3388fa1abd0fa88b06c44ce81e2234aa70fe578d455d OP_CHECKSIG",
         "address":"13TETb2WMr58mexBaNq1jmXV1J7Abk2tE2",
         "value":422300000000,
         "script":"4104cd5e9726e6afeae357b1806be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce3388fa1abd0fa88b06c44ce81e2234aa70fe578d455dac"
      }
   ]
}

Sehen Sie sich das input=0-Skript an und decodieren Sie es:

48  // push next 0x48 bytes
30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e01
41  // push next 0x41 bytes
042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb

Der erste Push ist eine mit hashtype=01 verkettete Signatur (SIGHASH_ALL)

Der zweite Push ist der öffentliche Schlüssel für die Adresse 17SkEw2md5avVNyYgj6RiXuQKNwkXaxFyQ

Wie prüfen wir - ist diese Transaktion gültig? Ist es richtig unterschrieben?

1) Entfernen Sie das Eingabeskript aus der Transaktion. Wir sollten Bytes entfernen (Skript len ​​nicht vergessen)

8b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d
075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59
290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e0
57cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8
526e59667ce9c4e9dcebcabb

2) Ersetzen Sie es durch das Finanzierungsskript zu 17SkEw2md5avVNyYgj6RiXuQKNwkXaxFyQ

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG
1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac

(Die Skriptlänge wieder nicht vergessen!)

3) Hängen Sie SIGHASH_ALL als 32-Bit-Low-Endian-Wert an. Das Ergebnis wird sein

01000000018dd4f5fbd5e980fc02f35c6ce145935b11e284605bf599a13c6d41
5db55d07a1000000001976a91446af3fb481837fadbb421727f9959c2d32a368
2988acffffffff0200719a81860000001976a914df1bd49a6c9e34dfa8631f2c
54cf39986027501b88ac009f0a5362000000434104cd5e9726e6afeae357b180
6be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce33
88fa1abd0fa88b06c44ce81e2234aa70fe578d455dac0000000001000000

4) Hash es zweimal von SHA256. Der Digest lautet 692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2

5) OK, wir haben jetzt drei Artikel:

  • a) öffentlicher Schlüssel 042e930f39ba62c6[...cut...]6e59667ce9c4e9dcebcabb
  • b) Unterschrift 304502210099081[...Schnitt...]d59290d2fddf25269ee0e
  • c) Digest 692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2

Übergeben Sie diese Werte an die Standard-ECDSA-Verifizierungsmethode und Sie erhalten das Ergebnis: wahr oder falsch. Hier ist ein kleiner Teil meines Quick-and-Dirty-Checks mit fest codierten Werten:

const QByteArray xx ( QByteArray::fromHex ( "01000000018dd4f5fbd5e980fc02f35c6ce145935b11e284605bf599a13c6d41"
                                            "5db55d07a1000000001976a91446af3fb481837fadbb421727f9959c2d32a368"
                                            "2988acffffffff0200719a81860000001976a914df1bd49a6c9e34dfa8631f2c"
                                            "54cf39986027501b88ac009f0a5362000000434104cd5e9726e6afeae357b180"
                                            "6be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce33"
                                            "88fa1abd0fa88b06c44ce81e2234aa70fe578d455dac0000000001000000" ) );
const MyKey32 digest ( xx.constData ( ), xx.size ( ) ); // construct object of sha256 (sha256 ( xx ) )
_trace ( digest.toString ( ) );                         // print result
const QByteArray pubkey ( QByteArray::fromHex ( "042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb" ) );
const QByteArray signature ( QByteArray::fromHex ( "30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e" ) );
_trace ( QString ( "verify=%1" ).arg ( digest.verify ( pubkey, signature ) ) );

Die Ausgabe ist

"692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2"
"verify=1"
Der kurze Durchlauf ist sehr nützlich, es gibt noch ein paar kleinere Fragen dazu. Ich bin vielleicht immer noch verwirrt, aber ich werde versuchen, es zu verstehen. Nach dem Entfernen des Eingabeskripts (Schritt 1) ​​Ersetzen Sie es durch das Finanzierungsskript (Schritt 2) und hängen Sie SIGHASH_ALL (Schritt 3) an, was die neue Transaktion ist. Gemäß der anderen Antwort würde ich für die Signatur s= (H(x)*d*r)n^-1 mod q, wobei H(x) alles in rohem tx ist, annehmen, dass dies genau wie der Digest ist ( ?) Die Signatur (304502 ... ee0e) wird also mit dem Digest (692678 ... d4c2), dem Tempkey (zufällig) und dem privaten Schlüssel generiert?
Wenn ja, sehe ich, dass Ihre ECDSA-Überprüfung nur 2 Eingaben enthält, nämlich Pubkey und Signatur. Heraus kam der Digest. Da das Grundkonzept u1 und u2 verwendet. Es stimmte mit u1(G)+u2(B) überein, wobei B= öffentlicher Schlüssel, G= Erzeugungspunkt, u1 = H(x)*s^-1, u2 = rd s -1*n, wo die Aufhebung auftritt lässt die x-Koordinate von n*G = r = varify. Aber da unser key.verify den Digest nicht enthält, verwendet es eine andere Methode? indem Sie den Digest mit dem öffentlichen Schlüssel und der Signatur neu generieren?
Ich habe meine eigene Bibliothek. Die Klasse MyKey32 ist eine Klasse zum Ausführen einiger Aktionen. Die letzte Zeile kann also als „digest.verify (pubkey, signature)“ geschrieben werden, wobei „digest –“ ein 32-Byte-Objekt ist
>Die Signatur (304502...ee0e) wird also mit dem Digest (692678...d4c2), dem Tempkey (zufällig) und dem privaten Schlüssel generiert? <<< Ja! Der Besitzer des privaten Schlüssels erstellte 2010 das gleiche Array von Bytes, berechnete Digest (das gleiche wie meins, oder um richtig zu sein: meins ist dasselbe wie seins) und erstellte eine Signatur mit privkey und Digest. Zum Erstellen der Signatur benötigt er privkey und Digest. Zur Überprüfung der Signatur benötigen wir Pubkey und Digest.

Die Frage ist, folgt es immer noch dem Grundkonzept, das u1, u2 berechnet und den vollständigen öffentlichen Schlüssel verwendet, der von Bob bereitgestellt wird, um am Ende zu versuchen, den r-Wert abzugleichen?

Ja, das ist die Grundidee, warum sollte es Ihrer Meinung nach anders sein? Es gibt eine etwas komplizierte Art und Weise, wie der Hash, der signiert werden muss, berechnet wird, aber sobald der Hash berechnet ist, behandelt ECDSA den Hash einfach als 256-Bit-Ganzzahl.

Es nimmt auch sha256^2 auf, was meiner Meinung nach doppeltes Hashing ist, mit dem (verifThisStr), von dem ich überhaupt nicht verstehe, woher das kommt

Ja, sha256^2(x) ist einfach als sha256(sha256(x)) definiert. Ich bin mir nicht sicher, was Sie versuchen, auf "verifThisStr" zu verweisen, aber wenn es der Wert ist, der mit dem ECDSA verifiziert werden muss, dann sprechen Sie nur über das Ergebnis des doppelten Hashs, das als Ganzzahl behandelt wird.

Auch wenn es immer noch dem Grundkonzept folgt, was würde bei der Berechnung von s in die gehashte Nachricht H(x) eingesetzt?

Die Teile der Transaktion, die doppelt gehasht und dann signiert werden müssen, hängen vom SigHashType ab ( https://bitcoin.org/en/developer-guide#signature-hash-types ). Für Standard-SIGHASH_ALL enthält es alles im Roh-Tx mit Ausnahme der scriptSigs, da Sie Ihre eigene Signatur nicht signieren können.

Und wählt Bob zufällig eine Variable aus, nur um die Signatur zu generieren, als er aufgefordert wurde, die nicht ausgegebene Transaktion zu beanspruchen?

Ja, beim Erstellen einer Signatur wird eine Zufallszahl ausgewählt, sodass ECDSA-Signaturen nicht deterministisch sind.

Es sollte beachtet werden, dass erstens die Zufallszahl k, die zum Generieren von R verwendet wird, kurzlebig sein sollte – niemals wiederholt, sonst besteht die Gefahr, dass Ihr privater Hauptschlüssel preisgegeben wird. Zweitens wird dringend empfohlen, nicht kmit einem Zufallszahlengenerator (RNG) zu generieren. Die bewährte Methode der Branche besteht darin, einen deterministisch-zufälligen Prozess zu verwenden, der mit den Transaktionsdaten selbst gesät wird. Dann riskieren Sie keine Wiederverwendung kaufgrund eines falsch gesetzten RNG. Siehe RFC 6979.