예제 #1
0
 def __init__(self, root_address: Address, channel_password = ''):
     self.tangle_con = TangleConnector()
     self.root_address = root_address.__str__()
     self.channel_pwd = channel_password
     self.current_write_addr = root_address.__str__()
     self.current_read_addr = root_address.__str__()
     self.trusted_pubkeys = {}
예제 #2
0
class TestTangleConnector(TestCase):
    def setUp(self):
        self.tangle_con = TangleConnector()

    def test_get_node(self):
        res = self.tangle_con.get_node()
        self.assertEqual(res['appName'], 'IRI')

    def test_get_tips(self):
        res = self.tangle_con.get_tips()
        self.assertTrue(res['hashes'])

    def test_get_hashes_from_addr(self):
        addr = Address(
            'CBGEYVNQIBTQFLR999YHPIDSKBBN9FFLDZPAXHWULQDRTFNDHFYEPNEKQOEF9OCKQTPXFRLOCRXMBCOFCODPNDPNPZ'
        )
        tx_list = self.tangle_con.get_hashes_from_addr(addr)
        self.assertTrue(tx_list)

    def test_get_trytes_from_hashes(self):
        tx = TransactionHash(
            b'LFHPLTGTTNCYZRCHHCQCBMGUJKFMEHWUDRMHHRUVWNTERXHVEYKWSMZDRLKSYLBFUVTTOFKOFLJI99999'
        )
        trytes_list = self.tangle_con.get_trytes_from_hashes([tx])
        self.assertTrue(trytes_list)

    def test_get_all_trytes_from_address(self):
        addr = Address(
            'CBGEYVNQIBTQFLR999YHPIDSKBBN9FFLDZPAXHWULQDRTFNDHFYEPNEKQOEF9OCKQTPXFRLOCRXMBCOFCODPNDPNPZ'
        )
        hashes_and_trytes = self.tangle_con.get_all_trytes_from_address(addr)
        self.assertTrue(hashes_and_trytes)

    def test_send_msg_to_addr(self):
        addr = Address(
            'CBGEYVNQIBTQFLR999YHPIDSKBBN9FFLDZPAXHWULQDRTFNDHFYEPNEKQOEF9OCKQTPXFRLOCRXMBCOFCODPNDPNPZ'
        )
        res = self.tangle_con.send_msg_to_addr(addr, 'test_string', 'TESTTAG')
        self.assertNotIn('Error', res.keys())

    def test_get_bundles_from_addr(self):
        addr = Address(
            'CBGEYVNQIBTQFLR999YHPIDSKBBN9FFLDZPAXHWULQDRTFNDHFYEPNEKQOEF9OCKQTPXFRLOCRXMBCOFCODPNDPNPZ'
        )
        res = self.tangle_con.get_bundles_from_addr(addr)
        self.assertTrue(res)

    def test_get_messages_from_bundles(self):
        addr = Address(
            'CBGEYVNQIBTQFLR999YHPIDSKBBN9FFLDZPAXHWULQDRTFNDHFYEPNEKQOEF9OCKQTPXFRLOCRXMBCOFCODPNDPNPZ'
        )
        res = self.tangle_con.get_bundles_from_addr(addr)
        output = self.tangle_con.get_messages_from_bundles(res)
        self.assertTrue(output)
예제 #3
0
class TestTangleConnector(TestCase):
    def setUp(self):
        self.tangle_con = TangleConnector()

    def test_get_node(self):
        res = self.tangle_con.get_node()
        self.assertEqual(res['appName'], 'IRI')

    def test_get_tips(self):
        res = self.tangle_con.get_tips()
        self.assertTrue(res['hashes'])

    def test_get_hashes_from_addr(self):
        addr = Address(
            'DU9DDSX9JOSPNFDTBCHYMLXTSB9YWIJTZZ9OMQSKUEMCGSCOVTXIQAH9WRCMGNVFCSUHPZWYLJZVCMGLAPHMVOBPAX'
        )
        tx_list = self.tangle_con.get_hashes_from_addr(addr)
        self.assertTrue(tx_list)

    def test_get_trytes_from_hashes(self):
        tx = TransactionHash(
            b'LFHPLTGTTNCYZRCHHCQCBMGUJKFMEHWUDRMHHRUVWNTERXHVEYKWSMZDRLKSYLBFUVTTOFKOFLJI99999'
        )
        trytes_list = self.tangle_con.get_trytes_from_hashes([tx])
        self.assertTrue(trytes_list)

    def test_get_all_trytes_from_address(self):
        addr = Address(
            'DU9DDSX9JOSPNFDTBCHYMLXTSB9YWIJTZZ9OMQSKUEMCGSCOVTXIQAH9WRCMGNVFCSUHPZWYLJZVCMGLAPHMVOBPAX'
        )
        hashes_and_trytes = self.tangle_con.get_all_trytes_from_address(addr)
        self.assertTrue(hashes_and_trytes)

    def test_send_msg_to_addr(self):
        addr = Address(
            'DU9DDSX9JOSPNFDTBCHYMLXTSB9YWIJTZZ9OMQSKUEMCGSCOVTXIQAH9WRCMGNVFCSUHPZWYLJZVCMGLAPHMVOBPAX'
        )
        res = self.tangle_con.send_msg_to_addr(addr, 'test_string', 'TESTTAG')
        self.assertNotIn('Error', res.keys())
