tMerge branch 'master' of git://gitorious.org/electrum/electrum - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 235088d83fd96df9f38d619d1be294181f7b0e8e DIR parent 14691ad9a85d778a08a3716a2315e46d4c521152 HTML Author: thomasv <thomasv@gitorious> Date: Wed, 22 Feb 2012 17:11:57 +0100 Merge branch 'master' of git://gitorious.org/electrum/electrum Diffstat: A client/remote.php | 24 ++++++++++++++++++++++++ A client/remote_wallet.py | 129 +++++++++++++++++++++++++++++++ D client/wdaemon.py | 112 ------------------------------- 3 files changed, 153 insertions(+), 112 deletions(-) --- DIR diff --git a/client/remote.php b/client/remote.php t@@ -0,0 +1,24 @@ +<? +require_once 'jsonrpcphp/includes/jsonRPCClient.php'; + +echo "<pre>\n"; +echo "This page demonstrates the generation of new addresses by a neutralized Electrum wallet.\n\n"; +echo "A neutralized wallet does not contain the seed that allows to generate private keys.\nIt contains a master public key that allows to create new addresses.\n\n"; +echo "An attacker getting access to the neutralized wallet cannot steal the bitcoins.\n"; +echo "The full wallet (with seed) is not stored on the webserver.\n\n"; +echo "<form action=\"\" method=\"post\"><input type=\"submit\" name=\"submit\" value=\"Get new address\"/></form> "; + +if($_POST['submit']) { + $daemon = new jsonRPCClient('http://foo:bar@ecdsa.org:8444/'); + try{ + $r = $daemon->getnewaddress(); + if($r) { + echo '<br/>'; + echo "<a href='bitcoin:$r'>bitcoin:$r</a>\n\n"; + } + } catch(Exception $e) { + echo "error: cannot reach wallet daemon"; + } +} +echo "</pre>"; +?> DIR diff --git a/client/remote_wallet.py b/client/remote_wallet.py t@@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# Electrum - lightweight Bitcoin client +# Copyright (C) 2011 thomasv@gitorious +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import time, thread, sys, socket + +# see http://code.google.com/p/jsonrpclib/ +import jsonrpclib +from wallet import Wallet +from interface import Interface + +""" +Simple wallet daemon for webservers. +- generates new addresses on request +- private keys are not needed in order to generate new addresses. A neutralized wallet can be used (seed removed) +- no gap limit: use 'getnum' to know how many addresses have been created. + +todo: +- return the max gap +- add expiration date + +""" + + +host = 'ecdsa.org' +port = 8444 +wallet_path = 'wallet_path' +username = 'foo' +password = 'bar' +interface = Interface() +wallet = Wallet(interface) +stopping = False + + + +from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCRequestHandler +import SimpleXMLRPCServer + +class authHandler(SimpleJSONRPCRequestHandler): + def parse_request(self): + if SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self): + if self.authenticate(self.headers): + return True + else: + self.send_error(401, 'Authentication failed') + return False + + def authenticate(self, headers): + from base64 import b64decode + basic, _, encoded = headers.get('Authorization').partition(' ') + assert basic == 'Basic', 'Only basic authentication supported' + x_username, _, x_password = b64decode(encoded).partition(':') + return username == x_username and password == x_password + + +def do_stop(): + global stopping + stopping = True + +def get_new_address(): + a = wallet.create_new_address(False) + wallet.save() + return a + +def get_num(): + return len(wallet.addresses) + +def get_mpk(): + return wallet.master_public_key.encode('hex') + + + +if __name__ == '__main__': + + if len(sys.argv)>1: + import jsonrpclib + server = jsonrpclib.Server('http://%s:%d'%(host,port)) + cmd = sys.argv[1] + + try: + if cmd == 'getnum': + out = server.getnum() + elif cmd == 'getkey': + out = server.getkey() + elif cmd == 'getnewaddress': + out = server.getnewaddress() + elif cmd == 'stop': + out = server.stop() + except socket.error: + print "server not running" + sys.exit(1) + print out + sys.exit(0) + + else: + + wallet.set_path(wallet_path) + wallet.read() + + def server_thread(): + from SocketServer import ThreadingMixIn + from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer + server = SimpleJSONRPCServer(( host, port), requestHandler=authHandler) + server.register_function(get_new_address, 'getnewaddress') + server.register_function(get_num, 'getnum') + server.register_function(get_mpk, 'getkey') + server.register_function(do_stop, 'stop') + server.serve_forever() + + thread.start_new_thread(server_thread, ()) + while not stopping: time.sleep(0.1) + + + + DIR diff --git a/client/wdaemon.py b/client/wdaemon.py t@@ -1,112 +0,0 @@ -#!/usr/bin/env python -# -# Electrum - lightweight Bitcoin client -# Copyright (C) 2011 thomasv@gitorious -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import time, thread, sys, socket - -# see http://code.google.com/p/jsonrpclib/ -import jsonrpclib -from wallet import Wallet -from interface import Interface - -""" -Simple wallet daemon for webservers. -- generates new addresses on request -- private keys are not needed in order to generate new addresses. A neutralized wallet can be used (seed removed) -- no gap limit: use 'getnum' to know how many addresses have been created. - -todo: -- return the max gap -- add expiration date - -""" - - -host = 'ecdsa.org' -port = 8444 -password = 'my_password' -wallet_path = 'wallet_path' - -interface = Interface() -wallet = Wallet(interface) -stopping = False - - -def do_stop(pw): - if pw != password: return False - global stopping - stopping = True - -def get_new_address(pw): - if pw != password: return False - a = wallet.create_new_address(False) - wallet.save() - return a - -def get_num(pw): - if pw != password: return False - return len(wallet.addresses) - -def get_mpk(pw): - if pw != password: return False - return wallet.master_public_key.encode('hex') - - - -if __name__ == '__main__': - - if len(sys.argv)>1: - import jsonrpclib - server = jsonrpclib.Server('http://%s:%d'%(host,port)) - cmd = sys.argv[1] - - try: - if cmd == 'getnum': - out = server.getnum(password) - elif cmd == 'getkey': - out = server.getkey(password) - elif cmd == 'getnewaddress': - out = server.getnewaddress(password) - elif cmd == 'stop': - out = server.stop(password) - except socket.error: - print "server not running" - sys.exit(1) - print out - sys.exit(0) - - else: - - wallet.set_path(wallet_path) - wallet.read() - - def server_thread(): - from SocketServer import ThreadingMixIn - from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer - server = SimpleJSONRPCServer(( host, port)) - server.register_function(get_new_address, 'getnewaddress') - server.register_function(get_num, 'getnum') - server.register_function(get_mpk, 'getkey') - server.register_function(do_stop, 'stop') - server.serve_forever() - - thread.start_new_thread(server_thread, ()) - while not stopping: time.sleep(0.1) - - - -