Skip to content

Instantly share code, notes, and snippets.

@scintill
Forked from xqus/example.php
Last active December 10, 2015 16:28
Show Gist options
  • Save scintill/4460738 to your computer and use it in GitHub Desktop.
Save scintill/4460738 to your computer and use it in GitHub Desktop.
<?php
// configure the ECC lib
if (!defined('USE_EXT')) {
if (extension_loaded('gmp')) {
define('USE_EXT', 'GMP');
} else if(extension_loaded('bcmath')) {
define('USE_EXT', 'BCMATH');
} else {
die('GMP or bcmath required. (GMP is faster).');
}
}
define('MAX_BASE', 256); // so we can use bcmath_Utils::bin2bc with "base256"
$secp256k1 = new CurveFp(
'115792089237316195423570985008687907853269984665640564039457584007908834671663',
'0', '7');
$secp256k1_G = new Point($secp256k1,
'55066263022277343669578718895168534326250603453777594175500187360389116729240',
'32670510020758816978083085130507043184471273380659243275938904335757337482424',
'115792089237316195423570985008687907852837564279074904382605163141518161494337');
/* The hash I want to sign. */
$txHash = '9302bda273a887cb40c13e02a50b4071a31fd3aae3ae04021b0b843dd61ad18e';
$txHash = gmp_Utils::gmp_hexdec($txHash);
/* Private key to sign the hash with. */
$privKey = '18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725';
$privKey = gmp_Utils::gmp_hexdec($privKey);
// Wikipedia (http://en.wikipedia.org/wiki/Elliptic_Curve_DSA#Signature_generation_algorithm) -- public key = private key * G, the base point
$pubKey = new PublicKey($secp256k1_G, Point::mul($privKey, $secp256k1_G));
// check that the DER-encoded public key is what it's supposed to be -- not that this is necessarily correct DER encoding in general
assert(('04'.gmp_Utils::gmp_dechex($pubKey->getPoint()->getX()).gmp_Utils::gmp_dechex($pubKey->getPoint()->getY())) == '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6');
// the "secret multiplier" is just the private key value itself
$prvKey = new PrivateKey($pubKey, $privKey);
// I am not sure this is exactly the right range (could be off by 1 if inclusive), but this is what the ECC lib's test suite does so I assume it's correct.
// Unfortunately since this value is random and the StackExchange answer doesn't say what their k value was (it's generated by the OpenSSL lib they're using through Python), it's hard to verify exactly with the example
$k = gmp_Utils::gmp_random($secp256k1_G->getOrder());
$signature = $prvKey->sign($txHash, $k);
// verify the signature
assert($pubKey->verifies($txHash, $signature));
// verify with the DER-decoded signature given in the StackExchange answer -- if this also verifies it seems like a good sign we're on the right track (and it does, on my machine at least)
assert($pubKey->verifies($txHash, new Signature(gmp_Utils::gmp_hexdec('9e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa'), gmp_Utils::gmp_hexdec('bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc06'))));
/**
* The next steps involve DER/ASN.1 encoding, which I don't know much about, but here's some links I found:
*
* http://crypto.stackexchange.com/questions/1795/converting-a-der-ecdsa-signature-to-asn-1
* http://stackoverflow.com/questions/6272020/do-any-php-libraries-exist-for-parsing-asn-1-or-generating-php-code-based-on-it
* https://github.com/FGrosse/PHPASN1
* http://pumka.net/2009/12/19/reading-writing-and-converting-rsa-keys-in-pem-der-publickeyblob-and-privatekeyblob-formats/
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment