def import_contact(c, interactive=True): try: if isinstance(c, bytes): c = json.loads(c.decode('utf-8')) if interactive: print('Import this contact?') print('Peers:') for k, v in c['peers'].items(): print('*', format_nickname(cryptutil.hash(cryptutil.import_key(k)))) if v != None: print(' (@%s)' % v) if k in c['trusted']: print(' (trusted)') print('Sockets:') for x in c['sockets']: print('*', x) print('Relays:') for k, v in c['relays'].items(): print('* %s via %s' % (format_nickname(k), format_nickname(v))) print('Exclusive routes:') for k, v in c['exclusive'].items(): print('* %s excl. via %s' % (format_nickname(k), v)) try: input('Press Enter to continue, Ctrl+C to abort') except KeyboardInterrupt: return for k, v in c['peers'].items(): config['peers'][cryptutil.hash(cryptutil.import_key(k))] = k if v != None: config['nicknames'][cryptutil.hash( cryptutil.import_key(k))] = v if cryptutil.hash(cryptutil.import_key(k)) in c['trusted']: config['trusted'].append( cryptutil.hash(cryptutil.import_key(k))) for x in c['sockets']: if x not in config['sockets']: start_peer_socket(x) config['sockets'].append(x) config['relays'].update(c['relays']) config['exclusive'].update(c['exclusive']) update_config() except: print('Error during contact import:', file=sys.stderr) sys.excepthook(*sys.exc_info())
def mb_encrypt(rec, idx, msg): if idx != None: saved_msgs[idx.decode('ascii', 'replace')] = msg if rec in config['peers']: signed = cryptutil.sign(self.encode('ascii') + b'\0' + msg, privkey) if idx != None: saved_msgs[idx.decode('ascii', 'replace')] = b'SIGNED\0' + signed msg = b'eMSG\0' + rec.encode('ascii') + b'\0' + cryptutil.encrypt( signed, cryptutil.import_key(config['peers'][rec]), 'e') return msg
BOT_KEY = 'MIICXAIBAAKBgQDDSRdeGz7KsA+KYbP9e/T741RWphm8gEH1CAulYQULItkrHPy51kufXdmK+j7ToTzOCUOHhBcSBqOgLsH/bpL9K7HY9WIlUjn0D522Sl1Jn6uSTrO3nWGBioPqRFPlxERZIKEj5A+tLS2Rlge9hLHUes3SRpx0vVb/VpEJlKGwAQIDAQABAoGAE6WrYa7pCthav+fjhWmutJbi+dK9PR9EQ4Q7M7jGmp+3bKR+cq3yLsbw55AUuRL8PJhnAF/UOF6NoMSDhRDZXc034++ZfFrNbCitZuDIl4/f0Ue7jpDec00ob8V/qsWDeBuy7/QL/Xdk3gwahx/SpUp5ma1rcj7SQEDKrGJrwAkCQQDU+cWP0ZCP3Y8xdSVYieEBA2mgpyaYH46KSqf1wdQUIWV0UyAnj1L0lq0Mv6PV7EzU8ZOPwwPRRI+p8nHM1T79AkEA6rx1BoCHPI4rrE2pkpYlpWDjN897PfFvyKd9NWnkmpkdScMlpsy+BzCMopLtxrKKG9F79jB7m72tCY17r6S+VQJAMFKz5tvv5xSoZtpjrOEr8mTp1I/Yi++tEee6kGJ4UlD5ihlKVG+KrQB7J0dcTy+chzyA9L+U4CikSDVAaO+BqQJBALm6LyXb4CTroGaOdFNFdbfqdx2bjrmuJHIxA4KVrIkeCOxp+YqGiPyLT1r6wiPq9BeaomhiaAsMArOCPJD22pkCQAWB6kQFWXRWwztpFeKR2i6gal7xKT9iFwuho5dKL+7pNOJb46hxG6zcf3hzgUgK/goU7Gn7f8nz75MxTPgWSEk=' import cryptutil, queue, os bot_key = cryptutil.import_key(BOT_KEY) bot_hash = cryptutil.hash(bot_key.publickey()) known_keys = {} known_pkts = set() known_msgs = set() class TheSocket: def __init__(self): self.queue = queue.Queue() def recv(self, x): return self.queue.get() def send_encrypted_back(self, sndr, x): sndr1 = sndr.decode('ascii', 'replace') self.queue.put(os.urandom(8).hex().encode('ascii')+b'\0eMSG\0'+sndr+b'\0'+cryptutil.encrypt(cryptutil.sign(bot_hash.encode('ascii')+b'\0'+x, bot_key), known_keys[sndr1], 'e')) def sendall(self, x): try: msgid, tp, dat0 = x.split(b'\0', 2) if msgid in known_pkts: return known_pkts.add(msgid) if tp == b'eMSG': tgt, dat = dat0.split(b'\0', 1) if tgt == bot_hash.encode('ascii'): dat2 = cryptutil.decrypt(dat, bot_key, 'd') sndr, tp2, dat3 = dat2.split(b'\0', 2) if tp2 == b'MSG': msgid2, rec, sndr2, tp3, dat4 = dat3.split(b'\0', 4)
import json, sys, cryptutil, base64 data = open(sys.argv[1]).read().split('\n') assert data[0].startswith('BOT_KEY = ') bot_key = eval(data[0][10:]) bot_id = cryptutil.hash(cryptutil.import_key(bot_key).publickey()) if '--devel' in sys.argv: path = repr(os.path.abspath(sys.argv[1])) data = ('exec(compile(open(' + path + ', "rb").read(), ' + path + ', "exec"))').encode('utf-8') else: data = open(sys.argv[1], 'rb').read() sock = 'python://' + ''.join(base64.b64encode(data).decode('ascii').split()) print( json.dumps({ 'peers': { cryptutil.export_key(cryptutil.import_key(bot_key).publickey()): sys.argv[2] }, 'trusted': [bot_id], 'sockets': [sock], 'relays': {}, 'exclusive': { bot_id: sock } }))
def handle_packet(msg, flags=0, verified_as=None, sender=None): if flags & F_FORWARDED: flags |= F_RELAYED idx, tp, dat = msg.split(b'\0', 2) if idx in pkt_cache: return pkt_cache.add(idx) # print('[relayed=%r][verified=%r][forwarded=%r] %r'%(bool(flags&F_RELAYED), bool(flags&F_VERIFIED), bool(flags&F_FORWARDED), msg)) if tp == b'EMSG': # if not (flags & F_EMSG_NOFORWARD): print('true EMSG! hi anonymity!') dat0 = cryptutil.decrypt(dat, privkey, 'd') if flags & F_EMSG_NOFORWARD: flags &= ~F_EMSG_NOFORWARD else: send_pkt(msg) if dat0 == None: return #not for our eyes snd, dat = dat0[:-128].split(b'\0', 1) snd = snd.decode('ascii', 'replace') if snd not in config['peers']: tp0, dat0 = dat.split(b'\0', 1) if tp0 == b'MSG': idx1, rec1, snd1, tp1, dat1 = dat0.split(b'\0', 4) if tp1 == b'KEY': # print('key is:', dat1) key = cryptutil.import_binary_key(dat1) # print('from %r: got key of %r'%(snd, cryptutil.hash(key))) config['peers'][cryptutil.hash( key)] = cryptutil.export_key(key) update_config() elif tp0 == b'ACK': return if snd not in config['peers']: send_msg(snd, b'NEEDKEY\0') return if not cryptutil.check_sign( dat0, cryptutil.import_key(config['peers'][snd])): frontend.warn('Warning: invalid EMSG signature') return else: pkt_cache.remove(idx) msgid = handle_packet(idx + b'\0' + dat, flags | F_VERIFIED | F_ENCRYPTED, snd, sender) if msgid != None: saved_msgs[msgid.decode('ascii', 'replace')] = b'SIGNED\0' + dat0 return msgid if tp == b'eMSG': rec, dat0 = dat.split(b'\0', 1) if rec != self.encode('ascii'): send_pkt(msg, rec.decode('ascii', 'replace')) return else: pkt_cache.remove(idx) return handle_packet(idx + b'\0EMSG\0' + dat0, flags | F_EMSG_NOFORWARD, verified_as, sender) if tp == b'SIGNED': dat0 = dat snd, dat = dat0[:-128].split(b'\0', 1) snd = snd.decode('ascii', 'replace') if snd not in config['peers']: frontend.warn( 'Warning: could not validate SIGNED message, no public key available' ) elif not cryptutil.check_sign( dat0, cryptutil.import_key(config['peers'][snd])): frontend.warn('Warning: dropping incorrectly SIGNED message') return pkt_cache.remove(idx) return handle_packet(idx + b'\0' + dat, flags | F_VERIFIED, snd, sender) if tp == b'MSG' and not (flags & F_RELAYED): idx2, rec, dat0 = dat.split(b'\0', 2) if rec == self.encode('ascii'): handle_send_ack(idx2, dat0) if tp == b'MSG': idx2, rec, dat = dat.split(b'\0', 2) if rec == self.encode('ascii') or (flags & F_FORWARDED): handle_incoming(idx, idx2, dat, flags, verified_as, rec) saved_msgs[idx2.decode('ascii', 'replace')] = msg.split(b'\0', 1)[1] return idx2 else: send_pkt(msg, rec) elif tp == b'ACK': snd, rec, idx2 = dat.split(b'\0', 2) if rec == self.encode('ascii'): try: del sender_pool[idx2.decode('ascii', 'replace')] except KeyError: pass else: rs[snd].recalc(sender) frontend.event('delivered', idx2.decode('ascii', 'replace')) else: send_pkt(msg, rec) else: frontend.warn('Warning: dropping unrecognized packet: %r' % msg)
def unimport_contact(c, interactive=True): try: if isinstance(c, bytes): c = json.loads(c.decode('utf-8')) if interactive: print('Unimport this contact?') print('Peers:') for k, v in c['peers'].items(): print('*', format_nickname(cryptutil.hash(cryptutil.import_key(k)))) if v != None: print(' (@%s)' % v) if k in c['trusted']: print(' (trusted)') print('Sockets:') for x in c['sockets']: print('*', x) print('Relays:') for k, v in c['relays'].items(): print('* %s via %s' % (format_nickname(k), format_nickname(v))) print('Exclusive routes:') for k, v in c['exclusive'].items(): print('* %s excl. via %s' % (format_nickname(k), v)) try: input('Press Enter to continue, Ctrl+C to abort') except KeyboardInterrupt: return for k, v in c['peers'].items(): try: del config['peers'][cryptutil.hash(cryptutil.import_key(k))] except KeyError: frontend.warn('Warning: %s was not in your contacts' % cryptutil.hash(cryptutil.import_key(k))) if v != None: try: del config['nicknames'][cryptutil.hash( cryptutil.import_key(k))] except KeyError: frontend.warn('Warning: @%s was not in your contacts' % v) if cryptutil.hash(cryptutil.import_key(k)) in c['trusted']: try: config['trusted'].remove( cryptutil.hash(cryptutil.import_key(k))) except ValueError: frontend.warn('Warning: %s was not in your trust list' % cryptutil.hash(cryptutil.import_key(k))) for x in c['sockets']: if x in config['sockets']: # start_peer_socket(x) try: config['sockets'].remove(x) except ValueError: frontend.warn( 'Warning: socket %s was not in your socket list' % x) else: frontend.warn( 'Note: socket %s removed from your socket list, will be disconnected on client restart' % x) for r in c['relays']: try: del config['relays'][r] except ValueError: frontend.warn('Warning: no relay was configured for %s' % r) for r in c['exclusive']: try: del config['exclusive'][r] except ValueError: frontend.warn( 'Warning: no exclusive socket was configured for %s' % r) update_config() except: print('Error during contact unimport:', file=sys.stderr) sys.excepthook(*sys.exc_info())
import threading, queue, os, socket, sys, json, cryptutil, socketutil, router, dbhelper from collections import defaultdict from frontend_helper import frontend config = json.loads(open(sys.argv[1] + '/config.json').read()) privkey = cryptutil.import_key(config['privkey']) pubkey = privkey.publickey() msgq = queue.Queue() peers = [] rs = router.RouteMap( peers, config['exclusive']) #defaultdict(lambda: router.RouteSet(peers)) def update_config(): with open(sys.argv[1] + '/config.json', 'w') as file: print(json.dumps(config), file=file) def peer_main(addr, q): # a1, a2 = addr # x = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # x.bind(a1) # x.connect(a2) x = [socketutil.create_socket(addr)] q.addr = addr def sender_thread(): while True: msg, rec = q.get() if rec != None and rec in config[ 'exclusive'] and config['exclusive'][rec] != addr: