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_random_address(): ## generate 32 bytes (256 bits) of pseudo-random data seed = hexlify(os.urandom(32)) ## reduce random data to make it a valid ed25519 scalar secret_spend_key = utils.sc_reduce32(seed) ## use a reduced hash of the secret spend key for the deterministic secret view key secret_view_key = utils.hash_to_scalar(secret_spend_key) ## multiply by the generator point to get public keys from private keys public_spend_key = utils.publickey_to_privatekey(secret_spend_key) public_view_key = utils.publickey_to_privatekey(secret_view_key) ## the network byte, public spend key, and public view key are all concatenated together ## 0x12 is the Monero mainnet network byte network_byte = "12" ## Concatenate the three strings data = network_byte + public_spend_key + public_view_key hash = utils.keccak_256(data) ## checksum is the first 4 bytes (8 hex characters) of the hash of the previous data checksum = hash[0:8] address = base58.encode(data + checksum) ## Priting the keys print("Secret_spend_key : " + secret_spend_key) print("Secret_view_key : " + secret_view_key) print("Public_spend_key : " + public_spend_key) print("Public_view_key : " + public_view_key) ## Returning address generated return address
def wif (priv, compressed, testnet=False): ''' Convert raw private key to base58-encoded wallet import format. >>> wif (binascii.unhexlify (b'1111111111111111111111111111111111111111111111111111111111111111'), False) b'5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh' >>> wif (binascii.unhexlify (b'1111111111111111111111111111111111111111111111111111111111111111'), True) b'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp' >>> wif (binascii.unhexlify (b'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), False) b'5KVzsHJiUxgvBBgtVS7qBTbbYZpwWM4WQNCCyNSiuFCJzYMxg8H' >>> wif (binascii.unhexlify (b'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), True) b'L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN' >>> wif (binascii.unhexlify (b'47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012'), False) b'5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y' >>> wif (binascii.unhexlify (b'47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012'), True) b'KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq' ''' result = (b'\x80' if not testnet else b'\xef') + (b'\x00' * (32 - len (priv)) + priv) assert len (result) == 33 if compressed: result += b'\x01' h1 = hashlib.sha256 (result) h2 = hashlib.sha256 (h1.digest ()) result += h2.digest ()[:4] return base58.encode (result)
def addr(pub, testnet=False): """ Convert raw public key to base58check-encoded address. >>> addr (binascii.unhexlify (b'044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1')) b'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a' >>> addr (binascii.unhexlify (b'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa')) b'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9' >>> addr (binascii.unhexlify (b'04ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bdedc416f5cefc1db0625cd0c75de8192d2b592d7e3b00bcfb4a0e860d880fd1fc')) b'1JyMKvPHkrCQd8jQrqTR1rBsAd1VpRhTiE' >>> addr (binascii.unhexlify (b'02ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bd')) b'1NKRhS7iYUGTaAfaR5z8BueAJesqaTyc4a' >>> addr (binascii.unhexlify (b'042596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3ed0a9004acf927666eee18b7f5e8ad72ff100a3bb710a577256fd7ec81eb1cb3')) b'1PM35qz2uwCDzcUJtiqDSudAaaLrWRw41L' >>> addr (binascii.unhexlify (b'032596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3')) b'19ck9VKC6KjGxR9LJg4DNMRc45qFrJguvV' """ if pub[0] == 4: assert len(pub) == 65 elif pub[0] == 2 or pub[0] == 3: assert len(pub) == 33 else: assert False, "Unknown public key format: {}".format(pub[0]) h3 = hashlib.sha256(pub) h4 = hashlib.new("ripemd160", h3.digest()) result = (b"\x00" if not testnet else b"\x6f") + h4.digest() h5 = hashlib.sha256(result) h6 = hashlib.sha256(h5.digest()) result += h6.digest()[:4] return base58.encode(result)
def addr (pub, testnet=False): ''' Convert raw public key to base58check-encoded address. >>> addr (binascii.unhexlify (b'044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1')) b'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a' >>> addr (binascii.unhexlify (b'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa')) b'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9' >>> addr (binascii.unhexlify (b'04ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bdedc416f5cefc1db0625cd0c75de8192d2b592d7e3b00bcfb4a0e860d880fd1fc')) b'1JyMKvPHkrCQd8jQrqTR1rBsAd1VpRhTiE' >>> addr (binascii.unhexlify (b'02ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bd')) b'1NKRhS7iYUGTaAfaR5z8BueAJesqaTyc4a' >>> addr (binascii.unhexlify (b'042596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3ed0a9004acf927666eee18b7f5e8ad72ff100a3bb710a577256fd7ec81eb1cb3')) b'1PM35qz2uwCDzcUJtiqDSudAaaLrWRw41L' >>> addr (binascii.unhexlify (b'032596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3')) b'19ck9VKC6KjGxR9LJg4DNMRc45qFrJguvV' ''' if pub[0] == 4: assert len (pub) == 65 elif pub[0] == 2 or pub[0] == 3: assert len (pub) == 33 else: assert False, 'Unknown public key format: {}'.format (pub[0]) h3 = hashlib.sha256 (pub) h4 = hashlib.new ('ripemd160', h3.digest ()) result = (b'\x00' if not testnet else b'\x6f') + h4.digest () h5 = hashlib.sha256 (result) h6 = hashlib.sha256 (h5.digest ()) result += h6.digest ()[:4] return base58.encode (result)
def __init__(self, engine, db): assert type(engine) is chord.ChordEngine self.engine = engine self.db = db self.loop = engine.loop self.latest_version_number = None self.latest_version_data = None self.auto_publish_enabled = True self.auto_scan_enabled = True self.csrf_token = base58.encode(os.urandom(64)) self._dmail_engine = None self._running = False self._data_key =\ mbase32.decode("sp1nara3xhndtgswh7fznt414we4mi3y6kdwbkz4jmt8ocb6x"\ "4w1faqjotjkcrefta11swe3h53dt6oru3r13t667pr7cpe3ocxeuma") self._path = b"latest_version" self._dmail_autoscan_processes = {}
def generate_link(self, url): url = self._clean_url(url) link = self.check_existing_link(url) if link is None: link = self.create_new_link(url) return request.host_url + base58.encode(link.integer_id())
def test_encode(): """should take a bitcoin address in raw byte format and encode it in base58""" actual = base58.encode("2304e21839bb9729ec18671893e4da55cb28a791".decode("hex")) expected = "14CAW1CobqYjs14boGNUwy5ZGNDRXjomFW" assert actual == expected
def base58_check(src, version_bytes=0): if isinstance(version_bytes, int): version_bytes = bytes([version_bytes]) src = version_bytes + src r = hash256(src) if DEBUG: print('SHA256(SHA256(0x{} + src)):'.format(bytes2hex(version_bytes)), bytes2hex(r)) checksum = r[:4] s = src + checksum if DEBUG: print('src + checksum:', bytes2hex(s)) e = base58.encode(int.from_bytes(s, 'big')) if version_bytes == bytes([0]): lz = 0 while lz < len(src) and src[lz] == 0: lz += 1 return ('1' * lz) + e return e
def wif(priv, compressed, testnet=False): """ Convert raw private key to base58-encoded wallet import format. >>> wif (binascii.unhexlify (b'1111111111111111111111111111111111111111111111111111111111111111'), False) b'5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh' >>> wif (binascii.unhexlify (b'1111111111111111111111111111111111111111111111111111111111111111'), True) b'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp' >>> wif (binascii.unhexlify (b'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), False) b'5KVzsHJiUxgvBBgtVS7qBTbbYZpwWM4WQNCCyNSiuFCJzYMxg8H' >>> wif (binascii.unhexlify (b'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), True) b'L4ezQvyC6QoBhxB4GVs9fAPhUKtbaXYUn8YTqoeXwbevQq4U92vN' >>> wif (binascii.unhexlify (b'47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012'), False) b'5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y' >>> wif (binascii.unhexlify (b'47f7616ea6f9b923076625b4488115de1ef1187f760e65f89eb6f4f7ff04b012'), True) b'KydbzBtk6uc7M6dXwEgTEH2sphZxSPbmDSz6kUUHi4eUpSQuhEbq' """ result = (b"\x80" if not testnet else b"\xef") + (b"\x00" * (32 - len(priv)) + priv) assert len(result) == 33 if compressed: result += b"\x01" h1 = hashlib.sha256(result) h2 = hashlib.sha256(h1.digest()) result += h2.digest()[:4] return base58.encode(result)
def wifkey(key, prefix=b'\x80'): ''' return key in Wallet Import Format prefix b'\x80' is for private key, '\x00' for public key ''' bytestring = prefix + key checksum = sha256(sha256(bytestring))[:4] return base58.encode(bytestring + checksum).decode('ascii')
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 _generate_history(file_keys): output = [] for file_key in file_keys: blob = blobstore.BlobInfo(file_key.blob_key) output.append({ 'url': base58.encode(file_key.key.id()), 'filename' : blob.filename, 'last_seen' : file_key.last_seen.isoformat() + "Z", 'created_time' : file_key.created_time.isoformat() + "Z" }) return output
def send_store_updateable_key(\ self, data, privkey, path=None, version=None, store_key=True,\ key_callback=None): privkey_enc = base58.encode(privkey._encode_key()) data_enc = base58.encode(data) cmd = "storeukeyenc {} {} {} {}"\ .format(privkey_enc, data_enc, version, store_key) r = yield from self.send_command(cmd) if not r: return 0 if key_callback: p1 = r.find(b']', 10) r = r[10:p1].decode() key_enc = r key_callback(mbase32.decode(key_enc)) return 1 #FIXME: The shell API doesn't return this value as of yet.
def save_file(key): """Saves file information to the datastore (not blobstore). Args: key: A string containing the blob_key of the file. Returns: A string containing the base58 encoding of the new datastore key. """ file_key = FileKey(blob_key=blobstore.BlobKey(key)) data_key = file_key.put() return base58.encode(data_key.integer_id())
def public_key_hex_to_address(public_key_hex): public_key_bytearray = bytearray.fromhex(public_key_hex) # Perform SHA-256 and RIPEMD-160 hashing on public key hash160_address = myhash160(public_key_bytearray) # add version byte: 0x00 for Main Network extended_address = '\x00' + hash160_address # generate double SHA-256 hash of extended address hash_address = myhash(extended_address) # Take the first 4 bytes of the second SHA-256 hash. This is the address checksum checksum = hash_address[:4] # Add the 4 checksum bytes from point 7 at the end of extended RIPEMD-160 hash from point 4. This is the 25-byte binary Bitcoin Address. binary_address = extended_address + checksum address = encode(binary_address) return address
def send_store_targeted_data(\ self, data, store_key=False, key_callback=None): data_enc = base58.encode(data) r = yield from\ self.send_command(\ "storetargetedblockenc {} {}".format(data_enc, store_key)) p0 = r.find(b']') data_key = mbase32.decode(r[10:p0].decode("UTF-8")) key_callback(data_key) p0 = r.find(b"storing_nodes=[", p0) + 15 p1 = r.find(b']', p0) return int(r[p0:p1])
def genHash(bytes,func_id): hashfunc = None if func_id == 0x11: #function is sha1 hashfunc = hashlib.sha1() elif func_id == 0x12: #function is sha256 hashfunc = hashlib.sha256() elif func_id == 0x13: #function is sha512 hashfunc = hashlib.sha512() else: raise Exception("Requested hash is not supported") hashfunc.update(bytes) data = hashfunc.digest() size = hashfunc.digest_size bytes = [func_id,size]+[ord(x) for x in data] return base58.encode(bytes_to_long(bytes))
def genHash(bytes, func_id): hashfunc = None if func_id == 0x11: #function is sha1 hashfunc = hashlib.sha1() elif func_id == 0x12: #function is sha256 hashfunc = hashlib.sha256() elif func_id == 0x13: #function is sha512 hashfunc = hashlib.sha512() else: raise Exception("Requested hash is not supported") hashfunc.update(bytes) data = hashfunc.digest() size = hashfunc.digest_size bytes = [func_id, size] + [ord(x) for x in data] return base58.encode(bytes_to_long(bytes))
def makeHash(): randInput = input( "Blindly sweep your hands across the keyboard and then press enter " ).encode("utf-8") print() hexIntermediate = hashlib.sha256(randInput).hexdigest() if int("0x" + hexIntermediate, 0) > 2**256: return hexIntermediate = "80" + hexIntermediate doubleHash = hashlib.sha256( hashlib.sha256(hexIntermediate.encode("utf-8")).hexdigest().encode( "utf-8")).hexdigest() hexIntermediate += doubleHash[:9] return (base58.encode(int("0x" + hexIntermediate, 0)))
def getnewaddress(): # Generate public and private keys key = Key() key.generate() key.set_compressed(True) private_key = key.get_privkey() public_key = key.get_pubkey() private_key_hex = private_key.encode('hex') public_key_hex = public_key.encode('hex') public_key_bytearray = bytearray.fromhex(public_key_hex) # Perform SHA-256 and RIPEMD-160 hashing on public key hash160_address = myhash160(public_key_bytearray) # add version byte: 0x00 for Main Network extended_address = '\x00' + hash160_address # generate double SHA-256 hash of extended address hash_address = myhash(extended_address) # Take the first 4 bytes of the second SHA-256 hash. This is the address checksum checksum = hash_address[:4] # Add the 4 checksum bytes from point 7 at the end of extended RIPEMD-160 hash from point 4. This is the 25-byte binary Bitcoin Address. binary_address = extended_address + checksum # Convert the result from a byte string into a base58 string using Base58Check encoding. address = encode(binary_address) return public_key, private_key, address
def __init__(self, engine, db): assert type(engine) is chord.ChordEngine self.engine = engine self.db = db self.loop = engine.loop self.latest_version_number = None self.latest_version_data = None self.auto_publish_enabled = True self.csrf_token = base58.encode(os.urandom(64)) self._dmail_engine = None self._running = False self._data_key =\ mbase32.decode("sp1nara3xhndtgswh7fznt414we4mi3y6kdwbkz4jmt8ocb6x"\ "4w1faqjotjkcrefta11swe3h53dt6oru3r13t667pr7cpe3ocxeuma") self._path = b"latest_version" self._dmail_autoscan_processes = {}
def slug(self):return base58.encode( base58.to_base128(self.key)) class Theme(Entity):
def slug(self):return base58.encode( base58.to_base128(self.key)) @property
def base58(self): data= byt(self.version) + self.hash data += shasha(data)[0:4] return base58.encode(data)
def wallet(self): data= byt(self.version)+convert.bytesfromnum(self.privkey) data += shasha(data)[:4] return base58.encode(data)
def dispatch_GET(self, rpath): assert rpath[0] == '.' if rpath.startswith(".aiwj"): self.send_content(\ b"AIWJ - Asynchronous IFrames Without Javascript!") return elif rpath.startswith(".main/"): rpath = rpath[6:] if rpath == "style.css": self.send_content(\ templates.main_css, content_type="text/css") elif rpath == "csrf_token": self.send_content(self.client_engine.csrf_token) else: self.send_error(errcode=400) return elif rpath == ".images/favicon.ico": self.send_content(\ templates.favicon_content, content_type="image/png") return elif rpath.startswith(".upload"): if rpath.startswith(".upload/generate"): priv_key =\ base58.encode(\ rsakey.RsaKey.generate(bits=4096)._encode_key()) self.send_response(307) self.send_header("Location", "{}".format(priv_key)) self.send_header("Content-Length", 0) self.end_headers() self.finish_response() return if rpath == ".upload" or rpath == ".upload/": if (self.handle_cache(rpath)): return template = templates.main_combined_upload[0] template = template.format(\ csrf_token=self.client_engine.csrf_token,\ private_key="",\ version="",\ updateable_key_mode_display="display: none;",\ static_mode_display="") self.send_content(template) else: template = templates.main_combined_upload[0] # 8 = len(".upload/"). template = template.format(\ csrf_token=self.client_engine.csrf_token,\ private_key=rpath[8:],\ version=str(int(time.time()*1000)),\ updateable_key_mode_display="",\ static_mode_display="display: none;") self.send_content(template) return elif rpath.startswith(".dmail"): yield from maalstroom.dmail.serve_get(self, rpath) return else: self.send_error(errcode=400)
def do_GET(self): self.__prepare_for_request() rpath = self.path[1:] if rpath and rpath[-1] == '/': rpath = rpath[:-1] connection_cnt = None if not rpath: connection_cnt = self._get_connection_count() content = pages.home_page_content[0].replace(\ b"${CONNECTIONS}", str(connection_cnt).encode()) content = content.replace(\ b"${MORPHIS_VERSION}", self.node.morphis_version.encode()) self._send_content([content, None]) return s_upload = ".upload" s_dmail = ".dmail" s_aiwj = ".aiwj" if log.isEnabledFor(logging.DEBUG): log.debug("rpath=[{}].".format(rpath)) if rpath.startswith(s_aiwj): self._send_content(\ b"AIWJ - Asynchronous IFrames Without Javascript!") return elif rpath.startswith(s_upload): if rpath.startswith(".upload/generate"): priv_key =\ base58.encode(\ rsakey.RsaKey.generate(bits=4096)._encode_key()) self.send_response(307) self.send_header("Location", "{}".format(priv_key)) self.send_header("Content-Length", 0) self.end_headers() return if len(rpath) == len(s_upload): self._send_content(static_upload_page_content) else: content =\ upload_page_content.replace(\ b"${PRIVATE_KEY}",\ rpath[len(s_upload)+1:].encode()) content =\ content.replace(\ b"${VERSION}",\ str(int(time.time()*1000)).encode()) content =\ content.replace(\ b"${UPDATEABLE_KEY_MODE_DISPLAY}",\ b"") content =\ content.replace(\ b"${STATIC_MODE_DISPLAY}",\ b"display: none") self._send_content(content) return elif rpath.startswith(s_dmail): if self.node.web_devel: importlib.reload(pages) importlib.reload(pages.dmail) pages.dmail.serve_get(self, rpath) return if self.headers["If-None-Match"] == rpath: cache_control = self.headers["Cache-Control"] if cache_control != "max-age=0": self.send_response(304) if cache_control: # This should only have been sent for an updateable key. self.send_header("Cache-Control", "max-age=15, public") else: self.send_header("ETag", rpath) self.send_header("Content-Length", 0) self.end_headers() return significant_bits = None # At this point we assume it is a key URL. if connection_cnt is None: connection_cnt = self._get_connection_count() if not connection_cnt: self._send_error("No connected nodes; cannot fetch from the"\ " network.") return path_sep_idx = rpath.find('/') if path_sep_idx != -1: path = rpath[path_sep_idx+1:].encode() rpath = rpath[:path_sep_idx] else: path = None try: data_key, significant_bits = mutil.decode_key(rpath) except: self._send_error(\ "Invalid encoded key: [{}].".format(rpath),\ errcode=400) return data_rw = DataResponseWrapper() self.node.loop.call_soon_threadsafe(\ asyncio.async,\ _send_get_data(data_key, significant_bits, path, data_rw)) data = data_rw.data_queue.get() if significant_bits: if data_rw.data_key: key = mbase32.encode(data_rw.data_key) if path: url = "{}{}/{}"\ .format(\ self.maalstroom_url_prefix.decode(),\ key,\ path.decode("UTF-8")) else: url = "{}{}"\ .format(\ self.maalstroom_url_prefix.decode(),\ key) message = ("<html><head><title>permalink</title></head><body><a href=\"{}\">{}</a>\n{}</body></html>"\ .format(url, url, key))\ .encode() self.send_response(301) self.send_header("Location", url) self.send_header("Content-Type", "text/html") self.send_header("Content-Length", len(message)) self.end_headers() self.wfile.write(message) return if data: self.send_response(200) rewrite_url = False if data_rw.mime_type: self.send_header("Content-Type", data_rw.mime_type) if data_rw.mime_type\ in ("text/html", "text/css", "application/javascript"): rewrite_url = True else: dh = data[:160] if dh[0] == 0xFF and dh[1] == 0xD8: self.send_header("Content-Type", "image/jpg") elif dh[0] == 0x89 and dh[1:4] == b"PNG": self.send_header("Content-Type", "image/png") elif dh[:5] == b"GIF89": self.send_header("Content-Type", "image/gif") elif dh[:5] == b"/*CSS": self.send_header("Content-Type", "text/css") rewrite_url = True elif dh[:12] == b"/*JAVASCRIPT": self.send_header("Content-Type", "application/javascript") rewrite_url = True elif dh[:8] == bytes(\ [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70])\ or dh[:8] == bytes(\ [0x00, 0x00, 0x00, 0x1c, 0x66, 0x74, 0x79, 0x70]): self.send_header("Content-Type", "video/mp4") elif dh[:8] == bytes(\ [0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00]): self.send_header("Content-Type", "application/zip") elif dh[:5] == bytes(\ [0x25, 0x50, 0x44, 0x46, 0x2d]): self.send_header("Content-Type", "application/pdf") elif dh[:4] == b"RIFF" and dh[8:11] == b"AVI": self.send_header("Content-Type", "video/avi") else: dhl = dh.lower() if (dhl.find(b"<html") > -1 or dhl.find(b"<HTML>") > -1)\ and (dhl.find(b"<head>") > -1\ or dhl.find(b"<HEAD") > -1): self.send_header("Content-Type", "text/html") rewrite_url = True else: self.send_header(\ "Content-Type", "application/octet-stream") rewrite_url = rewrite_url and not self.maalstroom_plugin_used if rewrite_url: self.send_header("Transfer-Encoding", "chunked") else: self.send_header("Content-Length", data_rw.size) if data_rw.version is not None: self.send_header("Cache-Control", "max-age=15, public") # self.send_header("ETag", rpath) else: self.send_header("Cache-Control", "public") self.send_header("ETag", rpath) self.end_headers() try: while True: if rewrite_url: self._send_partial_content(data) else: self.wfile.write(data) data = data_rw.data_queue.get() if data is None: if data_rw.timed_out: log.warning(\ "Request timed out; closing connection.") self.close_connection = True if rewrite_url: self._end_partial_content() break except ConnectionError: if log.isEnabledFor(logging.INFO): log.info("Maalstroom request got broken pipe from HTTP"\ " side; cancelling.") data_rw.cancelled.set() else: self._handle_error(data_rw)
def serve_get(dispatcher, rpath): global top_tags log.info("Service .dmail request.") req = rpath[len(s_dmail) :] # if log.isEnabledFor(logging.INFO): # log.info("req=[{}].".format(req)) if req == "" or req == "/" or req == "/goto_new_mail" or req.startswith("/wrapper/"): cacheable = False if req == "/goto_new_mail": tag = "Inbox" addr = yield from _load_first_address_with_new_mail(dispatcher) if addr: log.info("NEW") addr_enc = mbase32.encode(addr.site_key) else: log.info("NO NEW") addr_enc = "" qline = None elif req.startswith("/wrapper/"): params = req[9:] pq = params.find("?") if pq != -1: qline = params[pq + 1 :] params = params[:pq] else: qline = None p0 = params.find("/") if p0 == -1: p0 = len(params) tag = "Inbox" else: tag = params[p0 + 1 :] addr_enc = params[:p0] if addr_enc: cacheable = True if dispatcher.handle_cache(req): return else: tag = "Inbox" addr_enc = "" qline = None if not addr_enc: dmail_address = yield from _load_default_dmail_address(dispatcher) if dmail_address: addr_enc = mbase32.encode(dmail_address.site_key) msg_list = None if qline: eparams = parse_qs(qline) msg_list = eparams.get("msg_list") if msg_list: msg_list = msg_list[0] if not msg_list: msg_list = "morphis://.dmail/msg_list/" + addr_enc + "/" + tag template = templates.dmail_page_wrapper[0] template = template.format(tag=tag, addr=addr_enc, msg_list_iframe_url=msg_list) if cacheable: dispatcher.send_content([template, req]) else: dispatcher.send_content(template) return if req == "/style.css": dispatcher.send_content(templates.dmail_css, content_type="text/css") elif req == "/logo": template = templates.dmail_logo[0] current_version = dispatcher.node.morphis_version latest_version_number = dispatcher.latest_version_number if latest_version_number and current_version != latest_version_number: version_str = '<span class="strikethrough nomargin">{}</span>]' ' [<a href="{}{}">GET {}</a>'.format( current_version, dispatcher.handler.maalstroom_url_prefix_str, "sp1nara3xhndtgswh7fznt414we4mi3y6kdwbkz4jmt8ocb6" "x4w1faqjotjkcrefta11swe3h53dt6oru3r13t667pr7" "cpe3ocxeuma/latest_version", latest_version_number, ) else: version_str = current_version connections = dispatcher.connection_count if connections == 1: connection_str = "1 Connection" else: connection_str = str(connections) + " Connections" template = template.format(version=version_str, connections=connection_str) dispatcher.send_content(template) elif req.startswith("/nav/"): params = req[5:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] template = templates.dmail_nav[0] template = template.format(csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag) dispatcher.send_content(template) elif req.startswith("/aside/"): params = req[7:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] addr = mbase32.decode(addr_enc) template = templates.dmail_aside[0] fmt = {} for top_tag in top_tags: active = top_tag == tag unread_count = yield from _count_unread_dmails(dispatcher, addr, top_tag) fmt[top_tag + "_active"] = "active-mailbox" if active else "" fmt[top_tag + "_unread_count"] = unread_count if unread_count else "" fmt[top_tag + "_unread_class"] = ("active-notify" if active else "inactive-notify") if unread_count else "" tags = yield from _load_tags(dispatcher, top_tags) tag_rows = [] unquoted_tag = unquote(tag) for tag in tags: if unquoted_tag == tag.name: active = " active_tag" else: active = "" row = ( '<li class="bullet{active}"><span class="mailbox-pad">' '<a href="morphis://.dmail/wrapper/{addr}/{tag}">{tag}</a>' "</span></li>".format(active=active, addr=addr_enc, tag=tag.name) ) tag_rows.append(row) template = template.format( csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag, tag_rows="".join(tag_rows), **fmt ) acharset = dispatcher.get_accept_charset() dispatcher.send_content(template) elif req.startswith("/msg_list/list/"): params = req[15:] p0 = params.index("/") addr_enc = params[:p0] tag = unquote(params[p0 + 1 :]) template = templates.dmail_msg_list_list_start[0] addr_heading = "TO" if tag in ("Outbox", "Sent", "Drafts") else "FROM" if tag == "Inbox" or tag == "": unread_check = '<meta target="self" http-equiv="refresh" content="60"/>' else: unread_check = "" template = template.format(unread_check=unread_check, addr_heading=addr_heading) acharset = dispatcher.get_accept_charset() dispatcher.send_partial_content(template, True, content_type="text/html; charset={}".format(acharset)) yield from _list_dmails_for_tag(dispatcher, addr_enc, unquote(tag)) dispatcher.send_partial_content(templates.dmail_msg_list_list_end[0]) dispatcher.end_partial_content() elif req.startswith("/msg_list/"): params = req[10:] p0 = params.index("/") addr_enc = params[:p0] tag = params[p0 + 1 :] if dispatcher.handle_cache(req): return if tag == "Trash": empty_trash_button_class = "link-button" else: empty_trash_button_class = "display_none" template = templates.dmail_msg_list[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, tag=unquote(tag), addr=addr_enc, empty_trash_button_class=empty_trash_button_class, ) dispatcher.send_content([template, req]) elif req == "/new_mail": template = templates.dmail_new_mail[0] unread_count = yield from _count_unread_dmails(dispatcher) template = template.format(unread_count=unread_count) dispatcher.send_content(template) elif req.startswith("/images/"): dispatcher.send_content(templates.imgs[req[8:]]) elif req.startswith("/tag/view/list/"): params = req[15:] p0 = params.index("/") tag = params[:p0] addr_enc = params[p0 + 1 :] if log.isEnabledFor(logging.INFO): log.info("Viewing dmails with tag [{}] for address [{}].".format(tag, addr_enc)) start = templates.dmail_tag_view_list_start.replace(b"${TAG_NAME}", tag.encode()) # FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. start = start.replace(b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(b"${DMAIL_ADDRESS2}", "{}...".format(addr_enc[:32]).encode()) acharset = dispatcher.get_accept_charset() dispatcher.send_partial_content(start, True, content_type="text/html; charset={}".format(acharset)) yield from _list_dmails_for_tag(dispatcher, mbase32.decode(addr_enc), tag) dispatcher.send_partial_content(templates.dmail_tag_view_list_end) dispatcher.end_partial_content() elif req.startswith("/read/content/"): params = req[14:] msg_dbid = params dm = yield from _load_dmail(dispatcher, msg_dbid, fetch_parts=True) dmail_text = _format_dmail_content(dm) acharset = dispatcher.get_accept_charset() dispatcher.send_content(dmail_text.encode(acharset), content_type="text/plain; charset={}".format(acharset)) elif req.startswith("/read/subject/"): params = req[14:] msg_dbid = params dm = yield from _load_dmail(dispatcher, msg_dbid) acharset = dispatcher.get_accept_charset() dispatcher.send_content(dm.subject.encode(acharset), content_type="text/plain; charset={}".format(acharset)) elif req.startswith("/read/"): params = req[6:] p0 = params.index("/") p1 = params.index("/", p0 + 1) addr_enc = params[:p0] tag = params[p0 + 1 : p1] msg_dbid = params[p1 + 1 :] def processor(sess, dm): dm.read = True return True dm = yield from _process_dmail_message(dispatcher, msg_dbid, processor, fetch_parts=True, fetch_tags=True) if dm.hidden: trash_msg = "REMOVE FROM TRASH" else: trash_msg = "MOVE TO TRASH" safe_reply_subject = generate_safe_reply_subject(dm) if dm.sender_dmail_key: sender_addr = mbase32.encode(dm.sender_dmail_key) if dm.sender_valid: sender_class = "valid_sender" else: sender_class = "invalid_sender" else: sender_addr = "[Anonymous]" sender_class = "valid_sender" if dm.destination_dmail_key: dest_addr_enc = mbase32.encode(dm.destination_dmail_key) dest_class = "" else: dest_addr_enc = "" dest_class = " display_none" unquoted_tag = unquote(tag) existing_tag_rows = [] if len(dm.tags) > 1: remove_tag_class = "" for etag in dm.tags: if etag.name == unquoted_tag: selected = "selected " else: selected = "" row = '<option {selected}value"{tag_id}">{tag_name}</option>'.format( selected=selected, tag_id=etag.id, tag_name=etag.name ) existing_tag_rows.append(row) else: remove_tag_class = "display_none" current_tag_names = [x.name for x in dm.tags] current_tag_names.extend(top_tags) current_tag_names.remove("Inbox") tags = yield from _load_tags(dispatcher, current_tag_names) available_tag_rows = [] for atag in tags: row = '<option value"{tag_id}">{tag_name}</option>'.format(tag_id=atag.id, tag_name=atag.name) available_tag_rows.append(row) template = templates.dmail_read[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, addr=addr_enc, tag=tag, safe_reply_subject=safe_reply_subject, trash_msg=trash_msg, msg_id=msg_dbid, sender_class=sender_class, sender=sender_addr, dest_class=dest_class, dest_addr=dest_addr_enc, date=mutil.format_human_no_ms_datetime(dm.date), remove_tag_class=remove_tag_class, existing_tags="".join(existing_tag_rows), available_tags="".join(available_tag_rows), ) dispatcher.send_content(template) elif req.startswith("/compose/"): if len(req) > 8 and req[8] == "/": params = req[9:] else: params = req[8:] p0 = params.find("?") if p0 != -1: eparams = parse_qs(params[p0 + 1 :]) subject = eparams.get("subject") if subject: subject = subject[0].replace('"', """) else: subject = "" sender_addr_enc = eparams.get("sender") if sender_addr_enc: sender_addr_enc = sender_addr_enc[0] else: sender_addr_enc = "" message_text = eparams.get("message") if message_text: message_text = message_text[0] else: message_text = "" else: subject = "" sender_addr_enc = "" message_text = "" p0 = len(params) dest_addr_enc = params[:p0] autofocus_fields = {"dest_addr_autofocus": "", "subject_autofocus": "", "message_text_autofocus": ""} if not dest_addr_enc: autofocus_fields["dest_addr_autofocus"] = " autofocus" elif not subject: autofocus_fields["subject_autofocus"] = " autofocus" elif not message_text: autofocus_fields["message_text_autofocus"] = " autofocus" addrs = yield from _list_dmail_addresses(dispatcher) if sender_addr_enc: sender_addr = mbase32.decode(sender_addr_enc) default_id = None else: sender_addr = None default_id = yield from _load_default_dmail_address_id(dispatcher) if not default_id: owner_if_anon_id = "" from_addr_options = [] for addr in addrs: if sender_addr: selected = addr.site_key.startswith(sender_addr) elif default_id: selected = addr.id == default_id else: selected = False if selected: option = '<option value="{}" selected>{}</option>' owner_if_anon_id = addr.id else: option = '<option value="{}">{}</option>' addr_enc = mbase32.encode(addr.site_key) from_addr_options.append(option.format(addr.id, addr_enc)) from_addr_options.append("<option value=" ">[Anonymous]</option>") from_addr_options = "".join(from_addr_options) template = templates.dmail_compose[0] template = template.format( csrf_token=dispatcher.client_engine.csrf_token, delete_class="display_none", owner_if_anon=owner_if_anon_id, from_addr_options=from_addr_options, dest_addr=dest_addr_enc, subject=subject, message_text=message_text, **autofocus_fields ) acharset = dispatcher.get_accept_charset() dispatcher.send_content(template, content_type="text/html; charset={}".format(acharset)) elif req == "/address_list": addrs = yield from _list_dmail_addresses(dispatcher) default_id = yield from _load_default_dmail_address_id(dispatcher) csrf_token = dispatcher.client_engine.csrf_token row_template = templates.dmail_address_list_row[0] rows = [] for addr in addrs: site_key_enc = mbase32.encode(addr.site_key) if default_id and addr.id == default_id: set_default_class = "hidden" else: set_default_class = "" if addr.scan_interval: autoscan_link_text = "disable autoscan" autoscan_interval = 0 else: autoscan_link_text = "enable autoscan" autoscan_interval = 60 resp = row_template.format( csrf_token=csrf_token, addr=site_key_enc, addr_dbid=addr.id, set_default_class=set_default_class, autoscan_link_text=autoscan_link_text, autoscan_interval=autoscan_interval, ) rows.append(resp) rows_content = "".join(rows) template = templates.dmail_address_list[0] template = template.format(address_list=rows_content) dispatcher.send_content(template) # Actions. elif req.startswith("/create_tag?"): query = req[12:] qdict = parse_qs(query, keep_blank_values=True) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return tag_name = qdict["tag_name"][0] if not tag_name: dispatcher.send_204() return r = yield from _create_tag(dispatcher, tag_name) redirect = qdict.get("redirect") if r and redirect: dispatcher.send_301(redirect[0]) else: dispatcher.send_204() elif req.startswith("/modify_message_tag?"): query = req[20:] qdict = parse_qs(query, keep_blank_values=True) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return submit = qdict["submit"][0] def processor(sess, dm): if submit == "add_tag": dmail.attach_dmail_tag(sess, dm, qdict["add_tag"][0]) return True elif submit == "move_to_tag": dm.tags.clear() dmail.attach_dmail_tag(sess, dm, qdict["add_tag"][0]) return True elif submit == "remove_tag": if len(dm.tags) <= 1: return False remove_tag = qdict["remove_tag"][0] remove_target = None for tag in dm.tags: if tag.name == remove_tag: remove_target = tag break dm.tags.remove(remove_target) return True else: return False msg_id = qdict["msg_id"][0] dm = yield from _process_dmail_message(dispatcher, msg_id, processor, fetch_tags=True) redirect = qdict.get("redirect") if redirect: dispatcher.send_301(redirect[0]) else: dispatcher.send_204() elif req.startswith("/refresh/"): params = req[9:] p0 = params.index("/") csrf_token = params[:p0] addr_enc = params[p0 + 1 :] if not dispatcher.check_csrf_token(csrf_token): return dmail_address = yield from _load_dmail_address(dispatcher, site_key=mbase32.decode(addr_enc), fetch_keys=True) dispatcher.client_engine.trigger_dmail_scan(dmail_address) dispatcher.send_204() elif req.startswith("/toggle_read/"): params = req[13:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] msg_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dm): dm.read = not dm.read return True yield from _process_dmail_message(dispatcher, msg_dbid, processor) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/toggle_trashed/"): params = req[16:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] msg_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dm): dm.hidden = not dm.hidden return True yield from _process_dmail_message(dispatcher, msg_dbid, processor) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/set_autoscan/"): params = req[14:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) p1 = params.index("/", p0 + 1, pq) csrf_token = params[:p0] addr_id = int(params[p0 + 1 : p1]) interval = int(params[p1 + 1 : pq]) if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, addr): addr.scan_interval = interval return True addr = yield from _process_dmail_address(dispatcher, processor, addr_id, fetch_keys=True) dispatcher.client_engine.update_dmail_autoscan(addr) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/empty_trash/"): params = req[13:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/", 0, pq) csrf_token = params[:p0] addr_enc = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return yield from _empty_trash(dispatcher, addr_enc) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() elif req.startswith("/make_address_default/"): params = req[22:] pq = params.find("?redirect=") if pq != -1: redirect = params[pq + 10 :] else: redirect = None pq = len(params) p0 = params.index("/") csrf_token = params[:p0] addr_dbid = params[p0 + 1 : pq] if not dispatcher.check_csrf_token(csrf_token): return yield from _set_default_dmail_address(dispatcher, addr_dbid) if redirect: dispatcher.send_301(redirect) else: dispatcher.send_204() ##### OLD: elif req == "/create_address": if dispatcher.handle_cache(req): return template = templates.dmail_create_address[0] template = template.format(csrf_token=dispatcher.client_engine.csrf_token) dispatcher.send_content([template, req]) elif req.startswith("/address_config/"): params = req[16:] addr_enc = params dmail_address = yield from _load_dmail_address(dispatcher, site_key=mbase32.decode(addr_enc), fetch_keys=True) content = templates.dmail_address_config[0] content = content.replace("{csrf_token}", dispatcher.client_engine.csrf_token) content = content.replace("${DIFFICULTY}", str(dmail_address.keys[0].difficulty)) content = content.replace("${DMAIL_ADDRESS_SHORT}", addr_enc[:32]) content = content.replace("${DMAIL_ADDRESS}", addr_enc) content = content.replace("${PRIVATE_KEY}", base58.encode(dmail_address.site_privatekey)) content = content.replace("${X}", base58.encode(dmail_address.keys[0].x)) content = content.replace("${TARGET_KEY}", base58.encode(dmail_address.keys[0].target_key)) dispatcher.send_content([content, None]) ##### OLD ACTIONS: elif req.startswith("/create_address/make_it_so?"): query = req[27:] qdict = parse_qs(query, keep_blank_values=True) prefix = qdict["prefix"][0] difficulty = int(qdict["difficulty"][0]) csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return log.info("prefix=[{}].".format(prefix)) privkey, dmail_key, dms, storing_nodes = yield from _create_dmail_address(dispatcher, prefix, difficulty) dmail_key_enc = mbase32.encode(dmail_key) dispatcher.send_partial_content(templates.dmail_frame_start, True) if storing_nodes: dispatcher.send_partial_content(b"SUCCESS<br/>") else: dispatcher.send_partial_content( "PARTIAL SUCCESS<br/>" "<p>Your Dmail site was generated successfully; however," " it failed to be stored on the network. To remedy this," " simply go to your Dmail address page and click the" ' [<a target="_self" href="morphis://.dmail/' 'address_config/{}">Address Settings</a>] link, and then' ' click the "Republish Dmail Site" button.</p>'.format(dmail_key_enc).encode() ) dispatcher.send_partial_content( '<p>New dmail address: <a href="morphis://.dmail/wrapper/' '{addr_enc}">{addr_enc}</a></p>'.format(addr_enc=dmail_key_enc).encode() ) dispatcher.send_partial_content(templates.dmail_frame_end) dispatcher.end_partial_content() elif req.startswith("/save_address_config/publish?"): query = req[29:] qdict = parse_qs(query, keep_blank_values=True) addr_enc = qdict["dmail_address"][0] difficulty = qdict["difficulty"][0] csrf_token = qdict["csrf_token"][0] if not dispatcher.check_csrf_token(csrf_token): return def processor(sess, dmail_address): if difficulty != dmail_address.keys[0].difficulty: dmail_address.keys[0].difficulty = difficulty return True else: return False dmail_address = yield from _process_dmail_address( dispatcher, processor, site_key=mbase32.decode(addr_enc), fetch_keys=True ) 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(difficulty) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) de = dmail.DmailEngine(dispatcher.node.chord_engine.tasks, dispatcher.node.db) storing_nodes = yield from de.publish_dmail_site(private_key, dms) if storing_nodes: dispatcher.send_content( templates.dmail_addr_settings_edit_success_content[0].format(addr_enc, addr_enc[:32]).encode() ) else: dispatcher.send_content( templates.dmail_addr_settings_edit_fail_content[0].format(addr_enc, addr_enc[:32]).encode() ) else: dispatcher.send_error(errcode=400)
def to_old_address(self): rv = hashlib.new('sha256', self.raw_public_key()).digest() rv = hashlib.new('ripemd160', rv).digest() rv = '\x00' + rv rv += hashlib.new('sha256', hashlib.new('sha256', rv).digest()).digest()[0:4] return base58.encode(rv)
def __main(): global loop log.info("mcc running.") parser = argparse.ArgumentParser() parser.add_argument(\ "--address",\ help="The address of the Morphis node to connect to.",\ default="127.0.0.1:4250") parser.add_argument(\ "--create-dmail",\ help="Generate and upload a new dmail site.",\ action="store_true") parser.add_argument(\ "--dburl",\ help="Specify the database url to use.") parser.add_argument(\ "--fetch-dmail", help="Fetch dmail for specified key_id.") parser.add_argument(\ "-i",\ help="Read file as stdin.") parser.add_argument("--nn", type=int,\ help="Node instance number.") parser.add_argument(\ "--prefix",\ help="Specify the prefix for various things (currently --create-dmail"\ ").") parser.add_argument(\ "--scan-dmail",\ help="Scan the network for available dmails.") parser.add_argument(\ "--send-dmail",\ help="Send stdin as a dmail with the specified subject. The"\ " sender and recipients may be specified at the beginning of the"\ " data as with email headers: 'from: ' and 'to: '.") parser.add_argument(\ "--stat",\ help="Report node status.",\ action="store_true") parser.add_argument("-l", dest="logconf",\ help="Specify alternate logging.ini [IF SPECIFIED, THIS MUST BE THE"\ " FIRST PARAMETER!].") parser.add_argument(\ "--dmail-target",\ help="Specify the dmail target to validate dmail against.") parser.add_argument(\ "-x",\ help="Specify the x (Diffie-Hellman private secret) to use.") args = parser.parse_args() # Load or generate client mcc key. key_filename = "data/mcc_key-rsa.mnk" if os.path.exists(key_filename): log.info("mcc private key file found, loading.") client_key = rsakey.RsaKey(filename=key_filename) else: log.info("mcc private key file missing, generating.") client_key = rsakey.RsaKey.generate(bits=4096) client_key.write_private_key_file(key_filename) # Connect a Morphis Client (lightweight Node) instance. mc = client.Client(loop, client_key=client_key, address=args.address) r = yield from mc.connect() if not r: log.warning("Connection failed; exiting.") loop.stop() return dbase = init_db(args) de = dmail.DmailEngine(mc, dbase) log.info("Processing command requests...") if args.stat: r = yield from mc.send_command("stat") print(r.decode("UTF-8"), end='') if args.create_dmail: log.info("Creating and uploading dmail site.") privkey, data_key, dms, storing_nodes =\ yield from de.generate_dmail_address(args.prefix) print("privkey: {}".format(base58.encode(privkey._encode_key()))) print("x: {}".format(base58.encode(sshtype.encodeMpint(dms.dh.x)))) print("dmail address: {}".format(mbase32.encode(data_key))) print("storing_nodes=[{}]."\ .format(base58.encode(privkey._encode_key()))) if args.send_dmail: log.info("Sending dmail.") if args.i: with open(args.i, "rb") as fh: dmail_data = fh.read().decode() else: dmail_data = stdin.read() if log.isEnabledFor(logging.DEBUG): log.debug("dmail_data=[{}].".format(dmail_data)) yield from de.send_dmail_text(args.send_dmail, dmail_data) if args.scan_dmail: log.info("Scanning dmail address.") addr, sig_bits = mutil.decode_key(args.scan_dmail) def key_callback(key): print("dmail key: [{}].".format(mbase32.encode(key))) yield from de.scan_dmail_address(\ addr, sig_bits, key_callback=key_callback) if args.fetch_dmail: log.info("Fetching dmail for key=[{}].".format(args.fetch_dmail)) key = mbase32.decode(args.fetch_dmail) if args.x: l, x_int = sshtype.parseMpint(base58.decode(args.x)) else: x_int = None dmail_target = args.dmail_target dm, valid_sig = yield from de.fetch_dmail(key, x_int, dmail_target) if not dm: raise Exception("No dmail found.") if not x_int: print("Encrypted dmail data=[\n{}].".format(mutil.hex_dump(dm))) else: print("Subject: {}\n".format(dm.subject)) if dm.sender_pubkey: print("From: {}"\ .format(mbase32.encode(enc.generate_ID(dm.sender_pubkey)))) i = 0 for part in dm.parts: print("DmailPart[{}]:\n mime-type=[{}]\n data=[{}]\n"\ .format(i, part.mime_type, part.data)) i += 1 log.info("Disconnecting.") yield from mc.disconnect() loop.stop()
def __main(): global loop log.info("mcc running.") parser = argparse.ArgumentParser() parser.add_argument(\ "--address",\ help="The address of the Morphis node to connect to.",\ default="127.0.0.1:4250") parser.add_argument(\ "--create-dmail",\ help="Generate and upload a new dmail site.",\ action="store_true") parser.add_argument(\ "--dburl",\ help="Specify the database url to use.") parser.add_argument(\ "--fetch-dmail", help="Fetch dmail for specified key_id.") parser.add_argument(\ "-i",\ help="Read file as stdin.") parser.add_argument("--nn", type=int,\ help="Node instance number.") parser.add_argument(\ "--prefix",\ help="Specify the prefix for various things (currently --create-dmail"\ ").") parser.add_argument(\ "--scan-dmail",\ help="Scan the network for available dmails.") parser.add_argument(\ "--send-dmail",\ help="Send stdin as a dmail with the specified subject. The"\ " sender and recipients may be specified at the beginning of the"\ " data as with email headers: 'from: ' and 'to: '.") parser.add_argument(\ "--stat",\ help="Report node status.",\ action="store_true") parser.add_argument("-l", dest="logconf",\ help="Specify alternate logging.ini [IF SPECIFIED, THIS MUST BE THE"\ " FIRST PARAMETER!].") parser.add_argument(\ "--dmail-target",\ help="Specify the dmail target to validate dmail against.") parser.add_argument(\ "-x",\ help="Specify the x (Diffie-Hellman private secret) to use.") args = parser.parse_args() # Load or generate client mcc key. key_filename = "data/mcc_key-rsa.mnk" if os.path.exists(key_filename): log.info("mcc private key file found, loading.") client_key = rsakey.RsaKey(filename=key_filename) else: log.info("mcc private key file missing, generating.") client_key = rsakey.RsaKey.generate(bits=4096) client_key.write_private_key_file(key_filename) # Connect a Morphis Client (lightweight Node) instance. mc = client.Client(loop, client_key=client_key, address=args.address) r = yield from mc.connect() if not r: log.warning("Connection failed; exiting.") loop.stop() return dbase = init_db(args) de = dmail.DmailEngine(mc, dbase) log.info("Processing command requests...") if args.stat: r = yield from mc.send_command("stat") print(r.decode("UTF-8"), end='') if args.create_dmail: log.info("Creating and uploading dmail site.") privkey, data_key, dms =\ yield from de.generate_dmail_address(args.prefix) print("privkey: {}".format(base58.encode(privkey._encode_key()))) print("x: {}".format(base58.encode(sshtype.encodeMpint(dms.dh.x)))) print("dmail address: {}".format(mbase32.encode(data_key))) if args.send_dmail: log.info("Sending dmail.") if args.i: with open(args.i, "rb") as fh: dmail_data = fh.read().decode() else: dmail_data = stdin.read() if log.isEnabledFor(logging.DEBUG): log.debug("dmail_data=[{}].".format(dmail_data)) yield from de.send_dmail_text(args.send_dmail, dmail_data) if args.scan_dmail: log.info("Scanning dmail address.") addr, sig_bits = mutil.decode_key(args.scan_dmail) def key_callback(key): print("dmail key: [{}].".format(mbase32.encode(key))) yield from de.scan_dmail_address(\ addr, sig_bits, key_callback=key_callback) if args.fetch_dmail: log.info("Fetching dmail for key=[{}].".format(args.fetch_dmail)) key = mbase32.decode(args.fetch_dmail) if args.x: l, x_int = sshtype.parseMpint(base58.decode(args.x)) else: x_int = None dmail_target = args.dmail_target dm, valid_sig = yield from de.fetch_dmail(key, x_int, dmail_target) if not dm: raise Exception("No dmail found.") if not x_int: print("Encrypted dmail data=[\n{}].".format(mutil.hex_dump(dm))) else: print("Subject: {}\n".format(dm.subject)) if dm.sender_pubkey: print("From: {}"\ .format(mbase32.encode(enc.generate_ID(dm.sender_pubkey)))) i = 0 for part in dm.parts: print("DmailPart[{}]:\n mime-type=[{}]\n data=[{}]\n"\ .format(i, part.mime_type, part.data)) i += 1 log.info("Disconnecting.") yield from mc.disconnect() loop.stop()
def base58(self): data= chr(self.version) + self.hash data += shasha(data)[0:4] return base58.encode(data)
def __serve_get(handler, rpath, done_event): if len(rpath) == len(s_dmail): handler._send_content(pages.dmail_page_content) else: req = rpath[len(s_dmail):] log.info("req=[{}].".format(req)) if req == "/css": handler._send_content(\ pages.dmail_css_content, content_type="text/css") elif req == "/address_list": handler._send_partial_content( pages.dmail_page_content__f1_start, True) site_keys = yield from _list_dmail_addresses(handler) for dbid, site_key in site_keys: site_key_enc = mbase32.encode(site_key) resp = """<span class="nowrap">[<a href="addr/{}">view</a>]"""\ """ {}</span><br/>"""\ .format(site_key_enc, site_key_enc) handler._send_partial_content(resp) handler._send_partial_content(pages.dmail_page_content__f1_end) handler._end_partial_content() elif req.startswith("/compose/form"): dest_addr_enc = req[14:] if len(req) > 14 else "" handler._send_partial_content(\ pages.dmail_compose_dmail_form_start, True) site_keys = yield from _list_dmail_addresses(handler) for dbid, site_key in site_keys: site_key_enc = mbase32.encode(site_key) sender_element = """<option value="{}">{}</option>"""\ .format(dbid, site_key_enc) handler._send_partial_content(sender_element) handler._send_partial_content(\ "<option value="">[Anonymous]</option>") handler._send_partial_content(\ pages.dmail_compose_dmail_form_end.replace(\ b"${DEST_ADDR}", dest_addr_enc.encode())) handler._end_partial_content() elif req.startswith("/compose"): from_addr = req[9:] if len(req) > 9 else "" if from_addr: iframe_src = "../compose/form/{}".format(from_addr).encode() else: iframe_src = "compose/form".encode() content = pages.dmail_compose_dmail_content[0].replace(\ b"${IFRAME_SRC}", iframe_src) handler._send_content([content, None]) elif req.startswith("/addr/view/"): addr_enc = req[11:] start = pages.dmail_addr_view_start.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS_SHORT}", addr_enc[:32].encode()) handler._send_partial_content(start, True) handler._send_partial_content(pages.dmail_addr_view_end) handler._end_partial_content() elif req.startswith("/addr/settings/edit/publish?"): query = req[28:] qdict = urllib.parse.parse_qs(query, keep_blank_values=True) addr_enc = qdict["dmail_address"][0] difficulty = qdict["difficulty"][0] def processor(dmail_address): if difficulty != dmail_address.keys[0].difficulty: dmail_address.keys[0].difficulty = difficulty return True else: return False dmail_address = yield from\ _process_dmail_address(\ handler, mbase32.decode(addr_enc), processor) dh = dhgroup14.DhGroup14() dh.x = sshtype.parseMpint(dmail_address.keys[0].x)[1] dh.generate_e() dms = dmail.DmailSite() root = dms.root root["target"] =\ mbase32.encode(dmail_address.keys[0].target_key) root["difficulty"] = int(difficulty) root["ssm"] = "mdh-v1" root["sse"] = base58.encode(sshtype.encodeMpint(dh.e)) private_key = rsakey.RsaKey(privdata=dmail_address.site_privatekey) r = yield from\ handler.node.chord_engine.tasks.send_store_updateable_key(\ dms.export(), private_key,\ version=int(time.time()*1000), store_key=True) handler._send_content(\ pages.dmail_addr_settings_edit_success_content[0]\ .format(addr_enc, addr_enc[:32]).encode()) elif req.startswith("/addr/settings/edit/"): addr_enc = req[20:] dmail_address = yield from\ _load_dmail_address(handler, mbase32.decode(addr_enc)) content = pages.dmail_addr_settings_edit_content[0].replace(\ b"${DIFFICULTY}",\ str(dmail_address.keys[0].difficulty).encode()) content = content.replace(\ b"${DMAIL_ADDRESS_SHORT}", addr_enc[:32].encode()) content = content.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) content = content.replace(\ b"${PRIVATE_KEY}",\ base58.encode(dmail_address.site_privatekey).encode()) content = content.replace(\ b"${X}", base58.encode(dmail_address.keys[0].x).encode()) content = content.replace(\ b"${TARGET_KEY}",\ base58.encode(dmail_address.keys[0].target_key).encode()) handler._send_content([content, None]) elif req.startswith("/addr/settings/"): addr_enc = req[15:] content = pages.dmail_addr_settings_content[0].replace(\ b"${IFRAME_SRC}",\ "edit/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/addr/"): addr_enc = req[6:] if log.isEnabledFor(logging.INFO): log.info("Viewing dmail address [{}].".format(addr_enc)) content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "view/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/tag/view/list/"): params = req[15:] p0 = params.index('/') tag = params[:p0] addr_enc = params[p0+1:] if log.isEnabledFor(logging.INFO): log.info("Viewing dmails with tag [{}] for address [{}]."\ .format(tag, addr_enc)) start = pages.dmail_tag_view_list_start.replace(\ b"${TAG_NAME}", tag.encode()) #FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. start = start.replace(b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS2}",\ "{}...".format(addr_enc[:32]).encode()) handler._send_partial_content(start, True) yield from\ _list_dmails_for_tag(handler, mbase32.decode(addr_enc), tag) handler._send_partial_content(pages.dmail_tag_view_list_end) handler._end_partial_content() elif req.startswith("/tag/view/"): params = req[10:] content = pages.dmail_tag_view_content[0].replace(\ b"${IFRAME_SRC}", "../list/{}".format(params).encode()) handler._send_content(content) elif req.startswith("/scan/list/"): addr_enc = req[11:] if log.isEnabledFor(logging.INFO): log.info("Viewing inbox for dmail address [{}]."\ .format(addr_enc)) start = pages.dmail_inbox_start.replace(\ b"${DMAIL_ADDRESS}", addr_enc.encode()) start = start.replace(\ b"${DMAIL_ADDRESS2}", "{}...".format(addr_enc[:32]).encode()) handler._send_partial_content(start, True) addr, significant_bits = mutil.decode_key(addr_enc) yield from _scan_new_dmails(handler, addr, significant_bits) handler._send_partial_content(pages.dmail_inbox_end) handler._end_partial_content() elif req.startswith("/scan/"): addr_enc = req[6:] content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "list/{}".format(addr_enc).encode()) handler._send_content([content, None]) elif req.startswith("/fetch/view/"): keys = req[12:] p0 = keys.index('/') dmail_addr_enc = keys[:p0] dmail_key_enc = keys[p0+1:] dmail_addr = mbase32.decode(dmail_addr_enc) dmail_key = mbase32.decode(dmail_key_enc) dm = yield from _load_dmail(handler, dmail_key) if dm: valid_sig = dm.sender_valid else: dm, valid_sig =\ yield from _fetch_dmail(handler, dmail_addr, dmail_key) dmail_text = _format_dmail(dm, valid_sig) handler._send_content(\ dmail_text.encode(), content_type="text/plain") elif req.startswith("/fetch/panel/mark_as_read/"): req_data = req[26:] p0 = req_data.index('/') dmail_key_enc = req_data[p0+1:] dmail_key = mbase32.decode(dmail_key_enc) def processor(dmail): dmail.read = not dmail.read return True yield from _process_dmail_message(handler, dmail_key, processor) handler._send_204() elif req.startswith("/fetch/panel/trash/"): req_data = req[20:] p0 = req_data.index('/') dmail_key_enc = req_data[p0+1:] dmail_key = mbase32.decode(dmail_key_enc) def processor(dmail): dmail.hidden = not dmail.hidden return True yield from _process_dmail_message(handler, dmail_key, processor) handler._send_204() elif req.startswith("/fetch/panel/"): req_data = req[13:] content = pages.dmail_fetch_panel_content[0].replace(\ b"${DMAIL_IDS}", req_data.encode()) handler._send_content([content, None]) elif req.startswith("/fetch/wrapper/"): req_data = req[15:] content = pages.dmail_fetch_wrapper[0].replace(\ b"${IFRAME_SRC}",\ "../../view/{}"\ .format(req_data).encode()) #FIXME: This is getting inefficient now, maybe time for Flask or # something like it. Maybe we can use just it's template renderer. content = content.replace(\ b"${IFRAME2_SRC}",\ "../../panel/{}"\ .format(req_data).encode()) handler._send_content([content, None]) elif req.startswith("/fetch/"): req_data = req[7:] content = pages.dmail_address_page_content[0].replace(\ b"${IFRAME_SRC}", "../wrapper/{}".format(req_data).encode()) handler._send_content([content, None]) elif req == "/create_address": handler._send_content(pages.dmail_create_address_content) elif req == "/create_address/form": handler._send_content(pages.dmail_create_address_form_content) elif req.startswith("/create_address/make_it_so?"): query = req[27:] qdict = urllib.parse.parse_qs(query, keep_blank_values=True) prefix = qdict["prefix"][0] difficulty = int(qdict["difficulty"][0]) log.info("prefix=[{}].".format(prefix)) privkey, dmail_key, dms =\ yield from _create_dmail_address(handler, prefix, difficulty) dmail_key_enc = mbase32.encode(dmail_key) handler._send_partial_content(pages.dmail_frame_start, True) handler._send_partial_content(b"SUCCESS<br/>") handler._send_partial_content(\ """<p>New dmail address: <a href="../addr/{}">{}</a></p>"""\ .format(dmail_key_enc, dmail_key_enc).encode()) handler._send_partial_content(pages.dmail_frame_end) handler._end_partial_content() else: handler._handle_error()
def wallet(self): data= chr(self.version)+convert.bytesfromnum(self.privkey) data += shasha(data)[:4] return base58.encode(data)