Author

Topic: bitcoind - send btc's without storing the privatekey of a wallet permanently (Read 6122 times)

sr. member
Activity: 412
Merit: 287
That makes sense, your wallet will only cares about transactions that it's signature verification process realizes it's to do with one of your private keys, rather than payments to arbitrary addresses.

So you're right, it's only the signing process does not need the key to be in the wallet.

What type of service are you hoping to build?

I scan all transactions in a block when a new one is published, and log payments to addresses that I care about whenever they're encountered in a block. The process is quite quick, I have a library to do the deserialization rather than asking bitcoind to decode it.

In my programs flow, I store the address, and the purpose, so whenever a payment is received on that address it triggers a function to deal with that. So if a payment is received on an 'order' address, that function checks if sufficient payments on that address have been logged, and then it creates the raw transaction.

But it depends, why do you want to even consider submitting a private key at any stage? If the concern is leaving it on the servers wallet, it's not lessened a huge amount by only using it once.
newbie
Activity: 8
Merit: 0
You can do what you describe once you do it all with raw transactions, and if you run a full node (txindex=1)

So: you have an unsigned transaction, and a private key. You do not wish to save the private key to the wallet.

Decode the raw transaction, loop through the TxIn's.
 - Do decoderawtransaction(getrawtransaction()) on each txid/vout, and then obtain the scriptPubKey for that specific output. You need an array, which has a child array containing (txid, vout, scriptPubKey) for each input.

Now you have the raw transaction and the inputs. You are supplying a WIF private key, so this needs to be put into an array in your application (not directly as a string).

This example in PHP assumes you have a full node, and $btc - a jsonrpcclient object connected to a bitcoin daemon.

Code:
$raw_tx = 'your unsigned raw transaction';
$decode = $btc->decoderawtransaction($raw_tx);

// Build inputs - a full node can get/decode arbitrary transactions
$inputs = array();
foreach($decode['vin'] as $vout => $txin) {
    $old_txn = $btc->decoderawtransaction($btc->getrawtransaction($txin['txid']));
    $scriptPubKey = $old_txn['vout'][$txin['vout']]['scriptPubKey'];
    $inputs[] = array('txid' => $txin['txid'], 'vout' => $vout, 'scriptPubKey' => $scriptPubKey);
}

// Build privkeys array.
$privKeys = array('5L...........');

$sign = $btc->signrawtransaction($raw_tx, $inputs, $privKeys);

I'm sorry I didn’t know that this thread could be interesting for somebody, but now I'm back:
@fbueller: thanks for your help, but before I can setup a raw transaction process I have to get the latest "unspent coins" right?
Example:
Code:
$btc->listunspent(); //gives me the txIds, vout and scriptPubKey witch are required by the raw-transaction functions
//now I can call the several rawtransfer-functions to initiate a raw transaction, just like your code is doing that

But, listunspent gives me always a blank result unless I have imported the private key of an address and assigned that to an account. Here is my problem.

I've already tried to submit an address without the private key with:
Code:
$btc->setaccount('MYADDRESS', 'nameofmyAccount');
But the listunspent() always gave me a blank result. Maybe I doing something wrong, but in my opinion it is always required to import the private key right?


Unfortunately bitcoind will not tell you if the key was invalid. $sign contains a 'complete' index, which only changes from false -> true when the transaction is FULLY signed.


Why do you want to do signing on the server side? This means you're assuming full control of the coins, or asking people to divulge private keys. You could write a nice JS solution where they just enter a passphrase, which is converted to a seed, and you have them derive a particular key. then they sign client side and submit the transaction to you?

What are you hoping to write?
Well a seed-key-solution could be a good try. Now I'm still fighting with the bitcoind json-rpc-api key management is far away.
sr. member
Activity: 412
Merit: 287
You can do what you describe once you do it all with raw transactions, and if you run a full node (txindex=1)

So: you have an unsigned transaction, and a private key. You do not wish to save the private key to the wallet.

Decode the raw transaction, loop through the TxIn's.
 - Do decoderawtransaction(getrawtransaction()) on each txid/vout, and then obtain the scriptPubKey for that specific output. You need an array, which has a child array containing (txid, vout, scriptPubKey) for each input.

Now you have the raw transaction and the inputs. You are supplying a WIF private key, so this needs to be put into an array in your application (not directly as a string).

This example in PHP assumes you have a full node, and $btc - a jsonrpcclient object connected to a bitcoin daemon.

Code:
$raw_tx = 'your unsigned raw transaction';
$decode = $btc->decoderawtransaction($raw_tx);

// Build inputs - a full node can get/decode arbitrary transactions
$inputs = array();
foreach($decode['vin'] as $vout => $txin) {
    $old_txn = $btc->decoderawtransaction($btc->getrawtransaction($txin['txid']));
    $scriptPubKey = $old_txn['vout'][$txin['vout']]['scriptPubKey'];
    $inputs[] = array('txid' => $txin['txid'], 'vout' => $vout, 'scriptPubKey' => $scriptPubKey);
}

