def incoming(self, wrapper, payload, address): """Hands off incoming packets to appropriate Lines""" t, iv = wrapper['type'], wrapper['iv'].decode('hex') if t == 'line': l = wrapper['line'] if l in self.lines: self.lines[l].recv(iv, payload) elif t == 'open': remote_ecc_key = self.local.decrypt(wrapper['open']) aes_key = sha256(remote_ecc_key) body = aes(aes_key.digest(), iv).decrypt(payload) inner, remote_rsa = packet.decode(body) remote = SwitchID(key=remote_rsa) hn = remote.hash_name log.debug('Received open from %s' % hn) remote_line = inner['line'].decode('hex') aes_key.update(remote_line) candidate_line = self.known_hashes.get(hn, None) encrypted_sig = wrapper['sig'].decode('base64') sig = aes(aes_key.digest(), iv).decrypt(encrypted_sig) secrets = (remote_line, remote_ecc_key) if not remote.verify(sha256(payload).digest(), sig): log.debug('Invalid signature from: %s' % hn) return if candidate_line is not None: log.debug('Open for existing Line: %s' % candidate_line) line = self.lines[candidate_line] if line.secret is None: line.ecdh(secrets) else: line = Line(self.local, self.sendto, address, remote, secrets) self.lines[line.id] = line self.known_hashes[hn] = line.id else: pass # Fwomp
def _open(self, local, remote, secrets=None): inner = { 'to': remote.hash_name, 'at': int(time.time() * 1000), 'line': self.id } body = packet.encode(inner, local.pub_key_der) self._ecc_key = ecc.Key(256) ecc_key_pub = self._ecc_key.public.as_string(format='der', ansi=True) aes_key = sha256(ecc_key_pub) iv = os.urandom(16) encrypted_body = aes(aes_key.digest(), iv).encrypt(body) sig = local.sign(sha256(encrypted_body).digest()) aes_key.update(self._id) encrypted_sig = aes(aes_key.digest(), iv).encrypt(sig) outer = { 'type': 'open', 'open': remote.encrypt(ecc_key_pub), 'iv': iv.encode('hex'), 'sig': encrypted_sig.encode('base64').translate(None, '\n') } log.debug('Sending open to: %s' % remote.hash_name) if secrets is not None: self.ecdh(secrets) self.sendto(packet.encode(outer, encrypted_body), self.remote_iface)
def _send_open(self): iv = os.urandom(16) aes_key = sha256(self._ecc_pub) enc_body = aes(aes_key.digest(), iv).encrypt(self._open) aes_key.update(self.line.id.decode('hex')) sig = self.local_id.sign(sha256(enc_body).digest()) enc_sig = aes(aes_key.digest(), iv).encrypt(sig) o = self.id.encrypt(self._ecc_pub) data = packet.wrap_open(o, iv, enc_sig, enc_body) self._send(data) log.debug('Open to: %s' % self.id.hash_name) log.debug('Line: %s to %s' % (self.line.id, self.line.rid))
def read_open(me, sender_ecc, wrapper, payload): aes_key = sha256(sender_ecc) sig_test = sha256(payload).digest() iv = wrapper['iv'].decode('hex') body = aes(aes_key.digest(), iv).decrypt(payload) inner, sender_rsa = packet.decode(body) remote = SwitchID(key=sender_rsa) if not all(k in inner for k in ('to', 'at', 'line')): raise PacketException('Malformed inner open') enc_sig = wrapper['sig'].decode('base64') line_id = inner['line'].decode('hex') aes_key.update(line_id) sig = aes(aes_key.digest(), iv).decrypt(enc_sig) if not remote.verify(sig_test, sig): raise PacketException('Invalid signature in open') if inner['to'] != me: raise PacketException('Open addressed to wrong hash_name?!') #TODO: validate these too return remote, line_id, inner['at']
def aes_enc(self): return sha256(self.secret + self._id + self._rid).digest()
def test_bytearray_api(self): obj = hash.sha256(bytearray(b'hello,')) obj.update(bytearray(b' world')) assert obj.hexdigest( ) == '09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b'
def test_bytearray_api(self): obj = hash.sha256(bytearray(b'hello,')) obj.update(bytearray(b' world')) assert obj.hexdigest() == '09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b'
def _hash_from_key(key): pub_der = key.public.as_string(format='der') hex_string = sha256(pub_der).hexdigest() #TODO: Apparently this is what @classmethod is for? return SwitchID._hash_from_string(hex_string)