def test_authentication_is_required_if_password_is_provided_as_authentication_method( ): # Given allowed_authentication_methods = ["password"] password_salt = os.urandom(16) password_to_derive = b"test" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_methods, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_methods) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) # When result = server.next_message() # Then assert int.from_bytes(result.msg_id, 'little') == codes.HANDSHAKE assert int.from_bytes(result.topic, 'little') == Handshake.AUTHENTICATION_REQUIRED_TOPIC
def test_encrypt_return_different_bytes_than_input_when_connection_step_4_for_both_roles( ): # Given msg_to_encrypt = b"A very secret message" password_salt = os.urandom(16) password_to_derive = b"test" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) allowed_authentication_method = ["password"] authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_method) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) # When encrypt_server = server._encrypt(data=msg_to_encrypt) encrypt_client = client._encrypt(data=msg_to_encrypt) # Then assert encrypt_client != msg_to_encrypt assert encrypt_server != msg_to_encrypt
def test_next_message_return_authentication_required_message_when_connection_step_4_and_role_is_server_with_password( ): # Given password_to_derive = b"test" password_salt = os.urandom(16) derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) allowed_authentication_method = ["password"] authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_method) expected_message = UDPMessage( code=codes.HANDSHAKE, topic=Handshake.AUTHENTICATION_REQUIRED_TOPIC) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) # When result = server.next_message() # Then assert result.msg_id == expected_message.msg_id assert result.topic == expected_message.topic
def test_next_message_return_authentication_message_when_connection_step_4_and_role_is_client_with_password( ): # Given password_to_derive = b"test" password_salt = os.urandom(16) allowed_authentication_method = ["password"] derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_to_derive.decode("utf8") } authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_client) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) expected_id = codes.HANDSHAKE expected_topic = Handshake.AUTHENTICATION_TOPIC # When result = client.next_message() payload = client._decrypt(result.payload) payload = json.loads(bytes.decode(payload, "utf8")) password = payload[Handshake.AUTH_METHOD_INFO_KEY]["password"] # Then assert int.from_bytes(result.msg_id, 'little') == expected_id assert int.from_bytes(result.topic, 'little') == expected_topic assert password == password_to_derive.decode('utf8')
def test_authentication_message_contain_random_bits_of_correct_length(): # Given password_salt = os.urandom(16) password_to_derive = b"test" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) allowed_authentication_method = ["password"] authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_to_derive.decode("utf8") } authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_client) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) expected_id = codes.HANDSHAKE expected_topic = Handshake.AUTHENTICATION_TOPIC # When result = client.next_message() payload = client._decrypt(result.payload) payload = json.loads(bytes.decode(payload, "utf8")) # Then assert int.from_bytes(result.msg_id, 'little') == expected_id assert int.from_bytes(result.topic, 'little') == expected_topic assert Handshake.AUTHENTICATION_RANDOM_BITS_KEY in payload.keys() assert len( base64.b64decode(payload[Handshake.AUTHENTICATION_RANDOM_BITS_KEY]) ) == Handshake.RANDOM_BITS_LENGTH
def test_authentication_required_message_contain_a_list_of_authentication_methods_available( ): # Given password_to_derive = b"test" password_salt = os.urandom(16) derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) allowed_authentication_method = Handshake.AUTHENTICATION_METHODS_AVAILABLE authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_to_derive } client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=["password"], authentication_information=authentication_information_client) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) authentication_required_message = server.next_message() # When result = json.loads( bytes.decode(authentication_required_message.payload, "utf8")) # Then assert Handshake.AUTHENTICATION_METHODS_AVAILABLE_KEY_NAME in result.keys() assert type( result[Handshake.AUTHENTICATION_METHODS_AVAILABLE_KEY_NAME]) is list assert len(result[Handshake.AUTHENTICATION_METHODS_AVAILABLE_KEY_NAME]) > 0 assert result[ Handshake. AUTHENTICATION_METHODS_AVAILABLE_KEY_NAME] == Handshake.AUTHENTICATION_METHODS_AVAILABLE
def test_next_message_return_connection_failed_msg_when_connection_step_6_and_role_is_client_and_password_incorrect( ): # Given password_salt = os.urandom(16) password_to_derive = b"test" password_client = "incorrect" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) allowed_authentication_method = ["password"] authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_client } authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_server) client = Handshake( role=Handshake.CLIENT, allowed_authentication_methods=allowed_authentication_method, authentication_information=authentication_information_client) expected_id = codes.HANDSHAKE expected_topic = Handshake.CONNECTION_FAILED_TOPIC server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) # When result = server.next_message() # Then assert int.from_bytes(result.msg_id, 'little') == expected_id assert int.from_bytes(result.topic, 'little') == expected_topic
def test_authentication_message_select_password_method_if_it_is_the_only_authentication_method_for_both_instances( ): # Given password_salt = os.urandom(16) password_to_derive = b"test_password" allowed_authentication_methods = ["password"] derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_to_derive.decode("utf8") } authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, authentication_information=authentication_information_server, allowed_authentication_methods=allowed_authentication_methods) client = Handshake( role=Handshake.CLIENT, authentication_information=authentication_information_client, allowed_authentication_methods=allowed_authentication_methods) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) authentication_message = client.next_message() # When payload = client._decrypt(authentication_message.payload) result = json.loads(bytes.decode(payload, "utf8")) # Then assert Handshake.SELECTED_AUTHENTICATION_METHOD_KEY_NAME in result.keys() assert result[ Handshake.SELECTED_AUTHENTICATION_METHOD_KEY_NAME] == "password"
def test_derive_password_scrypt_correctly_derive_a_password_with_scrypt(): # Given password_to_verify = b"test_password" password_to_derive = b"test_password" password_salt = os.urandom(16) kdf = Scrypt( salt=password_salt, length=32, n=2**14, r=8, p=1, ) expected_result = kdf.derive(password_to_verify) # When result = derive_password_scrypt(password_to_derive, password_salt) # Then assert result == expected_result
def test_get_status_return_approved_when_authentication_is_correct(): # Given allowed_authentication_methods = ["password"] password_to_derive = b"test" password_salt = os.urandom(16) password_client = "test" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, authentication_information=authentication_information_server, allowed_authentication_methods=allowed_authentication_methods) authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_client } client = Handshake( role=Handshake.CLIENT, authentication_information=authentication_information_client, allowed_authentication_methods=allowed_authentication_methods) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) # When result_client = client.get_status() result_server = server.get_status() # Then assert result_client == Handshake.CONNECTION_STATUS_APPROVED assert result_server == Handshake.CONNECTION_STATUS_APPROVED
def test_client_next_message_is_connection_failed_if_no_common_authentication_method_auth_request( ): # Given allowed_authentication_methods_server = ["password"] allowed_authentication_methods_client = ["custom"] password_salt = os.urandom(16) password_to_derive = b"test_password" derived_password = derive_password_scrypt( password_salt=password_salt, password_to_derive=password_to_derive) authentication_information_client = { Handshake.PASSWORD_AUTH_METHOD_PASSWORD_KEY: password_to_derive } client = Handshake( role=Handshake.CLIENT, authentication_information=authentication_information_client, allowed_authentication_methods=allowed_authentication_methods_client) authentication_information_server = { "password": { Handshake.PASSWORD_AUTH_METHOD_DERIVED_PASSWORD_KEY: derived_password, Handshake.PASSWORD_AUTH_METHOD_SALT_KEY: password_salt } } server = Handshake( role=Handshake.SERVER, authentication_information=authentication_information_server, allowed_authentication_methods=allowed_authentication_methods_server) server.add_message(client.next_message()) client.add_message(server.next_message()) server.add_message(client.next_message()) client.add_message(server.next_message()) # When connection_failed_message = client.next_message() # Then assert int.from_bytes(connection_failed_message.topic, 'little') == Handshake.CONNECTION_FAILED_TOPIC