예제 #4
0
class MAML_Ed25519:

    def __init__(self, root_address: Address, channel_password = ''):
        self.tangle_con = TangleConnector()
        self.root_address = root_address.__str__()
        self.channel_pwd = channel_password
        self.current_write_addr = root_address.__str__()
        self.current_read_addr = root_address.__str__()
        self.trusted_pubkeys = {}

    @staticmethod
    def tryte_hash(msg: str):
        digest = SHA256.new()
        digest.update(msg.encode())
        hash = digest.hexdigest()
        tryte_hash = TryteString.from_unicode(hash)[0:81]
        return tryte_hash.__str__()

    def _find_empty_addr(self):
        check_addr = self.current_read_addr
        while True:
            previous_addr = check_addr
            check_addr = self.tryte_hash(check_addr + self.channel_pwd)
            response = self._get_MAM_from_address(Address(check_addr))
            if not response:
                self.current_write_addr = previous_addr
                break

    def _get_MAM_from_address(self, address: Address):
        # TODO need refactoring and to be able to handle bundles and validate JSONs for MAML protocol
        hashes_and_trytes = self.tangle_con.get_all_trytes_from_address(address)
        if hashes_and_trytes:
            trytes = hashes_and_trytes[list(hashes_and_trytes.keys())[0]]
            tx_json = self.tangle_con.get_json_from_tryte(trytes)
        else:
            return None

        try:
            if not self.trusted_pubkeys:
                is_trusted = True
            elif tx_json['pubkey'] in self.trusted_pubkeys:
                is_trusted = Ed25519Cipher.verify_signature((tx_json['data_payload'] + address.__str__()).encode(),
                                                            tx_json['signature'].encode(),
                                                            Ed25519Cipher.key_from_string(tx_json['pubkey']))
            else:
                is_trusted = False
            
            if self.channel_pwd:
                tx_json['data_payload'] = AESCipher(self.channel_pwd).decrypt(tx_json['data_payload'])
            
            msg = Message(tx_json['data_payload'], tx_json['pubkey'], tx_json['signature'],tx_json['timestamp'])
            response = Response(address.__str__(),
                                self.tryte_hash(address.__str__() + self.channel_pwd),
                                msg, True, is_trusted)
        except:
            # empty response
            response = Response(address.__str__(),
                                      self.tryte_hash(address.__str__()+ self.channel_pwd),
                                      Message(), False, False)
        return response

    def write(self, data: str, pubkey, prikey):
        self._find_empty_addr()
        self.current_write_addr = self.tryte_hash(self.current_write_addr + self.channel_pwd)

        if self.channel_pwd:
            data = AESCipher(self.channel_pwd).encrypt(data).decode()

        msg = Message().finalize(data, self.current_write_addr, pubkey, prikey, int(time.time()) )

        response_tangle = self.tangle_con.send_msg_to_addr(Address(self.current_write_addr),
                                         msg.__str__(),
                                         tag='PYTHONMAML')
        if response_tangle:
            response = Response(self.current_write_addr,
                                self.tryte_hash(self.current_write_addr + self.channel_pwd),
                                msg, True, True)
        else:
            response = None
        return response

    def read(self):
        previous_addr = self.current_read_addr
        self.current_read_addr = self.tryte_hash(self.current_read_addr + self.channel_pwd)
        response = self._get_MAM_from_address(Address(self.current_read_addr))
        if response:
            return response
        else:
            self.current_read_addr = previous_addr
            return None

    def split_channel(self, new_channel_pwd):
        self._find_empty_addr()
        self.channel_pwd = new_channel_pwd
        self.current_read_addr = self.current_write_addr

    def add_trusted_pubkey(self, name: str, pubkey):
        pubkey_str = pubkey.to_ascii(encoding = 'base64').decode()
        if pubkey_str:
            self.trusted_pubkeys[pubkey_str] = name

    def del_trusted_pubkey(self, pubkey_str: str):
        if pubkey_str:
            self.trusted_pubkeys.pop(pubkey_str)
예제 #5
0
 def __init__(self):
     self.tangle_con = TangleConnector()
