Пример #1
0
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
Пример #2
0
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'])
Пример #3
0
    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
Пример #4
0
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
Пример #5
0
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'])
Пример #6
0
    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)
Пример #7
0
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
Пример #8
0
    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
Пример #9
0
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
Пример #10
0
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
Пример #11
0
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
Пример #12
0
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
Пример #13
0
 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
Пример #14
0
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)
Пример #15
0
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)
Пример #16
0
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)
Пример #17
0
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]
Пример #18
0
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]
Пример #19
0
    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))
Пример #20
0
    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))
Пример #21
0
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)
Пример #22
0
    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))
Пример #23
0
    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
Пример #24
0
    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
Пример #25
0
    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))
Пример #26
0
    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
Пример #27
0
    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
Пример #28
0
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
Пример #29
0
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]
Пример #30
0
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]
Пример #31
0
    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))
Пример #32
0
    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))
Пример #33
0
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)
Пример #34
0
    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()
Пример #35
0
    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)
Пример #36
0
    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()
Пример #37
0
    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
Пример #38
0
    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
Пример #39
0
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]
Пример #40
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()
Пример #41
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 =\
            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()