298 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
| <?php
 | |
| 
 | |
| // simple santization function to accept only alphanumeric characters
 | |
| function san($a, $b = "")
 | |
| {
 | |
|     $a = preg_replace("/[^a-zA-Z0-9".$b."]/", "", $a);
 | |
| 
 | |
|     return $a;
 | |
| }
 | |
| 
 | |
| function san_ip($a)
 | |
| {
 | |
|     $a = preg_replace("/[^a-fA-F0-9\[\]\.\:]/", "", $a);
 | |
|     return $a;
 | |
| }
 | |
| 
 | |
| function san_host($a)
 | |
| {
 | |
|     $a = preg_replace("/[^a-zA-Z0-9\.\-\:\/]/", "", $a);
 | |
|     return $a;
 | |
| }
 | |
| 
 | |
| // api  error and exit
 | |
| function api_err($data)
 | |
| {
 | |
|     global $_config;
 | |
|     echo json_encode(["status" => "error", "data" => $data, "coin" => $_config['coin']]);
 | |
|     exit;
 | |
| }
 | |
| 
 | |
| // api print ok and exit
 | |
| function api_echo($data)
 | |
| {
 | |
|     global $_config;
 | |
|     echo json_encode(["status" => "ok", "data" => $data, "coin" => $_config['coin']]);
 | |
|     exit;
 | |
| }
 | |
| 
 | |
| // log function, shows only in cli atm
 | |
| function _log($data, $verbosity = 0)
 | |
| {
 | |
|     global $_config;
 | |
|     if ($_config['log_verbosity'] < $verbosity) {
 | |
|         return;
 | |
|     }
 | |
|     $date = date("[Y-m-d H:i:s]");
 | |
|     $trace = debug_backtrace();
 | |
|     $loc = count($trace) - 1;
 | |
|     $file = substr($trace[$loc]['file'], strrpos($trace[$loc]['file'], "/") + 1);
 | |
| 
 | |
|     $res = "$date ".$file.":".$trace[$loc]['line'];
 | |
| 
 | |
|     if (!empty($trace[$loc]['class'])) {
 | |
|         $res .= "---".$trace[$loc]['class'];
 | |
|     }
 | |
|     if (!empty($trace[$loc]['function']) && $trace[$loc]['function'] != '_log') {
 | |
|         $res .= '->'.$trace[$loc]['function'].'()';
 | |
|     }
 | |
|     $res .= " $data \n";
 | |
|     if (php_sapi_name() === 'cli') {
 | |
|         echo $res;
 | |
|     }
 | |
|     if ($_config['enable_logging'] == true && $_config['log_verbosity'] >= $verbosity) {
 | |
|         @file_put_contents($_config['log_file'], $res, FILE_APPEND);
 | |
|     }
 | |
| }
 | |
| 
 | |
| // converts PEM key to hex
 | |
| function pem2hex($data)
 | |
| {
 | |
|     $data = str_replace("-----BEGIN PUBLIC KEY-----", "", $data);
 | |
|     $data = str_replace("-----END PUBLIC KEY-----", "", $data);
 | |
|     $data = str_replace("-----BEGIN EC PRIVATE KEY-----", "", $data);
 | |
|     $data = str_replace("-----END EC PRIVATE KEY-----", "", $data);
 | |
|     $data = str_replace("\n", "", $data);
 | |
|     $data = base64_decode($data);
 | |
|     $data = bin2hex($data);
 | |
|     return $data;
 | |
| }
 | |
| 
 | |
| // converts hex key to PEM
 | |
| function hex2pem($data, $is_private_key = false)
 | |
| {
 | |
|     $data = hex2bin($data);
 | |
|     $data = base64_encode($data);
 | |
|     if ($is_private_key) {
 | |
|         return "-----BEGIN EC PRIVATE KEY-----\n".$data."\n-----END EC PRIVATE KEY-----";
 | |
|     }
 | |
|     return "-----BEGIN PUBLIC KEY-----\n".$data."\n-----END PUBLIC KEY-----";
 | |
| }
 | |
| 
 | |
| 
 | |
| // Base58 encoding/decoding functions - all credits go to https://github.com/stephen-hill/base58php
 | |
