def test_invalid_digest_size_raises_critical_error(self) -> None: for invalid_digest_size in [ -1, BLAKE2_DIGEST_LENGTH_MIN - 1, BLAKE2_DIGEST_LENGTH_MAX + 1, 1000 ]: with self.assertRaises(SystemExit): blake2b(self.test_string, digest_size=invalid_digest_size)
def test_invalid_size_blake2b_digest_raises_critical_error( self, mock_blake2b: MagicMock) -> None: with self.assertRaises(SystemExit): blake2b(self.test_string) with self.assertRaises(SystemExit): blake2b(self.test_string) mock_blake2b.assert_called()
def test_invalid_size_blake2b_digest_raises_critical_error( self, mock_blake2b): with self.assertRaises(SystemExit): blake2b(b'test_string') with self.assertRaises(SystemExit): blake2b(b'test_string') mock_blake2b.assert_called()
def test_x448_with_the_official_test_vectors(self) -> None: sk_alice_ = X448PrivateKey.from_private_bytes(TestX448.sk_alice) sk_bob_ = X448PrivateKey.from_private_bytes(TestX448.sk_bob) self.assertEqual(X448.derive_public_key(sk_alice_), TestX448.pk_alice) self.assertEqual(X448.derive_public_key(sk_bob_), TestX448.pk_bob) shared_secret1 = X448.shared_key(sk_alice_, TestX448.pk_bob) shared_secret2 = X448.shared_key(sk_bob_, TestX448.pk_alice) self.assertEqual(shared_secret1, blake2b(TestX448.shared_secret)) self.assertEqual(shared_secret2, blake2b(TestX448.shared_secret))
def rxp_load_psk(window: 'TxWindow', contact_list: 'ContactList', settings: 'Settings', queues: 'QueueDict', ) -> None: """Send command to Receiver Program to load PSK for active contact.""" if settings.traffic_masking: raise SoftError("Error: Command is disabled during traffic masking.", head_clear=True) if window.type == WIN_TYPE_GROUP or window.contact is None: raise SoftError("Error: Group is selected.", head_clear=True) if not contact_list.get_contact_by_pub_key(window.uid).uses_psk(): raise SoftError(f"Error: The current key was exchanged with {ECDHE}.", head_clear=True) c_code = blake2b(window.uid, digest_size=CONFIRM_CODE_LENGTH) command = KEY_EX_PSK_RX + c_code + window.uid queue_command(command, settings, queues) while True: try: purp_code = ask_confirmation_code('Receiver') if purp_code == c_code.hex(): window.contact.kex_status = KEX_STATUS_HAS_RX_PSK contact_list.store_contacts() raise SoftError(f"Removed PSK reminder for {window.name}.", tail_clear=True, delay=1) m_print("Incorrect confirmation code.", head=1) print_on_previous_line(reps=4, delay=2) except (EOFError, KeyboardInterrupt): raise SoftError("PSK install verification aborted.", tail_clear=True, delay=1, head=2)
def load_master_key(self) -> bytes: """Derive the master key from password and salt. Load the salt, hash, and key derivation settings from the login database. Derive the purported master key from the salt and entered password. If the BLAKE2b hash of derived master key matches the hash in the login database, accept the derived master key. """ database_data = self.database.load_database() if len(database_data) != MASTERKEY_DB_SIZE: raise CriticalError(f"Invalid {self.file_name} database size.") salt, key_hash, time_bytes, memory_bytes, parallelism_bytes \ = separate_headers(database_data, [ARGON2_SALT_LENGTH, BLAKE2_DIGEST_LENGTH, ENCODED_INTEGER_LENGTH, ENCODED_INTEGER_LENGTH]) time_cost = bytes_to_int(time_bytes) memory_cost = bytes_to_int(memory_bytes) parallelism = bytes_to_int(parallelism_bytes) while True: password = MasterKey.get_password() phase("Deriving master key", head=2, offset=len("Password correct")) purp_key = argon2_kdf(password, salt, time_cost, memory_cost, parallelism) if blake2b(purp_key) == key_hash: phase("Password correct", done=True, delay=1) clear_screen() return purp_key phase("Invalid password", done=True, delay=1) print_on_previous_line(reps=5)
def test_rotate_tx_mk(self) -> None: self.assertIsNone(self.keyset.rotate_tx_mk()) self.assertEqual(self.keyset.tx_mk, blake2b(bytes(SYMMETRIC_KEY_LENGTH) + int_to_bytes(INITIAL_HARAC), digest_size=SYMMETRIC_KEY_LENGTH)) self.assertEqual(self.keyset.rx_mk, bytes(SYMMETRIC_KEY_LENGTH)) self.assertEqual(self.keyset.tx_hk, bytes(SYMMETRIC_KEY_LENGTH)) self.assertEqual(self.keyset.rx_hk, bytes(SYMMETRIC_KEY_LENGTH)) self.assertEqual(self.keyset.tx_harac, 1) self.assertEqual(self.keyset.rx_harac, INITIAL_HARAC)
class TestInputLoop(unittest.TestCase): conf_code = blake2b(nick_to_pub_key('Alice'), digest_size=CONFIRM_CODE_LENGTH).hex() input_list = [ '61', # Enter Relay confirmation code '61', # Enter Receiver confirmation code nick_to_onion_address("Alice"), # Enter rx-account for new contact 'Alice', # Enter nick for contact '', # Enter to default for ECDHE VALID_ECDHE_PUB_KEY, # Enter public key for contact 'Yes', # Accept key fingerprints for Alice conf_code, # Confirmation code 'Alice', # Select Alice as the recipient 'Test', # Send test message '/file', # Open file selection prompt '', # Give empty string to abort '/exit' ] # Enter exit command def setUp(self) -> None: """Pre-test actions.""" self.settings = Settings(disable_gui_dialog=True) self.gateway = Gateway() self.contact_list = ContactList() self.group_list = GroupList() self.master_key = MasterKey() self.onion_service = OnionService() self.queues = gen_queue_dict() def tearDown(self) -> None: """Post-test actions.""" tear_queues(self.queues) @mock.patch('builtins.input', side_effect=input_list) @mock.patch('os.fdopen', MagicMock()) @mock.patch('os.getrandom', lambda n, flags: n * b'a') @mock.patch('os.urandom', lambda n: n * b'a') @mock.patch('shutil.get_terminal_size', return_value=[200, 200]) @mock.patch('src.transmitter.commands.exit_tfc', side_effect=SystemExit) @mock.patch('sys.stdin', MagicMock()) @mock.patch('time.sleep', return_value=None) @mock.patch('os.system', return_value=None) def test_input_loop_functions(self, *_: Any) -> None: with self.assertRaises(SystemExit): self.assertIsNone( input_loop(self.queues, self.settings, self.gateway, self.contact_list, self.group_list, self.master_key, self.onion_service, stdin_fd=1))
def store_unencrypted_database(self, data: bytes) -> None: """Store unencrypted data into database. For future integrity check, concatenate the BLAKE2b digest of the database content to the database file. """ ensure_dir(DIR_USER_DATA) self.ensure_temp_write(data + blake2b(data)) # Replace the original file with a temp file. (`os.replace` is atomic as per # POSIX requirements): https://docs.python.org/3/library/os.html#os.replace os.replace(self.database_temp, self.database_name)