/** * Decompress Public Key * * Accepts a y_byte, 02 or 03 indicating whether the Y coordinate is * odd or even, and $passpoint, which is simply a hexadecimal X coordinate. * Using this data, it is possible to deconstruct the original * uncompressed public key. * * @param $key * @return array|bool */ public static function decompress_public_key($key) { $math = EccFactory::getAdapter(); $y_byte = substr($key, 0, 2); $x_coordinate = substr($key, 2); $x = self::hex_decode($x_coordinate); $theory = EccFactory::getNumberTheory($math); $generator = EccFactory::getSecgCurves($math)->generator256k1(); $curve = $generator->getCurve(); try { $x3 = $math->powmod($x, 3, $curve->getPrime()); $y2 = $math->add($x3, $curve->getB()); $y0 = $theory->squareRootModP($y2, $curve->getPrime()); if ($y0 == null) { throw new \InvalidArgumentException("Invalid public key"); } $y1 = $math->sub($curve->getPrime(), $y0); $y = $y_byte == '02' ? $math->mod($y0, 2) == '0' ? $y0 : $y1 : ($math->mod($y0, 2) !== '0' ? $y0 : $y1); $y_coordinate = str_pad($math->decHex($y), 64, '0', STR_PAD_LEFT); $point = $curve->getPoint($x, $y); } catch (\Exception $e) { throw new \InvalidArgumentException("Invalid public key"); } return array('x' => $x_coordinate, 'y' => $y_coordinate, 'point' => $point, 'public_key' => '04' . $x_coordinate . $y_coordinate); }