예제 #6
0
class AuthCommunicator:
    def __init__(self):
        self.tangle_con = TangleConnector()

    def extract_valid_auth_txs(self,
                               raw_messages: Dict) -> List[AuthTransaction]:
        '''
        Extract valid AuthTransactions from list of raw messages
        :param raw_messages: Dict
        :return: List[AuthTransaction]
        '''
        output_auth_tx = []
        for tx_hash, raw_msg in raw_messages.items():
            auth_msg = FactoryAuthMsg.create_auth_msg_from_json(raw_msg['msg'])
            is_valid = auth_msg.validate()
            if is_valid:
                auth_tx = AuthTransaction(tx_hash, raw_msg['address'],
                                          raw_msg['timestamp'],
                                          raw_msg['value'], auth_msg)
                output_auth_tx.append(auth_tx)
        return output_auth_tx

    def filter_valid_auth_txs(self, auth_txs: List[AuthTransaction], pubkeys_list: List[str] = None) \
            -> List[AuthTransaction]:
        '''
        Filter list of AuthTransactions against pubkeys_list.
        If pubkeys_list is not provided, all AuthTransactions pass the filter
        :param auth_txs: List[AuthTransaction]
        :param pubkeys_list: List[str]
        :return: List[AuthTransaction]
        '''
        filtered_auth_txs = []
        for tx in auth_txs:
            is_in_pubkey_list = (pubkeys_list and tx.auth_msg.pubkey
                                 in (pubkeys_list or []))
            if (not pubkeys_list) or is_in_pubkey_list:
                filtered_auth_txs.append(tx)
        return filtered_auth_txs

    def get_auth_txs_from_address(
            self,
            address: Address,
            pubkeys_list: List[str] = None) -> List[AuthTransaction]:
        '''
        Retrieve list of AuthTransaction from address, optionaly filter for some specific pubkeys
        :param address: Address
        :param pubkeys_list: List[str]
        :return: List[AuthTransaction]
        '''
        raw_messages = self.tangle_con.get_all_msg_from_addr_by_bundle(address)
        auth_txs = self.extract_valid_auth_txs(raw_messages)
        return self.filter_valid_auth_txs(auth_txs, pubkeys_list)

    def send_msg(self,
                 auth_msg: AuthMessage,
                 address: Address,
                 tag: str = 'AUTH9MSG') -> AuthTransaction:
        '''
        Send AuthMessage to address
        :param auth_msg: AuthMessage
        :param address: Address
        :param tag: str
        :return: AuthTransaction
        '''
        auth_tx = None
        if auth_msg.validate():
            res = self.tangle_con.send_msg_to_addr(address, auth_msg.to_json(),
                                                   tag)
            if res:
                bundle = res['bundle'].as_json_compatible()[0]
                auth_tx = AuthTransaction(
                    bundle['bundle_hash'].__str__(),
                    address.__str__(),
                    bundle['timestamp'],
                    0,  # value
                    auth_msg)
        return auth_tx

    def send_msg_to_endpoint(self,
                             auth_msg: AuthMessage,
                             pubkey: str,
                             tag: str = 'AUTH9MSG') -> AuthTransaction:
        '''
        Send AuthMessage to the endpoint authenticated by the pubkey
        :param auth_msg: AuthMessage
        :param pubkey: str
        :param tag: str
        :return: AuthTransaction
        '''
        endpoint_address = Address(hash_tryte(pubkey))
        auth_tx = self.send_msg(auth_msg, endpoint_address, tag)
        return auth_tx

    def get_self_auth_txs_from_endpoint(self,
                                        pubkey: str) -> List[AuthTransaction]:
        '''
        Retrieve list of AuthTransaction from endpoint authenticated by the pubkey
        and authored by the same pubkey
        :param address: Address
        :param pubkeys_list: List[str]
        :return: List[AuthTransaction]
        '''
        endpoint_address = Address(hash_tryte(pubkey))
        auth_tx = self.get_auth_txs_from_address(endpoint_address, [pubkey])
        return auth_tx
예제 #7
0
from flask import Flask, jsonify
from flask import render_template_string
from iota import Address
from ciphers import Ed25519Cipher
from mam_lite import hash_tryte, AuthMessage, AuthCommunicator
from tangle_connector import TangleConnector

tangle_con = TangleConnector()
auth_comm = AuthCommunicator()

app = Flask(__name__)

@app.route('/web+iota:/<pubkey>')
def get_certficate(pubkey):
    auth_txs = auth_comm.get_self_auth_txs_from_endpoint(pubkey)
    if auth_txs:
        latest_auth_tx = sorted(auth_txs, key=lambda x: x.timestamp, reverse=True)[0]
        payload = latest_auth_tx.auth_msg.payload
    else:
        payload = f"No transactions from endpoint: {pubkey}"
    return render_template_string(payload)

@app.route('/submit_page')
def submit_page():
    prikey, pubkey = Ed25519Cipher.generate_keys()
    pubkey_str = pubkey.to_ascii(encoding='base64').decode()
    address = hash_tryte(pubkey_str)
    html = '''
    <!DOCTYPE html>
    <html>
    
예제 #8
0
 def setUp(self):
     self.tangle_con = TangleConnector()