Ich möchte openssl auf Unixoide-Systemen verwenden, um eine Transaktion zu überprüfen. Ich trete auf Fehler, wenn ich versuche, den Hash eines Bitcoin-Trx zu verifizieren. Hier arbeite ich an Mac OSX und OpenSSL (1.0.2a 19. März 2015).
Ich weiß, dass ich den QT-Client oder die verschiedenen Python/PHP/Java-Lösungen verwenden kann, das ist hier nicht das Ziel. Ich verstehe auch, dass Bitcoin nach libsecp256k1 wandert… Ich bin dem Beispiel von Pizza trx hier gefolgt:
Wie funktioniert der ECDSA-Verifizierungsalgorithmus während der Transaktion?
Für die Verifizierung ist kein privater Schlüssel erforderlich, nur Pubkey, Hash und Sig. Openssl bietet zwei Möglichkeiten, ein Ergebnis zu überprüfen:
openssl dgst -sha256 -verify pubkey.pem -signature tmpfile.sig sha256.txt
oder
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmpfile.sig -in sha256.txt
Knifflig ist, wie man vom Hex-Pub-Key („042e930f39…ebcabb“) in das PEM-Format kommt, das openssl zur Verifizierung will. Am Ende habe ich die Schritte hinzugefügt, wie ich den Inbusschlüssel in PEM umgewandelt habe.
Wenn ich das bitocin double sha256 des erwähnten Pizza trx verwende (ich habe auch mehrere andere ausprobiert), erhalte ich diesen Fehler:
openssl dgst -sha256 -verify pubkey.pem -signature tmpfile.sig sha256.txt
Error Verifying Data
140735175988048:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1198:
140735175988048:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:372:Type=ECDSA_SIG
oder mit pkeyutl:
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmpfile.sig -in sha256.txt
Public Key operation error
140735175988048:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1198:
140735175988048:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:372:Type=ECDSA_SIG
Wenn ich meine priv- und pub-Schlüssel mit openssl erstelle und einen „demo sha256“-String signiere, kann ich das korrekt verifizieren. Nur diese Bitcoin sha256s-Strings funktionieren nicht. Irgendetwas muss mir fehlen…
Basierend auf mehreren Messwerten hier im Stackexchange habe ich die PEM-Schlüssel von openssl rückentwickelt. Der pem-formatierte Schlüssel will einen PEM_prestring („3056301006072a8648ce3d020106052b8104000a034200“) und den angehängten Pubkey.
$ result=3056301006072a8648ce3d020106052b8104000a034200042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb
$ result=$( echo $result | sed 's/[[:xdigit:]]\{2\}/\\x&/g' )
$ printf $result > tmpfile
$ hexdump -C tmpfile
00000000 30 56 30 10 06 07 2a 86 48 ce 3d 02 01 06 05 2b |0V0...*.H.=....+|
00000010 81 04 00 0a 03 42 00 04 2e 93 0f 39 ba 62 c6 53 |.....B.....9.b.S|
00000020 4e e9 8e d2 0c a9 89 59 d3 4a a9 e0 57 cd a0 1c |N......Y.J..W...|
00000030 fd 42 2c 6b ab 36 67 b7 64 26 52 93 82 c2 3f 42 |.B,k.6g.d&R...?B|
00000040 b9 b0 8d 78 32 d4 fe e1 d6 b4 37 a8 52 6e 59 66 |...x2.....7.RnYf|
00000050 7c e9 c4 e9 dc eb ca bb ||.......|
Dies wird base64-kodiert sein und einige schöne Umgebungen hinzugefügt.
$ openssl enc -base64 -in tmpfile -out pubkey.pem
$ cat pubkey.pem
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
und wir geben pubkey.pem eine schöne Umgebung, damit es so aussieht:
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
-----END PUBLIC KEY-----
und überprüfen Sie über asn die Struktur:
$ openssl asn1parse -in pubkey.pem
0:d=0 hl=2 l= 86 cons: SEQUENCE
2:d=1 hl=2 l= 16 cons: SEQUENCE
4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
13:d=2 hl=2 l= 5 prim: OBJECT :secp256k1
20:d=1 hl=2 l= 66 prim: BIT STRING
Die von mir verwendeten Dateien:
$ cat pubkey.pem
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELpMPObpixlNO6Y7SDKmJWdNKqeBXzaAc
/UIsa6s2Z7dkJlKTgsI/QrmwjXgy1P7h1rQ3qFJuWWZ86cTp3OvKuw==
-----END PUBLIC KEY-----
$ cat tmpfile.sig
30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e
$ cat sha256.txt
692678553d1b85ccf87d4d4443095f276cdf600f2bb7dd44f6effbd7458fd4c2
Sie haben den Pubkey richtig verstanden, aber mindestens eine Sache falsch und vielleicht mehr in den Teilen, die Sie nicht gezeigt haben.
Erstens und grundlegend verwendet Bitcoin ein unkonventionelles (wohl nicht standardisiertes) Schema, bei dem die Daten vor der NonceG,kinv(Hash+Nonceimage)-Berechnung und der entsprechenden Überprüfung doppelt gehasht werden. dgst -sign/-verify
tut nur den Standard-Single-Hash, also müssen Sie entweder zuerst hashen und dann verwenden dgst -sign/verify
oder zweimal hashen und dann verwenden pkeyutl -sign/verify
.
Auch die Signaturdatei, die Verifizierungseingabedatei (Hash oder andere) und die Hash-Eingabe(n) müssen Rohdaten, auch Binärdaten , sein , nicht die Hex-Darstellung.
Daher:
$ cat pizza.inphex
01000000018dd4f5fbd5e980fc02f35c6ce145935b11e284605bf599a13c6d41
5db55d07a1000000001976a91446af3fb481837fadbb421727f9959c2d32a368
2988acffffffff0200719a81860000001976a914df1bd49a6c9e34dfa8631f2c
54cf39986027501b88ac009f0a5362000000434104cd5e9726e6afeae357b180
6be25a4c3d3811775835d235417ea746b7db9eeab33cf01674b944c64561ce33
88fa1abd0fa88b06c44ce81e2234aa70fe578d455dac0000000001000000
$ xxd -r -p <pizza.inphex >pizza.inpraw
$ cat pizza.sighex
30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e
$ xxd -r -p <pizza.sighex >pizza.sigraw
$ cat pizza.keyhex
3056301006072a8648ce3d020106052b8104000a034200
042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb
$ xxd -r -p <pizza.keyhex | openssl pkey -pubin -inform der >pizza.keypem
$ openssl sha256 <pizza.inpraw -binary >pizza.hash1; xxd pizza.hash1
0000000: 0838 6747 8cb0 d1d8 bb86 4175 bbc4 9728 .8gG......Au...(
0000010: cffc c114 bc2e 762c 6df6 4f2c 965a 9a66 ......v,m.O,.Z.f
$ openssl sha256 <pizza.hash1 -verify pizza.keypem -signature pizza.sigraw
Verified OK
$ openssl sha256 <pizza.hash1 -binary >pizza.hash2; xxd pizza.hash2
0000000: c2d4 8f45 d7fb eff6 44dd b72b 0f60 df6c ...E....D..+.`.l
0000010: 275f 0943 444d 7df8 cc85 1b3d 5578 2669 '_.CDM}....=Ux&i
$ openssl pkeyutl <pizza.hash2 -verify -pubin -inkey pizza.keypem -sigfile pizza.sigraw
Signature Verified Successfully
Beachten Sie, dass der zweite Hash der in #32305 Punkt 4 gezeigte ist, außer dass die Software von amaclin die Bytes in umgekehrter Reihenfolge anzeigt.
pebwindkraft
Benutzer2298995
dave_thompson_085
pkey -inform der -pubin
und wenn dies fehlschlägt, mitasn1parse -inform der
.