Browse Source

introducing signed aliases

283
thomasv 13 years ago
parent
commit
a590699d92
  1. 47
      client/gui.py
  2. 60
      client/wallet.py

47
client/gui.py

@ -588,7 +588,7 @@ class BitcoinGUI:
r = r.strip() r = r.strip()
if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r): if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
try: try:
to_address = self.wallet.get_alias(r) to_address = self.wallet.read_alias(r)[0]
except: except:
continue continue
if to_address: if to_address:
@ -807,22 +807,43 @@ class BitcoinGUI:
entry.set_text('') entry.set_text('')
def question(self,msg):
dialog = gtk.MessageDialog( self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg)
dialog.show()
result = dialog.run()
dialog.destroy()
return result == gtk.RESPONSE_OK
def get_alias(self, r): def get_alias(self, r):
try: try:
to_address = self.wallet.get_alias(r) target, signing_address, auth_name = self.wallet.read_alias(r)
except BaseException, e: except BaseException, e:
to_address = None # raise exception if verify fails (verify the chain)
msg = "Warning: the key corresponding to %s does not match its previously known value.\nDo you wish to accept the new key?"%r self.show_message("Alias error: " + e.message)
dialog = gtk.MessageDialog( self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg) return
dialog.show()
result = dialog.run()
dialog.destroy()
if result != gtk.RESPONSE_CANCEL:
print e.message
to_address = e.message
self.wallet.aliases[r] = to_address
return to_address if auth_name is None:
a = self.wallet.aliases.get(r)
if not a:
if self.question( "Warning: the alias is self-signed. Do you want to trust address %s ?"%to_address ):
self.wallet.aliases[r] = signing_address
else:
target = None
else:
if signing_address != a:
if self.question( "Warning: the signing key of %s does not match its previously known value! It is possible that someone is trying to do something nasty!!!\nDo you wish to accept the new key?"%r ):
self.wallet.aliases[r] = signing_address
else:
target = None
else:
if signing_address not in self.wallet.authorities.keys():
if self.question( "Warning: the alias '%s' was signed by %s [%s].\n\nDo you want to add this key to your list of trusted keys?"\
%(r,auth_name,signing_address)):
self.wallet.authorities[signing_address] = auth_name
else:
target = None
return target

60
client/wallet.py

@ -248,6 +248,8 @@ class Wallet:
self.history = {} self.history = {}
self.labels = {} # labels for addresses and transactions self.labels = {} # labels for addresses and transactions
self.aliases = {} # aliases for addresses self.aliases = {} # aliases for addresses
self.authorities = {} # trusted addresses
self.receipts = {} # signed URIs self.receipts = {} # signed URIs
self.receipt = None # next receipt self.receipt = None # next receipt
self.addressbook = [] # outgoing addresses, for payments self.addressbook = [] # outgoing addresses, for payments
@ -383,7 +385,7 @@ class Wallet:
order = G.order() order = G.order()
# extract r,s from signature # extract r,s from signature
sig = base64.b64decode(signature) sig = base64.b64decode(signature)
if len(sig) != 65: raise BaseException("error") if len(sig) != 65: raise BaseException("Wrong encoding")
r,s = util.sigdecode_string(sig[1:], order) r,s = util.sigdecode_string(sig[1:], order)
recid = ord(sig[0]) - 27 recid = ord(sig[0]) - 27
# 1.1 # 1.1
@ -407,7 +409,10 @@ class Wallet:
# check that we get the original signing address # check that we get the original signing address
addr = public_key_to_bc_address( '04'.decode('hex') + public_key.to_string() ) addr = public_key_to_bc_address( '04'.decode('hex') + public_key.to_string() )
# print addr # print addr
assert address == addr try:
assert address == addr
except:
raise BaseException("Bad signature")
def create_new_address2(self, for_change): def create_new_address2(self, for_change):
@ -489,6 +494,7 @@ class Wallet:
'contacts':self.addressbook, 'contacts':self.addressbook,
'imported_keys':self.imported_keys, 'imported_keys':self.imported_keys,
'aliases':self.aliases, 'aliases':self.aliases,
'authorities':self.authorities,
'receipts':self.receipts, 'receipts':self.receipts,
} }
f = open(self.path,"w") f = open(self.path,"w")
@ -521,6 +527,7 @@ class Wallet:
self.addressbook = d.get('contacts') self.addressbook = d.get('contacts')
self.imported_keys = d.get('imported_keys',{}) self.imported_keys = d.get('imported_keys',{})
self.aliases = d.get('aliases',{}) self.aliases = d.get('aliases',{})
self.authorities = d.get('authorities',{})
self.receipts = d.get('receipts',{}) self.receipts = d.get('receipts',{})
except: except:
raise BaseException(upgrade_msg) raise BaseException(upgrade_msg)
@ -724,34 +731,47 @@ class Wallet:
self.receipt = None self.receipt = None
return True, out return True, out
def get_alias(self, x):
def read_alias(self, alias):
# this might not be the right place for this function. # this might not be the right place for this function.
import urllib import urllib
if self.is_valid(x): if self.is_valid(alias):
return x return alias
else: else:
m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', x) m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', alias)
m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', x) m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', alias)
if m1: if m1:
url = 'http://' + m1.group(2) + '/bitcoin.id/' + m1.group(1) url = 'http://' + m1.group(2) + '/bitcoin.id/' + m1.group(1)
elif m2: elif m2:
url = 'http://' + x + '/bitcoin.id' url = 'http://' + alias + '/bitcoin.id'
else: else:
return '' return ''
try: try:
print url lines = urllib.urlopen(url).readlines()
xx = urllib.urlopen(url).read().strip()
except: except:
return '' return ''
if not self.is_valid(xx):
return ''
self.labels[xx] = x
s = self.aliases.get(x) # line 0
if s: line = lines[0].strip().split(':')
if s != xx: if len(line) == 1:
raise BaseException( xx ) auth_name = None
target = signing_addr = line[0]
else: else:
self.aliases[x] = xx target, auth_name, signing_addr, signature = line
msg = "alias:%s:%s:%s"%(alias,target,auth_name)
return xx print msg, signature
self.verify_message(signing_addr, signature, msg)
# other lines are signed updates
for line in lines[1:]:
line = line.strip()
if not line: continue
line = line.split(':')
previous = target
print repr(line)
target, signature = line
self.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
assert self.is_valid(target)
return target, signing_addr, auth_name

Loading…
Cancel
Save