def address_to_public_key_hash(address): binary_address = decode(address) # remove the 4 checksum bytes extended_address = binary_address[:-4] # remove version byte: 0x00 for Main Network hash160_address = extended_address[1:] return hash160_address
def bip32_get_public_key(bip32_private_key): decoded = base58.decode(bip32_private_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PRIVATE_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4-33] != 0: raise Exception("invalid bip32 key") private_key = decoded_bytes[-4-32:-4] r = decoded_bytes[4:-4-33] + compress(get_public_key(private_key)) coin = None for coin_name in COINS: for network in ('main', 'test'): if 'bip32_private' in COINS[coin_name][network] and decoded_bytes[0:4] == COINS[coin_name][network]['bip32_private']: coin = COINS[coin_name][network] break if coin is None: raise Exception("unknown extended private key") return base58_check(r, version_bytes=coin['bip32_public'])
def send_dmail_text(self, subject, message_text): if message_text.startswith("from: "): p0 = message_text.find('\n') m_from_asymkey = rsakey.RsaKey(\ privdata=base58.decode(message_text[6:p0])) p0 += 1 else: p0 = 0 m_from_asymkey = None m_dest_ids = [] while message_text.startswith("to: ", p0): p1 = message_text.find('\n') m_dest_enc = message_text[p0+4:p1] m_dest_id, sig_bits = mutil.decode_key(m_dest_enc) m_dest_ids.append((m_dest_enc, m_dest_id, sig_bits)) p0 = p1 + 1 date = mutil.utc_datetime() if message_text[p0] == '\n': p0 += 1 message_text = message_text[p0:] storing_nodes = yield from self.send_dmail(\ m_from_asymkey, m_dest_ids, subject, date, message_text) return storing_nodes
def decode_base58_private_key(src): decoded = base58.decode(src) try: # version + private_key + checksum decoded_bytes = decoded.to_bytes(37, 'big') version_byte = decoded_bytes[0] private_key = decoded_bytes[1:33] compressed_byte = 0 checksum = decoded_bytes[33:] src = bytes([version_byte]) + private_key except OverflowError: # version + private_key + compression + checksum decoded_bytes = decoded.to_bytes(38, 'big') version_byte = decoded_bytes[0] private_key = decoded_bytes[1:33] compressed_byte = decoded_bytes[33] checksum = decoded_bytes[34:] src = bytes([version_byte]) + private_key + bytes([compressed_byte]) s = hash256(src) if s[0:4] != checksum: raise Exception("invalid private key") return version_byte, compressed_byte == 0x01, private_key
def bip32_get_public_key(bip32_private_key): decoded = base58.decode(bip32_private_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PRIVATE_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4 - 33] != 0: raise Exception("invalid bip32 key") private_key = decoded_bytes[-4 - 32:-4] r = decoded_bytes[4:-4 - 33] + compress(get_public_key(private_key)) coin = None for coin_name in COINS: for network in ('main', 'test'): if 'bip32_private' in COINS[coin_name][network] and decoded_bytes[ 0:4] == COINS[coin_name][network]['bip32_private']: coin = COINS[coin_name][network] break if coin is None: raise Exception("unknown extended private key") return base58_check(r, version_bytes=coin['bip32_public'])
def get_private_key(self, version=None, change=True): if change: address = self.__rpc.getrawchangeaddress() else: address = self.__rpc.getnewaddress() private_key = self.__rpc.dumpprivkey(address) decoded = binascii.hexlify(base58.decode(private_key)) if version: if version != decoded[0:2]: raise ValueError("Unexpected private key version") compressed = decoded[-2:] if compressed != u'01': raise ValueError("Expected compressed bit to be set") decoded = decoded[2:-2] if len(decoded) != 64: raise ValueError("Unexpected private key length") secexp = int(decoded, 16) return ecdsa.SigningKey.from_secret_exponent(secexp, ecdsa.curves.SECP256k1)
def test_decode(): """should take a base58 encoded bitcoin address and return raw bytes for that address""" actual = base58.decode("14CAW1CobqYjs14boGNUwy5ZGNDRXjomFW") expected = "2304e21839bb9729ec18671893e4da55cb28a791".decode("hex") assert actual == expected
def send_dmail_text(self, subject, message_text): if message_text.startswith("from: "): p0 = message_text.find('\n') m_from_asymkey = rsakey.RsaKey(\ privdata=base58.decode(message_text[6:p0])) p0 += 1 else: p0 = 0 m_from_asymkey = None m_dest_ids = [] while message_text.startswith("to: ", p0): p1 = message_text.find('\n') m_dest_enc = message_text[p0 + 4:p1] m_dest_id, sig_bits = mutil.decode_key(m_dest_enc) m_dest_ids.append((m_dest_enc, m_dest_id, sig_bits)) p0 = p1 + 1 date = mutil.utc_datetime() if message_text[p0] == '\n': p0 += 1 message_text = message_text[p0:] storing_nodes = 0 for dest_id in m_dest_ids: storing_nodes += yield from self.send_dmail(\ m_from_asymkey, dest_id, subject, date, message_text) return storing_nodes
def getHashLength(hashstr): hashint = base58.decode(hashstr) hashbytes = int_to_byte_array(hashint) if len(hashbytes) < 3: raise Exception("Multihash must be at least 3 bytes") #hash_func_id = hashbytes[0] hash_length = int(hashbytes[1]) return hash_length
def get_link(self, key): try: id = base58.decode(key) except: return "" instance = self.get_by_id(id) if instance is None: return "" return instance.link
def parse_id(url): code = findall(r'flic\.kr\/p\/([1-9a-km-zA-HJ-NP-Z]+)', url) if code: return base58.decode(code[0]) code = findall(r'flickr\.com\/photos\/[\w\-\@]+\/(\d+)', url) if code: return code[0] raise InvalidUrlError(url)
def parseHash(hashstr): hashint = base58.decode(hashstr) hashbytes = int_to_byte_array(hashint) if len(hashbytes) < 3: raise Exception("Multihash must be at least 3 bytes") hash_func_id = hashbytes[0] hash_length = hashbytes[1] hash_contents = hashbytes[2:hash_length + 2] return bytes_to_long(hash_contents)
def parseHash(hashstr): hashint = base58.decode(hashstr) hashbytes = int_to_byte_array(hashint) if len(hashbytes) < 3: raise Exception("Multihash must be at least 3 bytes") hash_func_id = hashbytes[0] hash_length = hashbytes[1] hash_contents = hashbytes[2:hash_length+2] return bytes_to_long(hash_contents)
def bip32_extract_public_key(bip32_public_key): decoded = base58.decode(bip32_public_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PUBLIC_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4 - 33] not in (0x02, 0x03): raise Exception("invalid bip32 key") return decoded_bytes[-4 - 33:-4]
def bip32_extract_private_key(bip32_private_key): decoded = base58.decode(bip32_private_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PRIVATE_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4 - 33] != 0: raise Exception("invalid bip32 key") return decoded_bytes[-4 - 32:-4]
def do_storeukeyenc(self, arg): "<KEY> <DATA> <VERSION> <STOREKEY> [PATH] store base58 encoded DATA" " with base58 encoded private KEY." args = arg.split(' ') key = rsakey.RsaKey(privdata=base58.decode(args[0])) data = base58.decode(args[1]) version = int(args[2]) storekey = bool(args[3]) path = args[4] if len(args) > 4 else None def key_callback(data_key): self.writeln("data_key=[{}].".format(mbase32.encode(data_key))) start = datetime.today() yield from multipart.store_data(\ self.peer.engine, data, privatekey=key, path=path,\ version=version, key_callback=key_callback) diff = datetime.today() - start self.writeln("multipart.store_data(..) took: {}.".format(diff))
def do_storedataenc(self, arg): "<data> store base58 encoded data." data = base58.decode(arg) def key_callback(data_key): self.writeln("data_key=[{}].".format(mbase32.encode(data_key))) start = datetime.today() yield from multipart.store_data(self.peer.engine, data, key_callback=key_callback) diff = datetime.today() - start self.writeln("multipart.store_data(..) took: {}.".format(diff))
def get_file(data_id): try: key = base58.decode(data_id) except: return None file_key = FileKey.get_by_id(key) if file_key is None: return None # Calling put() on the filekey updates the "last seen" time of the file. file_key.put() return blobstore.BlobInfo(file_key.blob_key)
def frombase58(b58): self= Address() data= base58.decode(b58) if len(data)>25: print("addr len > 25: %s" % data.encode("hex")) raise Exception("Invalid base58 length") if len(data)<25: data= "\x00" * (25-len(data)) self.version= ord(data[0]) self.hash= data[1:21] if shasha(data[0:21])[:4] != data[21:]: print("addr: %s: %s != %s" % (data[:21].encode("hex"), data[21:].encode("hex"), shasha(data[0:21])[:4])) raise Exception("Invalid base58 checksum") return self
def frombase58(b58): self= Address() data= base58.decode(b58) if len(data)>25: print "addr len > 25: %s" % data.encode("hex") raise Exception("Invalid base58 length") if len(data)<25: data= "\x00" * (25-len(data)) self.version= ord(data[0]) self.hash= data[1:21] if shasha(data[0:21])[:4] != data[21:]: print "addr: %s: %s != %s" % (data[:21].encode("hex"), data[21:].encode("hex"), shasha(data[0:21])[:4]) raise Exception("Invalid base58 checksum") return self
def do_storedataenc(self, arg): "<data> store base58 encoded data." data = base58.decode(arg) def key_callback(data_key): self.writeln("data_key=[{}].".format(mbase32.encode(data_key))) start = datetime.today() yield from multipart.store_data(\ self.peer.engine, data, key_callback=key_callback) diff = datetime.today() - start self.writeln("multipart.store_data(..) took: {}.".format(diff))
def fromwallet(b58): self= PrivateKey() data= base58.decode(b58) if not len(data) in (37, 38): print "wallet len != 37/38: %s" % data.encode("hex") raise Exception("Invalid wallet length") self.version= ord(data[0]) self.privkey= convert.numfrombytes(data[1:33]) if len(data)==38: # todo: ?? what is this for? self.compressed= ord(data[33]) if shasha(data[:-4])[:4] != data[-4:]: print "wallet: %s: %s != %s" % (data[:33].encode("hex"), data[33:].encode("hex"), shasha(data[0:33])[:4]) raise Exception("Invalid base58 checksum") return self
def fromwallet(b58): self= PrivateKey() data= base58.decode(b58) if not len(data) in (37, 38): print("wallet len != 37/38: %s" % data.encode("hex")) raise Exception("Invalid wallet length") self.version= ord(data[0:1]) self.privkey= convert.numfrombytes(data[1:33]) if len(data)==38: # todo: ?? what is this for? self.compressed= ord(data[33]) if shasha(data[:-4])[:4] != data[-4:]: print("wallet: %s: %s != %s" % (data[:33].encode("hex"), data[33:].encode("hex"), shasha(data[0:33])[:4])) raise Exception("Invalid base58 checksum") return self
def is_valid_wallet(wallet): try: pubAddrHex = base58.decode(wallet) pubAddrChksum = pubAddrHex[-8:] pubAddrForHash = pubAddrHex[:-8] k = sha3.keccak_256() k.update(unhexlify(pubAddrForHash)) pubAddrHash = k.hexdigest() pubAddrChksum2 = pubAddrHash[:8] if pubAddrChksum2 == pubAddrChksum: #print("True: %s" % wallet) return True else: #print("False: %s" % wallet) return False except Exception: #print("False: %s" % wallet) return False
def bip32_extract_private_key(bip32_private_key): decoded = base58.decode(bip32_private_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PRIVATE_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4-33] != 0: raise Exception("invalid bip32 key") return decoded_bytes[-4-32:-4]
def bip32_extract_public_key(bip32_public_key): decoded = base58.decode(bip32_public_key) decoded_bytes = decoded.to_bytes(82, 'big') if len(decoded_bytes) != 82: raise Exception("invalid bip32 key") c = hash256(decoded_bytes[0:78]) if c[0:4] != decoded_bytes[78:]: raise Exception("invalid bip32 key") if decoded_bytes[0:4] not in BIP32_PUBLIC_KEY_BYTES: raise Exception("invalid bip32 key") if decoded_bytes[-4-33] not in (0x02, 0x03): raise Exception("invalid bip32 key") return decoded_bytes[-4-33:-4]
def do_storetargetedblockenc(self, arg): "<data> store base58 encoded targeted block." args = arg.split(' ') data = base58.decode(args[0]) store_key = bool(args[1]) if len(args) == 2 else False def key_callback(data_key): self.writeln("data_key=[{}].".format(mbase32.encode(data_key))) start = datetime.today() storing_nodes =\ yield from self.peer.engine.tasks.send_store_targeted_data(\ data, store_key=store_key, key_callback=key_callback) diff = datetime.today() - start self.writeln("storing_nodes=[{}].".format(storing_nodes)) self.writeln("send_store_targeted_data(..) took: {}.".format(diff))
def try_decode(text): valid = all(' ' <= c <= '~' or ord(c) in (0, 4, 10, 13) for c in text) print(f'{"Valid" if valid else "Weird"} ASCII: "{pprint(text)}"') if all('0' <= c <= '1' for c in text.lower()): print('Binary values or morse code.') yield bytes(int(''.join(bits), 2) for bits in grouper(text, 8, '0')) yield from morse.try_decode(text) elif all('0' <= c <= '7' for c in text.lower()): print('Octal values.') raise NotImplementedError elif all('0' <= c <= '9' or 'a' <= c <= 'f' for c in text.lower()): print('Hexadecimal values.') raise NotImplementedError elif all('2' <= c <= '7' or 'A' <= c <= 'Z' or c == '=' for c in text): try: decoded = base64.b32decode(text) print(f'Base32-decoded: {pprint(decoded)}') yield decoded except binascii.Error: print('Not base32-decodable.') elif all('0' <= c <= '9' or 'a' <= c <= 'z' or c in '=/+' for c in text.lower()): if not any(c in '0OlI+/' for c in text): decoded = base58.decode(text, 'BTC') print(f'Base58-decoded (BTC): {pprint(decoded)}') yield decoded decoded = base58.decode(text, 'RIPPLE') print(f'Base58-decoded (RIPPLE): {pprint(decoded)}') yield decoded try: decoded = base64.b64decode(text) print(f'Base64-decoded: {pprint(decoded)}') yield decoded except binascii.Error: print('Not base64-decodable.') else: try: decoded = base64.b64decode(text) print(f'Base85-decoded: {pprint(decoded)}') yield decoded except binascii.Error: print('Not base64-decodable.') elif all('!' <= c <= 'u' or c == '~' for c in text): if text.startswith('<~') and text.endswith('~>'): # Adobe-style Ascii85 try: decoded = base64.a85decode(text, adobe=True) print(f'Ascii85-decoded (Adobe): {pprint(decoded)}') yield decoded except ValueError: print('Not Ascii85-decodable (Adobe).') else: try: decoded = base64.b85decode(text) print(f'Base85-decoded: {pprint(decoded)}') yield decoded except ValueError: print('Not base85-decodable.') try: decoded = base64.a85decode(text) print(f'Ascii85-decoded: {pprint(decoded)}') yield decoded except ValueError: print('Not Ascii85-decodable.') elif '\r' in text or '\n' in text and ' ' not in text: print('Newlines detected: stripping them out.') yield text.translate(str.maketrans('', '', '\r\n')).encode() else: print('Just plain ASCII perhaps? Printing in full:') print(text)
def _do_POST(self, rpath): log.info("POST; rpath=[{}].".format(rpath)) if rpath != ".upload/upload": yield from maalstroom.dmail.serve_post(self, rpath) return if not self.connection_count: self.send_error("No connected nodes; cannot upload to the"\ " network.") return if log.isEnabledFor(logging.DEBUG): log.debug("headers=[{}].".format(self.handler.headers)) version = None path = None mime_type = None if self.handler.headers["Content-Type"]\ == "application/x-www-form-urlencoded": log.debug("Content-Type=[application/x-www-form-urlencoded].") data = yield from self.read_request() privatekey = None else: if log.isEnabledFor(logging.DEBUG): log.debug("Content-Type=[{}]."\ .format(self.handler.headers["Content-Type"])) data = yield from self.read_request() form = cgi.FieldStorage(\ fp=io.BytesIO(data),\ headers=self.handler.headers,\ environ={\ "REQUEST_METHOD": "POST",\ "CONTENT_TYPE": self.handler.headers["Content-Type"]}) if log.isEnabledFor(logging.DEBUG): log.debug("form=[{}].".format(form)) formelement = form["fileToUpload"] filename = formelement.filename data = formelement.file.read() if log.isEnabledFor(logging.INFO): log.info("filename=[{}].".format(filename)) privatekey = form["privateKey"].value if privatekey and privatekey != "${PRIVATE_KEY}": if log.isEnabledFor(logging.INFO): log.info("privatekey=[{}].".format(privatekey)) privatekey = base58.decode(privatekey) privatekey = rsakey.RsaKey(privdata=privatekey) path = form["path"].value.encode() version = form["version"].value if not version: version = 0 else: version = int(version) mime_type = form["mime_type"].value else: privatekey = None if log.isEnabledFor(logging.DEBUG): log.debug("data=[{}].".format(data)) if not privatekey: assert not version and not path and not mime_type try: key_callback = KeyCallback() yield from multipart.store_data(\ self.node.chord_engine, data, privatekey=privatekey,\ path=path, version=version, key_callback=key_callback,\ mime_type=mime_type) except asyncio.TimeoutError: self.send_error(errcode=408) except Exception as e: log.exception("send_store_data(..)") self.send_exception(e) if key_callback.data_key: enckey = mbase32.encode(key_callback.data_key) if privatekey and path: url = "{}{}/{}"\ .format(\ self.handler.maalstroom_url_prefix_str,\ enckey,\ path.decode("UTF-8")) else: url = "{}{}"\ .format(\ self.handler.maalstroom_url_prefix_str,\ enckey) if privatekey: message = '<a id="key" href="{}">updateable key link</a>'\ .format(url) if key_callback.referred_key: message +=\ '<br/><a id="referred_key" href="{}{}">perma link</a>'\ .format(\ self.handler.maalstroom_url_prefix_str,\ mbase32.encode(key_callback.referred_key)) else: message = '<a id="key" href="{}">perma link</a>'.format(url) self.send_response(200) self.send_header("Content-Type", "text/html") self.send_header("Content-Length", len(message)) self.end_headers() self.write(bytes(message, "UTF-8")) self.finish_response()
def do_POST(self): self.__prepare_for_request() rpath = self.path[1:] connection_cnt = self._get_connection_count() if not connection_cnt: self._send_error("No connected nodes; cannot upload to the"\ " network.") return log.info("POST; rpath=[{}].".format(rpath)) if rpath != ".upload/upload": pages.dmail.serve_post(self, rpath) return if log.isEnabledFor(logging.DEBUG): log.info(self.headers) if self.headers["Content-Type"] == "application/x-www-form-urlencoded": log.debug("Content-Type=[application/x-www-form-urlencoded].") data = self.rfile.read(int(self.headers["Content-Length"])) privatekey = None else: if log.isEnabledFor(logging.DEBUG): log.debug("Content-Type=[{}]."\ .format(self.headers["Content-Type"])) form = cgi.FieldStorage(\ fp=self.rfile,\ headers=self.headers,\ environ={\ "REQUEST_METHOD": "POST",\ "CONTENT_TYPE": self.headers["Content-Type"]}) if log.isEnabledFor(logging.DEBUG): log.debug("form=[{}].".format(form)) formelement = form["fileToUpload"] filename = formelement.filename data = formelement.file.read() if log.isEnabledFor(logging.INFO): log.info("filename=[{}].".format(filename)) try: privatekey = form["privateKey"].value if privatekey == "${PRIVATE_KEY}": raise KeyError() if log.isEnabledFor(logging.INFO): log.info("privatekey=[{}].".format(privatekey)) privatekey = base58.decode(privatekey) privatekey = rsakey.RsaKey(privdata=privatekey) path = form["path"].value.encode() version = form["version"].value if not version: version = 0 else: version = int(version) mime_type = form["mime_type"].value except KeyError: privatekey = None if log.isEnabledFor(logging.DEBUG): log.debug("data=[{}].".format(data)) data_rw = DataResponseWrapper() if privatekey: node.loop.call_soon_threadsafe(\ asyncio.async, _send_store_data(\ data, data_rw, privatekey, path, version, mime_type)) else: node.loop.call_soon_threadsafe(\ asyncio.async, _send_store_data(data, data_rw)) data_rw.is_done.wait() if data_rw.data_key: enckey = mbase32.encode(data_rw.data_key) if privatekey and path: url = "{}{}/{}"\ .format(\ self.maalstroom_url_prefix.decode(),\ enckey,\ path.decode("UTF-8")) else: url = "{}{}"\ .format(\ self.maalstroom_url_prefix.decode(),\ enckey) message = '<a href="{}">perma link</a>'.format(url) self.send_response(200) self.send_header("Content-Type", "text/html") self.send_header("Content-Length", len(message)) self.end_headers() self.wfile.write(bytes(message, "UTF-8")) else: self._handle_error(data_rw)
def __send_dmail(self, from_asymkey, recipient, dmail): assert type(recipient) is DmailSite root = recipient.root sse = sshtype.parseMpint(base58.decode(root["sse"]))[1] target = root["target"] difficulty = root["difficulty"] dh = dhgroup14.DhGroup14() dh.generate_x() dh.generate_e() dh.f = sse k = dh.calculate_k() target_key = mbase32.decode(target) key = self._generate_encryption_key(target_key, k) dmail_bytes = dmail.encode() m, r = enc.encrypt_data_block(dmail_bytes, key) if m: if r: m = m + r else: m = r dw = DmailWrapper() dw.ssm = _dh_method_name dw.sse = sse dw.ssf = dh.e if from_asymkey: dw.signature = from_asymkey.calc_rsassa_pss_sig(m) else: dw.signature = b'' dw.data_len = len(dmail_bytes) dw.data_enc = m tb = mp.TargetedBlock() tb.target_key = target_key tb.noonce = int(0).to_bytes(64, "big") tb.block = dw tb_data = tb.encode() tb_header = tb_data[:mp.TargetedBlock.BLOCK_OFFSET] if log.isEnabledFor(logging.INFO): log.info(\ "Attempting work on dmail (target=[{}], difficulty=[{}])."\ .format(target, difficulty)) def threadcall(): return brute.generate_targeted_block(\ target_key, difficulty, tb_header,\ mp.TargetedBlock.NOONCE_OFFSET,\ mp.TargetedBlock.NOONCE_SIZE) noonce_bytes = yield from self.loop.run_in_executor(None, threadcall) if log.isEnabledFor(logging.INFO): log.info("Work found noonce [{}].".format(noonce_bytes)) mp.TargetedBlock.set_noonce(tb_data, noonce_bytes) if log.isEnabledFor(logging.INFO): mp.TargetedBlock.set_noonce(tb_header, noonce_bytes) log.info("hash=[{}]."\ .format(mbase32.encode(enc.generate_ID(tb_header)))) key = None def key_callback(val): nonlocal key key = val log.info("Sending dmail to the network.") if log.isEnabledFor(logging.DEBUG): log.debug("dmail block data=[\n{}]."\ .format(mutil.hex_dump(tb_data))) 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 _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 decrypt(k):return encrypt.from_base128(encrypt.decode(k)) def parse_tags(t):return [a.strip() for a in t.split() if len(a.strip())>0]
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()