def _dmail_auto_publish(self, dmail_address): data_rw = yield from self.engine.tasks.send_get_data(\ dmail_address.site_key, retry_factor=100) if data_rw.data: if log.isEnabledFor(logging.DEBUG): log.debug("Succeeded in fetching dmail site [{}]; won't"\ " auto-publish."\ .format(mbase32.encode(dmail_address.site_key))) return if log.isEnabledFor(logging.INFO): log.info("Failed to fetch dmail site [{}]; republishing."\ .format(mbase32.encode(dmail_address.site_key))) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) dh = dhgroup14.DhGroup14() dh.x = sshtype.parseMpint(dmail_address.keys[0].x)[1] dh.generate_e() dms = dmail.DmailSite() root = dms.root root["ssm"] = "mdh-v1" root["sse"] = base58.encode(sshtype.encodeMpint(dh.e)) root["target"] =\ mbase32.encode(dmail_address.keys[0].target_key) root["difficulty"] = int(dmail_address.keys[0].difficulty) storing_nodes =\ yield from self._dmail_engine.publish_dmail_site(private_key, dms) if log.isEnabledFor(logging.INFO): log.info("Republished Dmail site with [{}] storing nodes."\ .format(storing_nodes))
def generate_ss(self): self.dh = dh = dhgroup14.DhGroup14() dh.generate_x() dh.generate_e() if log.isEnabledFor(logging.INFO): log.info("dmail e=[{}].".format(dh.e)) self.root["ssm"] = _dh_method_name self.root["sse"] = base58.encode(sshtype.encodeMpint(dh.e))
def _process_dmail_v2(self, key, x, tb, data_rw): dw = DmailWrapper(tb.buf, mp.TargetedBlock.BLOCK_OFFSET) if dw.ssm != "mdh-v1": raise DmailException(\ "Unrecognized key exchange method in dmail [{}]."\ .format(dw.ssm)) # Calculate the shared secret. kex = dhgroup14.DhGroup14() kex.x = x kex.generate_e() kex.f = dw.ssf if dw.sse != kex.e: raise DmailException(\ "Dmail [{}] is encrypted with a different e [{}] than"\ " the specified x resulted in [{}]."\ .format(mbase32.encode(data_rw.data_key), dw.sse, kex.e)) kex.calculate_k() # Generate the AES-256 encryption key. key = self._generate_encryption_key(tb.target_key, kex.k) # Decrypt the data. data = enc.decrypt_data_block(dw.data_enc, key) if not data: raise DmailException("Dmail data was empty.") dmail = Dmail(data) if dmail.signature: pubkey = rsakey.RsaKey(dmail.sender_pubkey) valid_sig =\ pubkey.verify_rsassa_pss_sig(\ data[:dmail.signature_offset], dmail.signature) return dmail, valid_sig else: return dmail, False
def _send_dmail(self, from_asymkey, recipient, dmail_bytes, signature): assert type(recipient) is DmailSite # Read in recipient DmailSite. root = recipient.root sse = sshtype.parseMpint(base58.decode(root["sse"]))[1] target_enc = root["target"] difficulty = root["difficulty"] # Calculate a shared secret. dh = dhgroup14.DhGroup14() dh.generate_x() dh.generate_e() dh.f = sse k = dh.calculate_k() target_key = mbase32.decode(target_enc) key = self._generate_encryption_key(target_key, k) # Encrypt the Dmail bytes. m, r = enc.encrypt_data_block(dmail_bytes, key) if m: if r: m = m + r else: m = r # Store it in a DmailWrapper. dw = DmailWrapper() dw.ssm = _dh_method_name dw.sse = sse dw.ssf = dh.e dw.data_len = len(dmail_bytes) dw.data_enc = m # Store the DmailWrapper in a TargetedBlock. tb = mp.TargetedBlock() tb.target_key = target_key tb.nonce = int(0).to_bytes(64, "big") tb.block = dw tb_data = tb.encode() tb_header = tb_data[:mp.TargetedBlock.BLOCK_OFFSET] # Do the POW on the TargetedBlock. if log.isEnabledFor(logging.INFO): log.info(\ "Attempting work on dmail (target=[{}], difficulty=[{}])."\ .format(target_enc, difficulty)) def threadcall(): return brute.generate_targeted_block(\ target_key, difficulty, tb_header,\ mp.TargetedBlock.NOONCE_OFFSET,\ mp.TargetedBlock.NOONCE_SIZE) nonce_bytes = yield from self.loop.run_in_executor(None, threadcall) if log.isEnabledFor(logging.INFO): log.info("Work found nonce [{}].".format(nonce_bytes)) mp.TargetedBlock.set_nonce(tb_data, nonce_bytes) if log.isEnabledFor(logging.INFO): mp.TargetedBlock.set_nonce(tb_header, nonce_bytes) log.info("Message key=[{}]."\ .format(mbase32.encode(enc.generate_ID(tb_header)))) key = None def key_callback(val): nonlocal key key = val if log.isEnabledFor(logging.DEBUG): log.debug("TargetedBlock dump=[\n{}]."\ .format(mutil.hex_dump(tb_data))) # Upload the TargetedBlock to the network. log.info("Sending dmail to the network.") total_storing = 0 retry = 0 while True: storing_nodes = yield from\ self.task_engine.send_store_targeted_data(\ tb_data, store_key=True, key_callback=key_callback,\ retry_factor=retry * 10) total_storing += storing_nodes if total_storing >= 3: break if retry > 32: break elif retry > 3: yield from asyncio.sleep(1) retry += 1 key_enc = mbase32.encode(key) id_enc = mbase32.encode(enc.generate_ID(key)) if log.isEnabledFor(logging.INFO): log.info("Dmail sent; key=[{}], id=[{}], storing_nodes=[{}]."\ .format(key_enc, id_enc, total_storing)) return total_storing
def fetch_dmail(self, key, x=None, target_key=None): "Fetch the Dmail referred to by key from the network."\ " Returns a Dmail object, not a db.DmailMessage object." data_rw = yield from self.task_engine.send_get_targeted_data(key) data = data_rw.data if not data: return None, None if not x: return data, None tb = mp.TargetedBlock(data) if target_key: if tb.target_key != target_key: tb_tid_enc = mbase32.encode(tb.target_key) tid_enc = mbase32.encode(target_key) raise DmailException(\ "TargetedBlock->target_key [{}] does not match request"\ " [{}]."\ .format(tb_tid_enc, tid_enc)) dw = DmailWrapper(tb.buf, mp.TargetedBlock.BLOCK_OFFSET) if dw.ssm != "mdh-v1": raise DmailException(\ "Unrecognized key exchange method in dmail [{}]."\ .format(dw.ssm)) kex = dhgroup14.DhGroup14() kex.x = x kex.generate_e() kex.f = dw.ssf if dw.sse != kex.e: raise DmailException(\ "Dmail [{}] is encrypted with a different e [{}] than"\ " the specified x resulted in [{}]."\ .format(mbase32.encode(data_rw.data_key), dw.sse, kex.e)) kex.calculate_k() key = self._generate_encryption_key(tb.target_key, kex.k) data = enc.decrypt_data_block(dw.data_enc, key) if not data: raise DmailException("Dmail data was empty.") dmail = Dmail(data, 0, dw.data_len) if dw.signature: signature = dw.signature pubkey = rsakey.RsaKey(dmail.sender_pubkey) valid_sig = pubkey.verify_rsassa_pss_sig(dw.data_enc, signature) return dmail, valid_sig else: return dmail, False
def __init__(self, protocol): self.dh = dhgroup14.DhGroup14() self.protocol = protocol