simplito / elliptic-php

Fast, general Elliptic Curve Cryptography library. Supports curves used in Bitcoin, Ethereum and other cryptocurrencies (secp256k1, ed25519, ..)
MIT License
220 stars 52 forks source link

how sign bitcoin raw transactions #14

Closed se8820726 closed 5 years ago

se8820726 commented 5 years ago

hi good man I was reading this article about how making bitcoin raw transactions.

in the article step3 is result after signing step1 with this privatekey: 0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d

step1 (raw transaction before signing):

01000000
01
be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
00000000
19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
ffffffff
01
23ce010000000000
19 76 a9 14 2bc89c2702e0e618db7d59eb5ce2f0f147b40754 88 ac
00000000
01000000

step3 (result after signing double sha256 of step1 raw trx): 3045022100da43201760bda697222002f56266bf65023fef2094519e13077f777baed553b102205ce35d05eabda58cd50a67977a65706347cc25ef43153e309ff210a134722e9e

I signed step1 by your library and got me this result: 30450220587ce0cf0252e2db3a7c3c91b355aa8f3385e128227cd8727c5f7777877ad772022100edc508b7c14891ed15ab38c687019d7ebaf5c12908cf21a83e8ae57e8c47e95c

As you see result of signing message is different from result of signing message in step3.

this is full my code:

use Elliptic\EC;
use StephenHill\Base58;
use BN\BN;

$trx = '0100000001be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88acffffffff0123ce0100000000001976a9142bc89c2702e0e618db7d59eb5ce2f0f147b4075488ac0000000001000000';

$a = hex2bin($trx);

$privatekey = '0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d';

$ec = new EC('secp256k1');
$key = $ec->keyFromPrivate($privatekey);
$doubleSha256Trx = hash('sha256', hash('sha256', $a, true));

$mustSign = $doubleSha256Trx;
$signature = $key->sign($mustSign);
$derSign = $signature->toDER('hex');
echo $derSign;

please help me to find out whats my wrong.

thanks

ldudzsim commented 5 years ago

Sorry for delay. I look into you post and everything in your example is ok. If you look futher into article you linked, you can see that in 4. point there is deterministic ECDSA signature and this output is exatly the same as your

30450220587ce0cf0252e2db3a7c3c91b355aa8f3385e128227cd8727c5f7777877ad772022100edc508b7c14891ed15ab38c687019d7ebaf5c12908cf21a83e8ae57e8c47e95c

In our lib all ECDSA signatures are generated in "deterministic" way by default. If you want to get not deterministic signature you should pass k option to sign method. K option is a function which should return BN number. If you generate signature in not determinsitic way, each signature will be different, but all these still will successfully validate. In article in 3. point there is a not deterministic signature which is almost imposible to regenerate because to achieve that you should generate the same k. Example how to generate not deterministic signature:

use Elliptic\EC;
use BN\BN;

$message = "30f10a6468b7d98257af63fb40dfcf2cefe991346fd37c67cf7b51ff8d4404d3";
$privKeyHex = "0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d";
$pubKeyHex = "042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9";

$ec = new EC('secp256k1');
$privKey = $ec->keyFromPrivate($privKeyHex);
$pubKey = $ec->keyFromPublic($pubKeyHex, "hex");
$notDeterministicOptions = array(
    "k" => function() {
        return new BN(openssl_random_pseudo_bytes(32), 256);
    }
);

$determinsiticSignature = $privKey->sign($message);
echo "Determinsitic signature: " . $determinsiticSignature->toDER("hex") . "\n";
echo "Validating determinisitic signature: " . ($pubKey->verify($message, $determinsiticSignature) ? "Success" : "Failure") . "\n";

$notDeterminsiticSignature1 = $privKey->sign($message, $notDeterministicOptions);
echo "Not determinsitic signature no. 1: " . $notDeterminsiticSignature1->toDER("hex") . "\n";
echo "Validating not determinisitic signature no. 1: " . ($pubKey->verify($message, $notDeterminsiticSignature1) ? "Success" : "Failure") . "\n";

$notDeterminsiticSignature2 = $privKey->sign($message, $notDeterministicOptions);
echo "Not determinsitic signature no. 2: " . $notDeterminsiticSignature2->toDER("hex") . "\n";
echo "Validating not determinisitic signature no. 2: " . ($pubKey->verify($message, $notDeterminsiticSignature2) ? "Success" : "Failure") . "\n";