Skip to content
This repository has been archived by the owner on Apr 8, 2023. It is now read-only.

Importing of Private Keys #72

Open
muwaka opened this issue Jun 22, 2018 · 2 comments
Open

Importing of Private Keys #72

muwaka opened this issue Jun 22, 2018 · 2 comments
Labels

Comments

@muwaka
Copy link

muwaka commented Jun 22, 2018

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

@jfm-so
Copy link
Owner

jfm-so commented Aug 2, 2018

Thank you, I'll be reviewing this and will commit to master.

@jfm-so jfm-so added the todo label Aug 2, 2018
@auscash
Copy link

auscash commented Aug 16, 2019

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants