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) if tp3 == b'KEY': key = cryptutil.import_binary_key(dat4[:-128]) known_keys[cryptutil.hash(key)] = key sndr1 = sndr.decode('ascii', 'replace') if sndr1 in known_keys: if not cryptutil.check_sign(dat2, known_keys[sndr1]): print('Badly signed!') if tp2 == b'MSG': if msgid2 in known_msgs: return known_msgs.add(msgid2) if tp3 == b'RELAY': msg2 = dat4[:-128].split(b'\0', 2)[2] if msg2.startswith(b'eMSG\0'): msg2 = b'EMSG\0'+msg2.split(b'\0', 2)[2] msg2 = msgid2+b'\0'+msg2 self.queue.put(msg2) self.send_encrypted_back(sndr, b'ACK\0'+bot_hash.encode('ascii')+b'\0'+sndr+b'\0'+msgid2) else: self.queue.put(os.urandom(8).hex().encode('ascii')+b'\0MSG\0'+os.urandom(8).hex().encode('ascii')+b'\0'+sndr+b'\0'+bot_hash.encode('ascii')+b'\0NEEDKEY\0') except Exception: import traceback traceback.print_exc()
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 handle_incoming(pktid, idx, dat, flags, verified_as, rec): if not (flags & F_FORWARDED): if idx in msg_cache: return msg_cache.add(idx) frontend.event('msg_pkt_id', idx.decode('ascii', 'replace'), pktid.decode('ascii', 'replace')) # print(dat) snd0, tp, dat = dat.split(b'\0', 2) snd = snd0.decode('ascii', 'replace') if not (flags & F_VERIFIED) and snd in config['peers']: frontend.warn('Warning: message %s not verified, may be spoofed' % idx.decode('ascii', 'replace')) elif (flags & F_VERIFIED) and snd != verified_as: frontend.warn('Warning: message %s: sender spoofed, dropping' % idx.decode('ascii', 'replace')) return if rec != self.encode('ascii'): frontend.event('originally_written', idx.decode('ascii', 'replace'), format_nickname(rec.decode('ascii', 'replace'))) # print('message:', snd0, tp, dat) if tp == b'NEEDKEY': send_key_to(snd) return if tp == b'MSG': frontend.event('incoming_msg', idx.decode('ascii', 'replace'), format_nickname(snd), dat) elif tp == b'KEY': key = cryptutil.import_binary_key(dat) config['peers'][cryptutil.hash(key)] = cryptutil.export_key(key) elif tp == b'RELAY': tgt, relayed, msg = dat.split(b'\0', 2) tgt = tgt.decode('ascii', 'replace') if snd in config['trusted'] and not ( flags & F_FORWARDED) or tgt in config['exclusive'] and config[ 'exclusive'][tgt].startswith('python://'): send_msg(tgt, b'RELAYED\0' + msg, relay_idx=float('inf') if relayed == b'0' else 0) else: frontend.warn('Warning: RELAY message from an untrusted source') elif tp == b'RELAYED': handle_packet(idx + b'\0' + dat, F_RELAYED) elif tp == b'FORWARD': frontend.event('was_forwarded', idx.decode('ascii', 'replace'), format_nickname(snd0.decode('ascii', 'replace'))) handle_packet(idx + b'\0' + dat, F_FORWARDED) elif tp == b'CONTACT': saved_contacts[idx.decode('ascii', 'replace')] = dat frontend.event('incoming_contact', idx.decode('ascii', 'replace'), format_nickname(snd0.decode('ascii', 'replace'))) else: frontend.warn('Warning: dropping unknown message type: %r' % tp)
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())
pass x[0] = socketutil.create_socket(addr) def receiver_thread(): while True: try: msgq.put((x[0].recv(1048576), q)) except: pass threading.Thread(target=sender_thread, daemon=True).start() threading.Thread(target=receiver_thread, daemon=True).start() pkt_cache = set() self = cryptutil.hash(pubkey) if self not in config['peers']: config['peers'][self] = cryptutil.export_key(pubkey) update_config() frontend.event('i_am', self) saved_msgs = dbhelper.DBDict('msgs', binary=True) saved_contacts = dbhelper.DBDict('contacts', binary=True) def receiver_loop(): while True: msg, snd = msgq.get() try: handle_packet(msg, sender=snd) except: