Ich versuche, ein Prüfsignal von einer Transaktion in der Live-Blockchain zu verifizieren. es schlägt auf meinem Debian-Jessie-PC mit fehl openssl 1.0.1k
, schlägt auf meiner virtuellen Ubuntu 12.04-Maschine mit fehl openssl 1.0.1
und validiert korrekt auf meinem Debian Wheezy-PC mit openssl 1.0.1e
. beide verwenden den gleichen Code . die Transaktion ist die erste Instanz eines SIGHASH_NONE in der Live-Blockchain . ich berechne den "message" (tx) hash wie folgt:
hex: 2c7ecdcb2381e657228284398f2f66b2d7d9cf6aa1bd8e39a7300d0b3c8cfa5a
same thing in base58: 3zh5uvKWoRjFgKMSLRVqEWXB6YVLsuDKo97yCsCJZ2wB
die signatur ist:
hex: 30440220bb4fbc495aa23babb2c2be4e3fb4a5dffefe20c8eff5940f135649c3ea96444a022004afcda966c807bb97622d3eefea828f623af306ef2b756782ee6f8a22a959a2
same thing in base58: 381yXZvFc5V2dx81gRNNpj7ResKUgWA92mkTefemM9gM2kW37b3DGkV5v2BsFq94pSuH1E4jHq9ScHcp6T7Mfg41a7rbZCnd
note that this signature does not have the 02 hashcode appended to it
und der pubkey ist:
hex: 04f1939ae6b01e849bf05d0ed51fd5b92b79a0e313e3f389c726f11fa3e144d9227b07e8a87c0ee36372e967e090d11b777707aa73efacabffffa285c00b3622d6
same thing in base58: SJa4B8CrqDs6St5KaXMm4KCCksaT7RDcCaRDyKSD6Mbu1WzSwokEq3JwGtfZRz7by6jYD5QmuVhgqsPYc6wTijQq
converts to bitcoin address: 145YPBBWRj4aquewvx59SAWNrSZFT5rvxr
könnte mir jemand sagen, ob diese parameter die ecdsa-überprüfung bestehen oder nicht? Auch wenn jemand einen Online-Validator kennt, der hilfreich wäre.
Ich versuche, dies mit dem jsonrpc-Client zu überprüfen, aber es funktioniert auf keinem Computer, den ich habe:
#!/usr/bin/env python2.7
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
rpcuser = 1
rpcpassword = 1
rpc_connection = AuthServiceProxy("http://%s:%s@127.0.0.1:8332" % (rpcuser, rpcpassword))
message = "3zh5uvKWoRjFgKMSLRVqEWXB6YVLsuDKo97yCsCJZ2wB"
sig = "381yXZvFc5V2dx81gRNNpj7ResKUgWA92mkTefemM9gM2kW37b3DGkV5v2BsFq94pSuH1E4jHq9ScHcp6T7Mfg41a7rbZCnd"
addr = "145YPBBWRj4aquewvx59SAWNrSZFT5rvxr"
res = rpc_connection.verifymessage(addr, sig, message)
print res
Ausgang:
False
Vielleicht codiere ich die Nachricht oder Signatur für den RPC-Client falsch? Ich habe versucht, binär codierte Daten an ihn weiterzugeben, aber das hat ihm nicht gefallen:
File "/usr/local/lib/python2.7/dist-packages/bitcoinrpc/authproxy.py", line 125, in __call__
json.dumps(args, default=EncodeDecimal)))
File "/usr/lib/python2.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 200, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 263, in iterencode
return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xcd in position 2: invalid continuation byte
Die Verifizierung mit pybitcointools funktioniert auf allen Rechnern:
from bitcoin import *
import binascii
msg = "2c7ecdcb2381e657228284398f2f66b2d7d9cf6aa1bd8e39a7300d0b3c8cfa5a"
# make sure to include the 02 hashcode on the end of the signature here!!
sig = "30440220bb4fbc495aa23babb2c2be4e3fb4a5dffefe20c8eff5940f135649c3ea96444a022004afcda966c807bb97622d3eefea828f623af306ef2b756782ee6f8a22a959a202"
pub = "04f1939ae6b01e849bf05d0ed51fd5b92b79a0e313e3f389c726f11fa3e144d9227b07e8a87c0ee36372e967e090d11b777707aa73efacabffffa285c00b3622d6"
msg = binascii.unhexlify(msg)
print ecdsa_raw_verify(msg, der_decode_sig(sig), pub)
Ausgang:
True
Ja, Sie haben den Digest 2c7ecdcb2381e657228284398f2f66b2d7d9cf6aa1bd8e39a7300d0b3c8cfa5a richtig berechnet.
Hier ist mein Stück schmutziger Code:
static void xxtest ( )
{
const QByteArray t ( MyByteArray ( )
.putInt32 ( TX_VERSION ) // 01000000
.putInt8 ( 1 ) // 01 : one input
.putArray ( QByteArray::fromHex ( "5f386c8a3842c9a9dcfa9b78be785a40a7bda08b64646be3654301eaccfc8d5e" ) )
.putInt32 ( 1 ) // 01000000 : index
.putPrefixed ( MyByteArray ( )
.putInt8 ( OP_DUP )
.putInt8 ( OP_HASH160 )
.putPrefixed ( QByteArray::fromHex ( "21c43ce400901312a603e4207aadfd742be8e7da" ) )
.putInt8 ( OP_EQUALVERIFY )
.putInt8 ( OP_CHECKSIG ) )
.putInt32 ( TX_SEQUENCE )
.putInt8 ( 0 ) // no outputs
.putInt32 ( TX_LOCK )
.putInt32 ( SIGHASH_NONE ) );
_trace ( QString ( t.toHex ( ).constData ( ) ) );
const MyKey32 digest ( t.constData ( ), t.size ( ) );
_trace ( QString ( "digest = %1" ).arg ( digest.toStringRev ( ) ) );
const QByteArray pubkey ( QByteArray::fromHex ( "04f1939ae6b01e849bf05d0ed51fd5b92b79a0e313e3f389c726f11fa3e144d9227b07e8a87c0ee36372e967e090d11b777707aa73efacabffffa285c00b3622d6" ) );
const QByteArray signature ( QByteArray::fromHex ( "30440220bb4fbc495aa23babb2c2be4e3fb4a5dffefe20c8eff5940f135649c3ea96444a022004afcda966c807bb97622d3eefea828f623af306ef2b756782ee6f8a22a959a2" ) );
_trace ( QString ( "verify=%1 (expected value=1)" ).arg ( digest.verify ( pubkey, signature ) ) );
// now test the same with wrong digest
const MyKey32 temp ( "temp", 4 );
_trace ( QString ( "verify=%1 (expected value=0)" ).arg ( temp.verify ( pubkey, signature ) ) );
}
//--------------------------------------------------------------
bool MyKey32::verify ( const QByteArray& pub, const QByteArray& sig ) const
{
return 0 < ECDSA_verify ( 0, constPtr ( ), 32, (const quint8*)sig.constData ( ), sig.size ( ), EC_KEY_pub_key ( pub ) );
}
die ausgabe ist:
"01000000015f386c8a3842c9a9dcfa9b78be785a40a7bda08b64646be3654301eaccfc8d5e010000001976a91421c43ce400901312a603e4207aadfd742be8e7da88acffffffff000000000002000000"
"digest = 2c7ecdcb2381e657228284398f2f66b2d7d9cf6aa1bd8e39a7300d0b3c8cfa5a"
"verify=1 (expected value=1)"
"verify=0 (expected value=0)"
Update: Hier ist ein kleines Programm zum Überprüfen von Signaturen mit Abhängigkeit nur für die OpenSSL-Bibliothek:
#include <QByteArray>
#include <QDebug>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/ecdsa.h>
#include <openssl/sha.h>
static EC_KEY* EC_KEY_pub_key ( const QByteArray& pub )
{
static EC_KEY* eckey = EC_KEY_new_by_curve_name ( NID_secp256k1 );
const quint8* ppub = (const quint8*)pub.constData ( );
o2i_ECPublicKey ( &eckey, &ppub, pub.size ( ) );
return eckey;
}
//--------------------------------------------------------------
int main(int argc, char *argv[])
{
const QByteArray data ( QByteArray::fromHex ( argv [1] ) );
const QByteArray sign ( QByteArray::fromHex ( argv [2] ) );
const QByteArray pubk ( QByteArray::fromHex ( argv [3] ) );
quint8 tmp [32];
::SHA256 ( (const quint8*)data.constData ( ), data.size ( ), tmp );
quint8 digest [32];
::SHA256 ( tmp, 32, digest );
qDebug ( ) << "data=" << QString ( data.toHex ( ) );
qDebug ( ) << "sign=" << QString ( sign.toHex ( ) );
qDebug ( ) << "pubk=" << QString ( pubk.toHex ( ) );
qDebug ( ) << "digest=" << QString ( QByteArray ( (const char*)digest, 32 ).toHex ( ) );
const bool v ( ::ECDSA_verify ( 0, digest, 32, (const quint8*)sign.constData ( ), sign.size ( ), EC_KEY_pub_key ( pubk ) ) );
qDebug ( ) << "result=" << v;
return 0;
}
Die Tatsache, dass pybitcointools
(eine reine Python-Implementierung von ecdsa) in der Lage ist, die Nachricht anhand des Pubkeys und der Signatur zu verifizieren, weist darauf hin, dass es sich um ein Problem mit openssl
und nicht um die Daten selbst handelt, die falsch sind.
Gemäß den Kommentaren von amaclin unter seiner Antwort ist die Codierung für diese Signatur nicht standardmäßig:
30440220bb4fbc495aa23babb2c2be4e3fb4a5dffefe20c8eff5940f135649c3ea96444a022004afcda966c807bb97622d3eefea828f623af306ef2b756782ee6f8a22a959a2
dies wird dekodiert als:
0x30 # constant placeholder
0x44 # total length = 68 bytes
0x02 # constant placeholder
0x20 # r-length = 32 bytes
0xbb4fbc495aa23babb2c2be4e3fb4a5dffefe20c8eff5940f135649c3ea96444a # r
0x02 # constant placeholder
0x20 # s-length = 32 bytes
0x04afcda966c807bb97622d3eefea828f623af306ef2b756782ee6f8a22a959a2 # s
Beachten Sie, dass der r
Wert hier mit beginnt 0xbb = 1011 1011
- da das höchstwertige Bit ( 0x80
) gesetzt ist, ist dies eine negative Zahl. Dies würde die IsValidSignatureEncoding
Prüfung nicht bestehen und seit bip66 abgelehnt werden . Insbesondere diese Zeile würde den Fehler verursachen:
// Negative numbers are not allowed for R.
if (sig[4] & 0x80) return false;
Hier sig[4]
ist das erste (ganz linke) Byte des r
Werts.
dies erklärt also, warum einige Versionen von openssl diese Prüfsignatur nicht bestehen und andere sie bestehen - es handelt sich um eine Nicht-Standard-Kodierung, die nur mit bestimmten Versionen von openssl kompatibel ist.
Müllhausen
Amaclin
Amaclin
Müllhausen
Amaclin
dave_thompson_085
Müllhausen