Importing of Private Keys
Hello Johnathan,
well, this is not really an issue, but somehow i do not get how to create a pull request.
I implemented the feature, that you can import private keys to your wallet. This is kind of a quick-shot solution. Error handling and internationalization can be improved. But i saw private key handling is on your todo list, and this would be a part of it
To view/wallet.php i added the following between WALLET_SUPPORT and WALLET_2FAON, so the button is show on the top of your wallet between the support button and the enable 2FA button:
<form action="index.php" method="POST">
<input type="hidden" name="action" value="enterprivkey" />
<button type="submit" class="btn btn-default"><?php echo $lang['WALLET_ENTER_PRIVKEY']; ?> </button>
</form>
to index.php i added this to the switch($_POST['action']):
// this part shows an input and a button at the top of the site to insert your private keys
case "enterprivkey":
$user = new User($mysqli);
$enterprivkey = $user->enterPrivKey();
echo $enterprivkey;
break;
// this part is handling the click on the submit button from the above code
case "submitprivkey":
if(empty($_POST['privkey'])) {
$error['message'] = "No private keys submitted!";
break;
}
$privkey = $_POST['privkey'];
// check length and check for valid characters depends on your *coind implementation.
// this would be better to be checked by the *coind daemon,
// since it checks them also and completely skip the checks here
// check length
if(strlen($privkey) !== 52) {
$error['message'] = "Length of private key is wrong: ". strval(strlen($privkey)) .". Has to be 52!";
break;
}
// check for valid characters
for($i = 0; $i < strlen($privkey); $i++) {
// valid characters are between 0 and 9 and between a and f
if($privkey[$i] < "0" || $privkey[$i] > "9") {
if(strtolower($privkey[$i]) < "a" || strtolower($privkey[$i]) > "z") {
$error['message'] = "Invalid characters are in the private key!";
break;
}
}
}
$result = $client->importPrivateKey($user_session, $privkey);
$r = json_decode($result);
if($r->{'error'} == null) {
$error['message'] = "Successfully added a Private Key to your wallet. It can take a while that it appears in your wallet since the network has to verify your action.";
} else {
$error['message'] = $r->{'error'}->{'message'};
}
break;
At the end of classes/Client.php i added this:
function importPrivateKey($user_session, $private_key) {
return $this->jsonrpc->importprivkey($private_key, "zelles(" . $user_session . ")");
}
This function i added to classes/User.php
function enterPrivKey() {
$htmlcode = '
<form action="index.php" method="POST"method="POST" id="enterprivkeyform">
<input type="hidden" name="action" value="submitprivkey" />
<input type="text" name="privkey" placeholder="Private Key" />
<button type="submit" class="btn btn-default">Submit</button>
</form>';
return $htmlcode;
}
The change of jsonRPCClient.php was the toughest part. Since your code always resulted in a http error 500 when sending importprivkey, i had to use php-curl to call the *coind daemon. Maybe it is better so switch completely to php-curl because the error handling is much better and options can easier be set, than with fopen. So i enhanced the function __call by the following:
public function __call($method,$params) {
/* ... your code ... */
// my code handling "importprivkey"
if($method === "importprivkey") {
$privkey = $params[0];
$account = $params[1];
$rescan = "true";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // enable return as string
curl_setopt($curl, CURLOPT_POST, 1); // enable post
curl_setopt($curl, CURLOPT_POSTFIELDS, '{"jsonrpc":"1.0","method":"importprivkey","params":["'.$privkey.'", "'.$account.'", true]}'); // enable post fiels
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); // set content-type
$result = curl_exec($curl);
return $result;
} else {
// your old code handling all the other methods
if ($fp = fopen($this->url, 'r', false, $context)) {
$response = '';
while($row = fgets($fp)) {
$response.= trim($row)."\n";
}
$this->debug && $debug.='***** Server response *****'."\n".$response.'***** End of server response *****'."\n";
$response = json_decode($response,true);
} else {
throw new Exception('Unable to connect to '.$this->url);
}
}
/* ... again your code ... */
}
Hope this helps, Gottfried, servus.at
Thank you, I'll be reviewing this and will commit to master.
A user's private key should never go in here without additional strong protections, such as encrypting the key properly in the database.
As a general rule: not your key, not your coins. Same for sharing it. Sometimes when there is no other option you just have enough coins you can lose on a web wallet.
The user can just spend to their Web wallet and dispense with importing private keys.