Created
May 23, 2014 01:44
-
-
Save afk11/a3f1174f30e1e8d9ed2d to your computer and use it in GitHub Desktop.
Decompress bitcoin public keys (PHP)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Decompressing a compressed bitcoin public key. | |
// Will require a big number library, with functions for modular exponent, square root (mod prime), and modulus. | |
// Requires gmp, and mathyass danters ecclib | |
public static function decompress_public_key($key) | |
{ | |
$y_byte = substr($key, 0, 2); | |
$x_coordinate = substr($key, 2); | |
// Convert x hexadecimal to a decimal | |
$x = gmp_strval(gmp_init($x_coordinate, 16),10); | |
$curve = \SECcurve::curve_secp256k1(); | |
$generator = \SECcurve::generator_secp256k1(); | |
try | |
{ | |
// x^3 % p | |
$x3 = \NumberTheory::modular_exp( $x, 3, $curve->getPrime() ); | |
// y^2 = x^3 + b | |
$y2 = gmp_add( | |
$x3, | |
$curve->getB() | |
); | |
// Solve for y: | |
// y = (x^3 + b)^(1/2) % p | |
$y0 = \NumberTheory::square_root_mod_prime( | |
gmp_strval($y2, 10), | |
$curve->getPrime() | |
); | |
// Could be another y. Prefix specifies if value is even or odd. | |
// y' = p - y | |
$y1 = gmp_strval(gmp_sub($curve->getPrime(), $y0), 10); | |
// if prefix is 02: | |
// if y%2 == 0: | |
// real_y = y | |
// else | |
// real_y = y' | |
// if prefix is 03: | |
// if y%2 !== 0: | |
// real_y = y | |
// else | |
// real_y = y' | |
$y_coordinate = ($y_byte == '02') | |
? ((\gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) == '0') ? $y0 : $y1) | |
: ((\gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) !== '0') ? $y0 : $y1); | |
// Convert the y coordinate to hex, and pad it to 64 characters. | |
$y_coordinate = str_pad(gmp_strval($y_coordinate, 16),64,'0',STR_PAD_LEFT); | |
// Instantiate a point based on curve, x coordinate, y coordinate, and order of the curve.. To test that the decompressed point is valid. | |
$point = new \Point($curve, gmp_strval(gmp_init($x_coordinate, 16),10), gmp_strval(gmp_init($y_coordinate, 16),10), $generator->getOrder()); | |
} | |
catch (\Exception $e) | |
{ | |
return FALSE; | |
} | |
return array( | |
'x' => $x_coordinate, | |
'y' => $y_coordinate, | |
'point' => $point, | |
'public_key' => '04'.$x_coordinate.$y_coordinate); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment