Beispiel #1
0
    def test_show_public_key_diffs(self, _: Any) -> None:

        self.assert_prints("""\
           ┌──────────────────────────────────────────────────────────────────────────────────────┐           
           │                   Source Computer received an invalid public key.                    │           
           │                  See arrows below that point to correct characters.                  │           
           │                                                                                      │           
           │ 4EEue4P8vkwzjAEnxiUw9s4ibVA3YVWvzshd6tCQp67qjqda7n93SCtM8Z24tVFd8ZuS9Kt5kecghuajaneR │           
           │    ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ │           
           │ 4EEjKap9yReFo8SdSKPhUgsQgsKD19nJBrhiBuDmcB7yzucbYMaGtpQF8de99KHWLqWtohzLKWtqTv9HG5Fb │           
           └──────────────────────────────────────────────────────────────────────────────────────┘           
""", show_value_diffs, 'public key',
                           b58encode(TFC_PUBLIC_KEY_LENGTH*b'a', public_key=True),
                           b58encode(TFC_PUBLIC_KEY_LENGTH*b'b', public_key=True),
                           local_test=True)

        self.assert_prints("""\
     ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐      
     │                         Source Computer received an invalid public key.                         │      
     │                       See arrows below that point to correct characters.                        │      
     │                                                                                                 │      
     │    A       B       C       D       E       F       G       H       I       J       K       L    │      
     │ 4EEue4P 8vkwzjA EnxiUw9 s4ibVA3 YVWvzsh d6tCQp6 7qjqda7 n93SCtM 8Z24tVF d8ZuS9K t5kecgh uajaneR │      
     │    ↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓  ↓↓↓↓↓↓↓  ↓↓↓↓↓↓ ↓↓↓↓↓↓↓  ↓↓↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓ │      
     │ 4EEjKap 9yReFo8 SdSKPhU gsQgsKD 19nJBrh iBuDmcB 7yzucbY MaGtpQF 8de99KH WLqWtoh zLKWtqT v9HG5Fb │      
     │    A       B       C       D       E       F       G       H       I       J       K       L    │      
     └─────────────────────────────────────────────────────────────────────────────────────────────────┘      
""", show_value_diffs, 'public key',
                           b58encode(TFC_PUBLIC_KEY_LENGTH*b'a', public_key=True),
                           b58encode(TFC_PUBLIC_KEY_LENGTH*b'b', public_key=True),
                           local_test=False)
Beispiel #2
0
def pub_key_checker(queues: 'QueueDict',
                    local_test: bool,
                    unit_test: bool = False) -> None:
    """\
    Display diffs between received public keys and public keys
    manually imported to Source Computer.
    """
    pub_key_check_queue = queues[PUB_KEY_CHECK_QUEUE]
    pub_key_send_queue = queues[PUB_KEY_SEND_QUEUE]
    pub_key_dictionary = dict()

    while True:
        with ignored(EOFError, KeyboardInterrupt):
            if pub_key_send_queue.qsize() != 0:
                account, pub_key = pub_key_send_queue.get()
                pub_key_dictionary[account] = b58encode(pub_key,
                                                        public_key=True)
                continue

            if pub_key_check_queue.qsize() != 0:
                purp_account, purp_pub_key = pub_key_check_queue.get(
                )  # type: bytes, bytes

                if purp_account in pub_key_dictionary:
                    purp_b58_pub_key = purp_pub_key.decode()
                    true_b58_pub_key = pub_key_dictionary[purp_account]

                    show_value_diffs("public key", true_b58_pub_key,
                                     purp_b58_pub_key, local_test)

            time.sleep(0.01)

            if unit_test:
                break
Beispiel #3
0
    def test_invalid_compression_raises_fr(self):
        # Setup
        data        = os.urandom(1000)
        compressed  = zlib.compress(data, level=9)
        compressed  = compressed[:-2] + b'aa'
        key         = os.urandom(32)
        key_b58     = b58encode(key)
        packet      = IMPORTED_FILE_CT_HEADER + encrypt_and_sign(compressed, key)
        ts          = datetime.datetime.now()
        window_list = WindowList()

        o_input     = builtins.input
        input_list  = ['bad', key_b58]
        gen         = iter(input_list)

        def mock_input(_):
            return str(next(gen))

        builtins.input = mock_input

        # Test
        self.assertFR("Decompression of file data failed.", process_imported_file, ts, packet, window_list)

        # Teardown
        builtins.input = o_input
Beispiel #4
0
    def test_valid_import(self):
        file_name   = str_to_bytes('testfile.txt')
        data        = file_name + os.urandom(1000)
        compressed  = zlib.compress(data, level=9)
        key         = os.urandom(32)
        key_b58     = b58encode(key)
        packet      = IMPORTED_FILE_CT_HEADER + encrypt_and_sign(compressed, key)
        ts          = datetime.datetime.now()
        window_list = WindowList(nicks=['local'])
        o_input     = builtins.input
        input_list  = ['2QJL5gVSPEjMTaxWPfYkzG9UJxzZDNSx6PPeVWdzS5CFN7knZy', key_b58]
        gen         = iter(input_list)

        def mock_input(_):
            return str(next(gen))

        builtins.input = mock_input

        # Setup
        self.assertIsNone(process_imported_file(ts, packet, window_list))
        self.assertTrue(os.path.isfile(f"{DIR_IMPORTED}/testfile.txt"))

        # Teardown
        builtins.input = o_input
        shutil.rmtree(f'{DIR_IMPORTED}/')
Beispiel #5
0
def g_msg_manager(queues: 'QueueDict', unit_test: bool = False) -> None:
    """Show group management messages according to contact list state.

    This process keeps track of existing contacts for whom there's a
    `client` process. When a group management message from a contact
    is received, existing contacts are displayed under "known contacts",
    and non-existing contacts are displayed under "unknown contacts".
    """
    existing_contacts = []  # type: List[bytes]
    group_management_queue = queues[GROUP_MGMT_QUEUE]

    while True:
        with ignored(EOFError, KeyboardInterrupt):
            while queues[GROUP_MSG_QUEUE].qsize() == 0:
                time.sleep(0.01)

            header, payload, trunc_addr = queues[GROUP_MSG_QUEUE].get()
            group_id, data = separate_header(payload, GROUP_ID_LENGTH)

            if len(group_id) != GROUP_ID_LENGTH:
                continue
            group_id_hr = b58encode(group_id)

            existing_contacts = update_list_of_existing_contacts(
                group_management_queue, existing_contacts)

            process_group_management_message(data, existing_contacts,
                                             group_id_hr, header, trunc_addr)

            if unit_test and queues[UNIT_TEST_QUEUE].qsize() != 0:
                break
Beispiel #6
0
 def test_invalid_decoding(self):
     key = KEY_LENGTH * b'\x01'
     encoded = b58encode(
         key)  # 5HpjE2Hs7vjU4SN3YyPQCdhzCu92WoEeuE6PWNuiPyTu3ESGnzn
     changed = encoded[:-1] + 'a'
     with self.assertRaises(ValueError):
         b58decode(changed)
Beispiel #7
0
def print_key(message:    str,                              # Instructive message
              key_bytes:  bytes,                            # 32-byte key to be displayed
              settings:   Union['Settings', 'GWSettings'],  # Settings object
              public_key: bool = False                      # When True, uses Testnet address WIF format
              ) -> None:
    """Print a symmetric key in WIF format.

    If local testing is not enabled, this function adds spacing in the
    middle of the key, as well as guide letters to help the user keep
    track of typing progress:

    Local key encryption keys:

     A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q
    5Ka 52G yNz vjF nM4 2jw Duu rWo 7di zgi Y8g iiy yGd 78L cCx mwQ mWV

    X448 public keys:

       A       B       C       D       E       F       H       H       I       J       K       L
    4EcuqaD ddsdsuc gBX2PY2 qR8hReA aeSN2oh JB9w5Cv q6BQjDa PPgzSvW 932aHio sT42SKJ Gu2PpS1 Za3Xrao
    """
    b58key = b58encode(key_bytes, public_key)
    if settings.local_testing_mode:
        m_print([message, b58key], box=True)
    else:
        guide, chunk_len = (B58_PUBLIC_KEY_GUIDE, 7) if public_key else (B58_LOCAL_KEY_GUIDE, 3)

        key = ' '.join(split_string(b58key, item_len=chunk_len))
        m_print([message, guide, key], box=True)
Beispiel #8
0
def process_public_key(ts: 'datetime', packet: bytes,
                       window_list: 'WindowList', settings: 'Settings',
                       pubkey_buf: Dict[str, bytes]) -> None:
    """Display contact's public key and add it to buffer."""
    pub_key = packet[1:33]
    origin = packet[33:34]

    try:
        account = packet[34:].decode()
    except UnicodeError:
        raise FunctionReturn(
            "Error! Account for received public key had invalid encoding.")

    if origin not in [ORIGIN_CONTACT_HEADER, ORIGIN_USER_HEADER]:
        raise FunctionReturn(
            "Error! Received public key had an invalid origin header.")

    if origin == ORIGIN_CONTACT_HEADER:
        pubkey_buf[account] = pub_key
        print_key(f"Received public key from {account}:", pub_key, settings)

        local_win = window_list.get_local_window()
        pub_key_b58 = ' '.join(
            split_string(b58encode(pub_key),
                         item_len=(51 if settings.local_testing_mode else 3)))
        local_win.add_new(
            ts, f"Received public key from {account}: {pub_key_b58}")

    elif origin == ORIGIN_USER_HEADER and account in pubkey_buf:
        clear_screen()
        print_key(f"Public key for {account}:", pubkey_buf[account], settings)
Beispiel #9
0
    def test_new_local_key(self, *_: Any) -> None:
        # Setup
        self.settings.nc_bypass_messages = False
        self.settings.traffic_masking    = False

        # Test
        self.assertIsNone(new_local_key(*self.args))
        local_contact = self.contact_list.get_contact_by_pub_key(LOCAL_PUBKEY)

        self.assertEqual(local_contact.onion_pub_key,  LOCAL_PUBKEY)
        self.assertEqual(local_contact.nick,           LOCAL_NICK)
        self.assertEqual(local_contact.tx_fingerprint, blake2b(b58encode(blake2b(SYMMETRIC_KEY_LENGTH*b'a')).encode()))
        self.assertEqual(local_contact.rx_fingerprint, bytes(FINGERPRINT_LENGTH))
        self.assertFalse(local_contact.log_messages)
        self.assertFalse(local_contact.file_reception)
        self.assertFalse(local_contact.notifications)

        self.assertEqual(self.queues[COMMAND_PACKET_QUEUE].qsize(), 1)

        cmd, account, tx_key, rx_key, tx_hek, rx_hek = self.queues[KEY_MANAGEMENT_QUEUE].get()

        self.assertEqual(cmd, KDB_ADD_ENTRY_HEADER)
        self.assertEqual(account, LOCAL_PUBKEY)
        for key in [tx_key, rx_key, tx_hek, rx_hek]:
            self.assertIsInstance(key, bytes)
            self.assertEqual(len(key), SYMMETRIC_KEY_LENGTH)
Beispiel #10
0
def process_public_key(ts: 'datetime', packet: bytes,
                       window_list: 'WindowList', settings: 'Settings',
                       pubkey_buf: Dict[str, str]) -> None:
    """Display public from contact."""
    pub_key = packet[1:33]
    origin = packet[33:34]
    account = packet[34:].decode()

    if origin == ORIGIN_CONTACT_HEADER:
        pub_key_enc = b58encode(pub_key)
        ssl = {48: 8, 49: 7, 50: 5}.get(len(pub_key_enc), 5)
        pub_key_enc = pub_key_enc if settings.local_testing_mode else ' '.join(
            split_string(pub_key_enc, item_len=ssl))

        pubkey_buf[account] = pub_key_enc

        box_print(
            [f"Received public key from {account}", '', pubkey_buf[account]],
            head=1,
            tail=1)

        local_win = window_list.get_local_window()
        local_win.print_new(
            ts,
            f"Received public key from {account}: {pub_key_enc}",
            print_=False)

    if origin == ORIGIN_USER_HEADER and account in pubkey_buf:
        clear_screen()
        box_print([f"Public key for {account}", '', pubkey_buf[account]],
                  head=1,
                  tail=1)
Beispiel #11
0
    def test_zero_public_key_raises_fr(self):
        # Setup
        builtins.input = lambda _: b58encode(bytes(32))

        # Test
        self.assertFR("Error: Zero public key", start_key_exchange,
                      '*****@*****.**', '*****@*****.**', 'Alice',
                      self.contact_list, self.settings, self.queues)
Beispiel #12
0
    def test_compare_pub_keys(self):
        # Setup
        onion_pub_key = ONION_SERVICE_PUBLIC_KEY_LENGTH * b'a'
        invalid_pub_key = b58encode(TFC_PUBLIC_KEY_LENGTH * b'a').encode()

        # Test
        compare_pub_keys(onion_pub_key + invalid_pub_key, self.queues)
        self.assertEqual(self.queues[PUB_KEY_CHECK_QUEUE].get(),
                         (onion_pub_key, invalid_pub_key))
Beispiel #13
0
    def test_bitcoin_wif_test_vectors(self):
        """Test vectors are available at
            https://en.bitcoin.it/wiki/Wallet_import_format
        """
        byte_key = bytes.fromhex("0C28FCA386C7A227600B2FE50B7CAE11"
                                 "EC86D3BF1FBE471BE89827E19D72AA1D")

        b58_key = "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ"

        self.assertEqual(b58encode(byte_key), b58_key)
        self.assertEqual(b58decode(b58_key), byte_key)
Beispiel #14
0
    def setUp(self):
        self.o_input     = builtins.input
        self.settings    = Settings()
        self.ts          = datetime.datetime.now()
        self.window_list = WindowList(nicks=[LOCAL_ID])
        self.key         = os.urandom(KEY_LENGTH)
        self.key_b58     = b58encode(self.key, file_key=True)

        input_list     = ['91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwi1C2GD', self.key_b58]
        gen            = iter(input_list)
        builtins.input = lambda _: str(next(gen))
Beispiel #15
0
    def test_pub_key_checker(self, _: Any) -> None:
        # Setup
        public_key         = TFC_PUBLIC_KEY_LENGTH*b'a'
        invalid_public_key = b58encode(public_key, public_key=True)[:-1] + 'a'
        account            = nick_to_pub_key('Bob')

        for local_test in [True, False]:
            self.queues[PUB_KEY_SEND_QUEUE].put((account,  public_key))
            self.queues[PUB_KEY_CHECK_QUEUE].put((account, invalid_public_key.encode()))

            # Test
            self.assertIsNone(pub_key_checker(self.queues, local_test=local_test, unit_test=True))
            self.assertIsNone(pub_key_checker(self.queues, local_test=local_test, unit_test=True))
Beispiel #16
0
    def test_account_checker(self, *_: Any) -> None:
        # Setup
        user_account     = b58encode(nick_to_pub_key('Alice'))
        account          = b58encode(nick_to_pub_key('Bob'))
        unknown_account  = b58encode(nick_to_pub_key('Charlie'))
        invalid_account1 = account[:-1] + 'c'
        invalid_account2 = unknown_account[:-1] + 'c'

        def queue_delayer() -> None:
            """Place messages to queue one at a time."""
            time.sleep(0.05)
            self.queues[USER_ACCOUNT_QUEUE].put(user_account)
        threading.Thread(target=queue_delayer).start()

        self.queues[GUI_INPUT_QUEUE].put(unknown_account)
        self.queues[ACCOUNT_SEND_QUEUE].put(invalid_account1)
        self.queues[ACCOUNT_CHECK_QUEUE].put(account)
        self.queues[ACCOUNT_CHECK_QUEUE].put(invalid_account2)

        # Test
        with mock.patch('time.sleep', lambda _: None):
            self.assertIsNone(account_checker(self.queues, stdin_fd=1, unit_test=True))
Beispiel #17
0
    def __init__(self, uid: bytes, contact_list: 'ContactList',
                 group_list: 'GroupList', settings: 'Settings',
                 packet_list: 'PacketList') -> None:
        """Create a new RxWindow object."""
        self.uid = uid
        self.contact_list = contact_list
        self.group_list = group_list
        self.settings = settings
        self.packet_list = packet_list

        self.is_active = False
        self.contact = None
        self.group = None
        self.group_msg_id = os.urandom(GROUP_MSG_ID_LENGTH)

        self.window_contacts = []  # type: List[Contact]
        self.message_log = []  # type: List[MsgTuple]
        self.handle_dict = dict()  # type: Dict[bytes, str]
        self.previous_msg_ts = datetime.now()
        self.unread_messages = 0

        if self.uid == WIN_UID_COMMAND:
            self.type = WIN_TYPE_COMMAND  # type: str
            self.name = self.type  # type: str
            self.window_contacts = []

        elif self.uid == WIN_UID_FILE:
            self.type = WIN_TYPE_FILE
            self.packet_list = packet_list

        elif self.uid in self.contact_list.get_list_of_pub_keys():
            self.type = WIN_TYPE_CONTACT
            self.contact = self.contact_list.get_contact_by_pub_key(uid)
            self.name = self.contact.nick
            self.window_contacts = [self.contact]

        elif self.uid in self.group_list.get_list_of_group_ids():
            self.type = WIN_TYPE_GROUP
            self.group = self.group_list.get_group_by_id(self.uid)
            self.name = self.group.name
            self.window_contacts = self.group.members

        else:
            if len(uid) == ONION_SERVICE_PUBLIC_KEY_LENGTH:
                hr_uid = pub_key_to_onion_address(uid)
            elif len(uid) == GROUP_ID_LENGTH:
                hr_uid = b58encode(uid)
            else:
                hr_uid = "<unable to encode>"

            raise SoftError(f"Invalid window '{hr_uid}'.")
Beispiel #18
0
    def test_successful_local_key_processing_existing_local_key(self):
        # Setup
        conf_code = os.urandom(1)
        key       = os.urandom(KEY_LENGTH)
        hek       = os.urandom(KEY_LENGTH)
        kek       = os.urandom(KEY_LENGTH)
        packet    = LOCAL_KEY_PACKET_HEADER + encrypt_and_sign(key + hek + conf_code, key=kek)

        input_list     = ['5JJwZE46Eic9B8sKJ8Qocyxa8ytUJSfcqRo7Hr5ES7YgFGeJjCJ', b58encode(kek)]
        gen            = iter(input_list)
        builtins.input = lambda _: str(next(gen))

        # Test
        self.assertIsNone(process_local_key(self.ts, packet, self.window_list, self.contact_list, self.key_list, self.settings))
Beispiel #19
0
def protect_kdk(kdk: bytes) -> None:
    """Prevent leak of KDK via terminal history / clipboard."""
    readline.clear_history()
    reset_terminal()
    root = tkinter.Tk()
    root.withdraw()

    try:
        if root.clipboard_get() == b58encode(kdk):  # type: ignore
            root.clipboard_clear()  # type: ignore
    except tkinter.TclError:
        pass

    root.destroy()
Beispiel #20
0
    def test_successful_local_key_processing_existing_bootstrap(self):
        # Setup
        conf_code = os.urandom(1)
        key       = os.urandom(KEY_LENGTH)
        hek       = os.urandom(KEY_LENGTH)
        kek       = os.urandom(KEY_LENGTH)
        packet    = LOCAL_KEY_PACKET_HEADER + encrypt_and_sign(key + hek + conf_code, key=kek)

        input_list     = [b58encode(kek)]
        gen            = iter(input_list)
        builtins.input = lambda _: str(next(gen))

        self.key_list.keysets = []

        # Test
        self.assertIsNone(process_local_key(self.ts, packet, self.window_list, self.contact_list, self.key_list, self.settings))
        self.assertEqual(self.window_list.active_win.uid, LOCAL_ID)