| function base58_encode($string)
 | |
| {
 | |
|     $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 | |
|     $base = strlen($alphabet);
 | |
|     // Type validation
 | |
|     if (is_string($string) === false) {
 | |
|         return false;
 | |
|     }
 | |
|     // If the string is empty, then the encoded string is obviously empty
 | |
|     if (strlen($string) === 0) {
 | |
|         return '';
 | |
|     }
 | |
|     // Now we need to convert the byte array into an arbitrary-precision decimal
 | |
|     // We basically do this by performing a base256 to base10 conversion
 | |
|     $hex = unpack('H*', $string);
 | |
|     $hex = reset($hex);
 | |
|     $decimal = gmp_init($hex, 16);
 | |
|     // This loop now performs base 10 to base 58 conversion
 | |
|     // The remainder or modulo on each loop becomes a base 58 character
 | |
|     $output = '';
 | |
|     while (gmp_cmp($decimal, $base) >= 0) {
 | |
|         list($decimal, $mod) = gmp_div_qr($decimal, $base);
 | |
|         $output .= $alphabet[gmp_intval($mod)];
 | |
|     }
 | |
|     // If there's still a remainder, append it
 | |
|     if (gmp_cmp($decimal, 0) > 0) {
 | |
|         $output .= $alphabet[gmp_intval($decimal)];
 | |
|     }
 | |
|     // Now we need to reverse the encoded data
 | |
|     $output = strrev($output);
 | |
|     // Now we need to add leading zeros
 | |
|     $bytes = str_split($string);
 | |
|     foreach ($bytes as $byte) {
 | |
|         if ($byte === "\x00") {
 | |
|             $output = $alphabet[0].$output;
 | |
|             continue;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     return (string)$output;
 | |
| }
 | |
| 
 | |
| function base58_decode($base58)
 | |
| {
 | |
|     $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 | |
|     $base = strlen($alphabet);
 | |
| 
 | |
|     // Type Validation
 | |
|     if (is_string($base58) === false) {
 | |
|         return false;
 | |
|     }
 | |
|     // If the string is empty, then the decoded string is obviously empty
 | |
|     if (strlen($base58) === 0) {
 | |
|         return '';
 | |
|     }
 | |
|     $indexes = array_flip(str_split($alphabet));
 | |
|     $chars = str_split($base58);
 | |
|     // Check for invalid characters in the supplied base58 string
 | |
|     foreach ($chars as $char) {
 | |
|         if (isset($indexes[$char]) === false) {
 | |
|             return false;
 | |
|         }
 | |
|     }
 | |
|     // Convert from base58 to base10
 | |
|     $decimal = gmp_init($indexes[$chars[0]], 10);
 | |
|     for ($i = 1, $l = count($chars); $i < $l; $i++) {
 | |
|         $decimal = gmp_mul($decimal, $base);
 | |
|         $decimal = gmp_add($decimal, $indexes[$chars[$i]]);
 | |
|     }
 | |
|     // Convert from base10 to base256 (8-bit byte array)
 | |
|     $output = '';
 | |
|     while (gmp_cmp($decimal, 0) > 0) {
 | |
|         list($decimal, $byte) = gmp_div_qr($decimal, 256);
 | |
|         $output = pack('C', gmp_intval($byte)).$output;
 | |
|     }
 | |
|     // Now we need to add leading zeros
 | |
|     foreach ($chars as $char) {
 | |
|         if ($indexes[$char] === 0) {
 | |
|             $output = "\x00".$output;
 | |
|             continue;
 | |
|         }
 | |
|         break;
 | |
|     }
 | |
|     return $output;
 | |
| }
 | |
| 
 | |
| // converts PEM key to the base58 version used by ARO
 | |
| function pem2coin($data)
 | |
| {
 | |
|     $data = str_replace("-----BEGIN PUBLIC KEY-----", "", $data);
 | |
|     $data = str_replace("-----END PUBLIC KEY-----", "", $data);
 | |
|     $data = str_replace("-----BEGIN EC PRIVATE KEY-----", "", $data);
 | |
|     $data = str_replace("-----END EC PRIVATE KEY-----", "", $data);
 | |
|     $data = str_replace("\n", "", $data);
 | |
|     $data = base64_decode($data);
 | |
| 
 | |
| 
 | |
|     return base58_encode($data);
 | |
| }
 | |
| 
 | |
| // converts the key in base58 to PEM
 | |
| function coin2pem($data, $is_private_key = false)
 | |
| {
 | |
|     $data = base58_decode($data);
 | |
|     $data = base64_encode($data);
 | |
| 
 | |
|     $dat = str_split($data, 64);
 | |
|     $data = implode("\n", $dat);
 | |
| 
 | |
|     if ($is_private_key) {
 | |
|         return "-----BEGIN EC PRIVATE KEY-----\n".$data."\n-----END EC PRIVATE KEY-----\n";
 | |
|     }
 | |
|     return "-----BEGIN PUBLIC KEY-----\n".$data."\n-----END PUBLIC KEY-----\n";
 | |
| }
 | |
| 
 | |
| // sign data with private key
 | |
| function ec_sign($data, $key)
 | |
| {
 | |
|     // transform the base58 key format to PEM
 | |
|     $private_key = coin2pem($key, true);
 | |
| 
 | |
| 
 | |
|     $pkey = openssl_pkey_get_private($private_key);
 | |
| 
 | |
|     $k = openssl_pkey_get_details($pkey);
 | |
| 
 | |
| 
 | |
|     openssl_sign($data, $signature, $pkey, OPENSSL_ALGO_SHA256);
 | |
| 
 | |
|     // the signature will be base58 encoded
 | |
|     return base58_encode($signature);
 | |
| }
 | |
| 
 | |
| 
 | |
| function ec_verify($data, $signature, $key)
 | |
| {
 | |
|     // transform the base58 key to PEM
 | |
|     $public_key = coin2pem($key);
 | |
| 
 | |
|     $signature = base58_decode($signature);
 | |
| 
 | |
|     $pkey = openssl_pkey_get_public($public_key);
 | |
| 
 | |
|     $res = openssl_verify($data, $signature, $pkey, OPENSSL_ALGO_SHA256);
 | |
| 
 | |
| 
 | |
|     if ($res === 1) {
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| // POST data to an URL (usualy peer). The data is an array, json encoded with is sent as $_POST['data']
 | |
| function peer_post($url, $data = [], $timeout = 60, $debug = false)
 | |
| {
 | |
|     global $_config;
 | |
|     if ($debug) {
 | |
|         echo "\nPeer post: $url\n";
 | |
|     }
 | |
|     $postdata = http_build_query(
 | |
|         [
 | |
|             'data' => json_encode($data),
 | |
|             "coin" => $_config['coin'],
 | |
|         ]
 | |
|     );
 | |
| 
 | |
|     $opts = [
 | |
|         'http' =>
 | |
|             [
 | |
|                 'timeout' => $timeout,
 | |
|                 'method'  => 'POST',
 | |
|                 'header'  => 'Content-type: application/x-www-form-urlencoded',
 | |
|                 'content' => $postdata,
 | |
|             ],
 | |
|     ];
 | |
| 
 | |
|     $context = stream_context_create($opts);
 | |
| 
 | |
|     $result = file_get_contents($url, false, $context);
 | |
|     if ($debug) {
 | |
|         echo "\nPeer response: $result\n";
 | |
|     }
 | |
|     $res = json_decode($result, true);
 | |
| 
 | |
|     // the function will return false if something goes wrong
 | |
|     if ($res['status'] != "ok" || $res['coin'] != $_config['coin']) {
 | |
|         return false;
 | |
|     }
 | |
|     return $res['data'];
 | |
| }
 | |
| 
 | |
| // convers hex to base58
 | |
| function hex2coin($hex)
 | |
| {
 | |
|     $data = hex2bin($hex);
 | |
|     return base58_encode($data);
 | |
| }
 | |
| 
 | |
| // converts base58 to hex
 | |
| function coin2hex($data)
 | |
| {
 | |
|     $bin = base58_decode($data);
 | |
|     return bin2hex($bin);
 | |
| }
 | 
