def test_verify(test_password): """ Verification works with unicode and bytes. """ porridge = Porridge('keyid1:key1', encoding='latin1') encoded = ( # handrolled test vector lifted from argon2_cffi "$argon2i$m=8,t=1,p=1$" "bL/lLsegFKTuR+5vVyA8tA$VKz5CHavCtFOL1N5TIXWSA" ) assert porridge.verify(test_password, encoded)
def test_verify_doesnt_bail_on_values_equal_to_threshold(parameter, threshold): # Create an instance where memory_cost is at least the highest parallelism*8 porridge = Porridge('key1:secret1', memory_cost=64, time_cost=1, parallelism=1, parameter_threshold=threshold) parameters = { 'time_cost': porridge.time_cost, 'memory_cost': porridge.memory_cost, 'parallelism': porridge.parallelism, } parameters[parameter] *= porridge.parameter_threshold encoded = get_encoded_password_with_parameters(parameters) # Since the parameters are wrong the password should not be valid assert porridge.verify('password', encoded) == False
def test_operational_error_memory_allocation_error_verify_mock(): lib_mock = mock.Mock() # Ref. https://github.com/P-H-C/phc-winner-argon2/blob/master/include/argon2.h#L131 lib_mock.return_value = -22 # 'password' encoded with key 'secret' encoded = ('$argon2i$v=19$m=512,t=2,p=4,keyid=key$Zs0La+XTLuJ9fpmXnUneCA$' '5dJXxTR/z/i7Bre6BM4RUEKeStSoVU8yzY+a+UxwnT8') porridge = Porridge('key:secret') with mock.patch('porridge.porridge.verify_hash', lib_mock): with pytest.raises(PorridgeError) as exception: porridge.verify('password', encoded) assert 'Memory allocation' in exception.value.args[0]
def test_operational_error_memory_allocation_error_on_boil(): '''Tries to allocate 1TB for password hashing, which is hopefully more than what is available on any machine that tries to run the tests, or this test will take a long-ass time to finish. ''' with pytest.raises(PorridgeError) as exception: porridge = Porridge('key:secret', memory_cost=1000000000) assert 'Memory allocation' in exception.value.args[0]
def test_str(): porridge = Porridge('key:secret,oldkey:oldsecret', memory_cost=8, time_cost=1, parallelism=1) assert str( porridge ) == "Porridge(key='key', memory_cost=8, time_cost=1, parallelism=1)"
def test_operational_error_on_threading_error_on_boil(): with nproc_soft_limit(100) as limits: parallelism = limits[0] * 2 memory_cost = 8 * parallelism with pytest.raises(PorridgeError) as exception: Porridge('key:secret', parallelism=parallelism, memory_cost=memory_cost) assert exception.value.args[0] == 'Threading failure'
def create_porridge(): return Porridge( 'key:secret,oldkey:oldsecret', time_cost=2, memory_cost=16, parallelism=2, hash_len=16, salt_len=16, )
def test_repr(): porridge = Porridge('key:secret,oldkey:oldsecret', memory_cost=8, time_cost=1, parallelism=1, parameter_threshold=2, hash_len=7, salt_len=9, encoding='latin-1') assert repr(porridge) == ( "Porridge(key='key', memory_cost=8, time_cost=1, parallelism=1, " "hash_len=7, salt_len=9, parameter_threshold=2, encoding='latin-1')")
def test_invalid_parameters(): with pytest.raises(ParameterError) as exception: porridge = Porridge('key:secret', time_cost=1, memory_cost=1) assert 'Memory cost is too small' == exception.value.args[0]
def test_verify_legacy_passwords_without_secret(encoded): # Set high enough parameters to avoid triggering the safety check porridge = Porridge('key1:secret1', memory_cost=256, time_cost=1, parallelism=2) assert porridge.verify('password', encoded)
def test_attacker_cant_verify_without_secret(password): our_porridge = Porridge('id1:key1') attacker_porridge = Porridge('otherid:otherkey') encoded_password = our_porridge.boil(password) with pytest.raises(MissingKeyError): attacker_porridge.verify(password, encoded_password)
def test_verify_self_default_parameters(password): porridge = Porridge('key:secret') assert porridge.verify(password, porridge.boil(password))
def test_verify_custom_parameters(password, time_cost, memory_cost, parallelism): assume(parallelism * 8 <= memory_cost) porridge = Porridge('key:secret', time_cost=time_cost, memory_cost=memory_cost, parallelism=parallelism) assert porridge.verify(password, porridge.boil(password))
def test_invalid_parameter_types(): with pytest.raises(TypeError) as exception: Porridge(1) assert exception.value.args[0].startswith("'secrets' must be a str")
def test_invalid_parameter_types_int(): with pytest.raises(TypeError) as exception: Porridge('key:secret', time_cost='hello') assert exception.value.args[0].startswith("'time_cost' must be a int")
# coding: utf-8 from __future__ import unicode_literals import pytest from porridge import Porridge KETTLES = (Porridge( 'key1:secret1', time_cost=1, memory_cost=8, parallelism=1, ), Porridge( 'key2:secret2,key1:secret1', time_cost=1, memory_cost=8, parallelism=1, )) @pytest.fixture(params=KETTLES) def porridge(request): '''A Porridge-instance suitable for testing. Does no environment check and has very fast parameters. ''' return request.param
def test_invalid_threshold(): with pytest.raises(ValueError) as exception: Porridge('key:secret', parameter_threshold=0) assert exception.value.args[0] == 'parameter_threshold must be at least 1'