Beispiel #21
0
    def test_successful_local_key_processing(self):
        # Setup
        conf_code      = os.urandom(1)
        key            = os.urandom(32)
        hek            = os.urandom(32)
        kek            = os.urandom(32)
        packet         = LOCAL_KEY_PACKET_HEADER + encrypt_and_sign(key + hek + conf_code, key=kek)
        contact_list   = ContactList()
        key_list       = KeyList()
        o_input        = builtins.input
        builtins.input = lambda x: b58encode(kek)

        # Test
        self.assertIsNone(process_local_key(packet, contact_list, key_list))

        # Teardown
        builtins.input = o_input
Beispiel #22
0
def print_kdk(kdk_bytes: bytes, settings: 'Settings') -> None:
    """Print symmetric key decryption key.

    If local testing is not enabled, this function will add spacing between
    key decryption key to help user keep track of key typing progress. The
    length of the Base58 encoded key varies between 48..50 characters, thus
    spacing is adjusted to get even length for each substring.

    :param kdk_bytes: Key decryption key
    :param settings:  Settings object
    :return:          None
    """
    kdk_enc = b58encode(kdk_bytes)
    ssl = {48: 8, 49: 7, 50: 5}.get(len(kdk_enc), 5)
    kdk = kdk_enc if settings.local_testing_mode else ' '.join(
        split_string(kdk_enc, item_len=ssl))

    box_print(["Local key decryption key (to RxM)", kdk])
Beispiel #23
0
def export_file(settings: 'Settings', gateway: 'Gateway'):
    """Encrypt and export file to NH.

    This is a faster method of sending large files. It is used together with '/fi' import_file
    command that loads ciphertext to RxM for later decryption. Key is generated automatically
    so that bad passwords by users do not affect security of ciphertexts.

    As use of this command reveals use of TFC, it is disabled during trickle connection.
    """
    if settings.session_trickle:
        raise FunctionReturn("Command disabled during trickle connection.")

    path = ask_path_gui("Select file to export...", settings, get_file=True)
    name = path.split('/')[-1]
    data = bytearray()
    data.extend(str_to_bytes(name))

    if not os.path.isfile(path):
        raise FunctionReturn("Error: File not found.")

    if os.path.getsize(path) == 0:
        raise FunctionReturn("Error: Target file is empty. No file was sent.")

    phase("Reading data")
    with open(path, 'rb') as f:
        data.extend(f.read())
    phase("Done")

    phase("Compressing data")
    comp  = bytes(zlib.compress(bytes(data), level=9))
    phase("Done")

    phase("Encrypting data")
    file_key = keygen()
    file_ct  = encrypt_and_sign(comp, key=file_key)
    phase("Done")

    phase("Exporting data")
    transmit(EXPORTED_FILE_CT_HEADER + file_ct, settings, gateway)
    phase("Done")

    box_print([f"Decryption key for file {name}:", '', b58encode(file_key)], head=1, tail=1)
Beispiel #24
0
def print_key(message: str,
              key_bytes: bytes,
              settings: 'Settings',
              no_split: bool = False,
              file_key: bool = False) -> None:
    """Print symmetric key.

    If local testing is not enabled, this function will add spacing in the
    middle of the key to help user keep track of typing progress. The ideal
    substring length in Cowan's `focus of attention` is four digits:

        https://en.wikipedia.org/wiki/Working_memory#Working_memory_as_part_of_long-term_memory

    The 51 char KDK is however not divisible by 4, and remembering which
    symbols are letters and if they are capitalized is harder than remembering
    just digits. 51 is divisible by 3. The 17 segments are displayed with guide
    letter A..Q to help keep track when typing:

         A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q
        5Ka 52G yNz vjF nM4 2jw Duu rWo 7di zgi Y8g iiy yGd 78L cCx mwQ mWV

    :param message:   Message to print
    :param key_bytes: Decryption key
    :param settings:  Settings object
    :param no_split:  When True, does not split decryption key to chunks
    :param file_key   When True, uses testnet address format
    :return:          None
    """
    b58key = b58encode(key_bytes, file_key)
    if settings.local_testing_mode or no_split:
        box_print([message, b58key])
    else:
        box_print([
            message, '   '.join('ABCDEFGHIJKLMNOPQ'),
            ' '.join(split_string(b58key, item_len=3))
        ])
Beispiel #25
0
    def test_invalid_name_raises_fr(self):
        # Setup
        file_name   = str_to_bytes('\x01testfile.txt')
        data        = file_name + os.urandom(1000)
        compressed  = zlib.compress(data, level=9)
        key         = os.urandom(32)
        key_b58     = b58encode(key)
        packet      = IMPORTED_FILE_CT_HEADER + encrypt_and_sign(compressed, key)
        ts          = datetime.datetime.now()
        window_list = WindowList(nicks=['local'])
        o_input     = builtins.input
        input_list  = ['2QJL5gVSPEjMTaxWPfYkzG9UJxzZDNSx6PPeVWdzS5CFN7knZy', key_b58]
        gen         = iter(input_list)

        def mock_input(_):
            return str(next(gen))

        builtins.input = mock_input

        # Test
        self.assertFR("Received file had an invalid name.", process_imported_file, ts, packet, window_list)

        # Teardown
        builtins.input = o_input
Beispiel #26
0
 def test_local_keys_raise_value_error_when_expecting_public_key(self):
     b58_file_key = b58encode(self.key, public_key=True)
     with self.assertRaises(ValueError):
         b58decode(b58_file_key)
Beispiel #27
0
 def test_encoding_and_decoding_of_random_public_keys(self):
     for _ in range(100):
         key = os.urandom(TFC_PUBLIC_KEY_LENGTH)
         encoded = b58encode(key, public_key=True)
         decoded = b58decode(encoded, public_key=True)
         self.assertEqual(key, decoded)
Beispiel #28
0
 def test_encoding_and_decoding_of_random_local_keys(self):
     for _ in range(100):
         key = os.urandom(SYMMETRIC_KEY_LENGTH)
         encoded = b58encode(key)
         decoded = b58decode(encoded)
         self.assertEqual(key, decoded)
Beispiel #29
0
    def print_groups(self) -> None:
        """Print list of groups.

        Neatly printed group list allows easy group management and it
        also allows the user to check active logging and notification
        setting, as well as what group ID Relay Program shows
        corresponds to what group, and which contacts are in the group.
        """
        # Initialize columns
        c1 = ['Group']
        c2 = ['Group ID']
        c3 = ['Logging ']
        c4 = ['Notify']
        c5 = ['Members']

        # Populate columns with group data that has only a single line
        for g in self.groups:
            c1.append(g.name)
            c2.append(b58encode(g.group_id))
            c3.append('Yes' if g.log_messages else 'No')
            c4.append('Yes' if g.notifications else 'No')

        # Calculate the width of single-line columns
        c1w, c2w, c3w, c4w = [
            max(len(v) for v in column) + CONTACT_LIST_INDENT
            for column in [c1, c2, c3, c4]
        ]

        # Create a wrapper for Members-column
        wrapped_members_line_indent = c1w + c2w + c3w + c4w
        members_column_width = max(
            1,
            get_terminal_width() - wrapped_members_line_indent)
        wrapper = textwrap.TextWrapper(width=members_column_width)

        # Populate the Members-column
        for g in self.groups:
            if g.empty():
                c5.append("<Empty group>\n")
            else:
                comma_separated_nicks = ', '.join(
                    sorted([m.nick for m in g.members]))
                members_column_lines = wrapper.fill(
                    comma_separated_nicks).split('\n')

                final_str = members_column_lines[0] + '\n'
                for line in members_column_lines[1:]:
                    final_str += wrapped_members_line_indent * ' ' + line + '\n'

                c5.append(final_str)

        # Align columns by adding whitespace between fields of each line
        lines = [
            f'{f1:{c1w}}{f2:{c2w}}{f3:{c3w}}{f4:{c4w}}{f5}'
            for f1, f2, f3, f4, f5 in zip(c1, c2, c3, c4, c5)
        ]

        # Add a terminal-wide line between the column names and the data
        lines.insert(1, get_terminal_width() * '─')

        # Print the group list
        print('\n'.join(lines) + '\n')
Beispiel #30
0
 def get_list_of_hr_group_ids(self) -> List[str]:
     """Return list of human readable (B58 encoded) group IDs."""
     return [b58encode(g.group_id) for g in self.groups]