// Build privkeys array.
$privKeys = array('5L...........');

$sign = $btc->signrawtransaction($raw_tx, $inputs, $privKeys);

Unfortunately bitcoind will not tell you if the key was invalid. $sign contains a 'complete' index, which only changes from false -> true when the transaction is FULLY signed.


Why do you want to do signing on the server side? This means you're assuming full control of the coins, or asking people to divulge private keys. You could write a nice JS solution where they just enter a passphrase, which is converted to a seed, and you have them derive a particular key. then they sign client side and submit the transaction to you?

What are you hoping to write?
cp1
hero member
Activity: 616
Merit: 500
Stop using branwallets
You're right, better to just give up.
newbie
Activity: 8
Merit: 0
You could use another client and sweep the key.  Or use something like sx and do it yourself.
I tried the (no longer supported) Armory-daemon which got 4(!) methods.
https://github.com/thedawnrider/BitcoinArmory-Daemon


I don't know what do you mean with 'sx' but the primary question is whether it's worth the work. How long Bitcoin can exists with such fundamental flaws (no persistence password/key storage is the first security rule since the 70's) of it's current clients plus their high worth volatility of bitcoins?
cp1
hero member
Activity: 616
Merit: 500
Stop using branwallets
You could use another client and sweep the key.  Or use something like sx and do it yourself.
newbie
Activity: 8
Merit: 0
Hello,

I tried both the abstracted sendfrom and the low level raw-functions. But both requiring an permanent import of a wallet including its privatekey even the raw functions.
The reason for that is the required 'scriptPubKey' which can be only obtained if you imported the wallet which should be work as a sender in a transfer first.

Well it looks like the permanent storage of the private key in order to import a wallet is still a problem.
However it would not be a problem if it would be possible to delete a wallet after the work (like sending some btc's) is done. But that feature has been (as I already mentioned) removed.

Sure I don’t have any proves but maybe this problem caused some close-downs of several bitcoin market-places in the past. I mean if somebody knows what is stored in a wallet.dat-file and got a key for it's decryption as well (like an employee), he/her is rich.
cp1
hero member
Activity: 616
Merit: 500
Stop using branwallets
Be really careful you don't mess up the change and send it as a fee instead.
newbie
Activity: 8
Merit: 0
Thanks Abdussamad
that’s exactly what I need.  Grin
legendary
Activity: 3682
Merit: 1580
You can use the createrawtransaction and signrawtransaction commands with your own private key. Check the wiki:

https://en.bitcoin.it/wiki/Raw_Transactions
newbie
Activity: 8
Merit: 0
However, to spend bitcoins you need the private key to sign the transaction. No way around that. People try various arrangements like a dedicated transaction signing server behind a firewall. It's not exactly budget friendly for small operations.
Thanks for your advice with the transaction signing server.

Nevertheless, it must be said that the permanent storing of private-keys is just another potentially security flaw (in general). It is comparable with the saved passwords in a web-browser (
I don't think that this should be our goal).

It would be a good approach to give the developers an Json-RPC function which requires something like:
- the public/wallet
- private key
- amount of BTC's
- receiver
- etc.

This would give the developers the possibility to store their private-keys how they want, and prevents the need to import (to store the private-key of a wallet in other words) a wallet first before you send some btc's from that to someone else.

Hopefully this reads a higher-ranked BTC-developer.
cp1
hero member
Activity: 616
Merit: 500
Stop using branwallets
You could use another client and sweep the key.  Or use something like sx and do it yourself.
legendary
Activity: 3682
Merit: 1580
It is possible to receive bitcoins without having the private key. You just need the address. You can store large amounts of pre-generated addresses in a database and hand them out one by one or you can generate them deterministically.

However, to spend bitcoins you need the private key to sign the transaction. No way around that. People try various arrangements like a dedicated transaction signing server behind a firewall. It's not exactly budget friendly for small operations.
newbie
Activity: 8
Merit: 0
Hello,
as you can see in it's subject, I try to find a way to send/receive btc's using the bitcoind via the JSON-RPC-API without storing the private-key.
Now all private keys will be stored in the wallet.dat file and could not be removed after an action is done. Well it is possible to shut-down the bitcoind and delete the wallet.dat file, but this is a very unclean solution.
Sure, it is possible to encrypt the wallet.dat but this requires a save way to store it's 'master key' which is not an easy task if you’re using an interpreter-language (which are very common in the web-development) or a web-server which is potentially vulnerable.

The possibility of delete private keys was available until 0.6.0 (https://en.bitcoin.it/wiki/How_to_import_private_keys) came out, but what was the reason for that 'wise' idea?
Is there a better way to send/receive amounts of btc's on the fly without storing the private-key of a wallet permanently and it is not yet listed in the API list(https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list )?


Best Regards
Jump to: