diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/conftest.py | 61 | ||||
| -rw-r--r-- | tests/test_cli.py | 57 | ||||
| -rw-r--r-- | tests/test_envtoolkit_instance.py | 6 | ||||
| -rw-r--r-- | tests/test_envtoolkit_instance_static.py | 136 |
4 files changed, 173 insertions, 87 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index cbf7152..37dd184 100644 --- a/tests/conftest.py +++ b/tests/conftest.py | |||
| @@ -45,9 +45,9 @@ def config_data(): | |||
| 45 | 'ETOOLKIT_SENSITIVE': ['ETOOLKIT_TEST_PASSWORD'], | 45 | 'ETOOLKIT_SENSITIVE': ['ETOOLKIT_TEST_PASSWORD'], |
| 46 | 'GNUPGHOME': '%h/private/.gnupg', | 46 | 'GNUPGHOME': '%h/private/.gnupg', |
| 47 | 'ETOOLKIT_TEST_PASSWORD': ( | 47 | 'ETOOLKIT_TEST_PASSWORD': ( |
| 48 | 'enc-val$2$v6F2M7LeUDbQWNLg6WW5mUcbuYYo7aGynSxzWAENVBI=$' | 48 | 'enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviqrLTBxM=$' |
| 49 | 'ZcyWzf9Kp0aYI8N+biKMSmu4RGGi199ayq' | 49 | '+YYrZbwTBuG0Pl+WMQrvxLUtq5j8qYuQqz' |
| 50 | 'EYdJl+qdq7b1HSutwYlC7UR2GsSofu4Xo=' | 50 | 'oIwgoGt7AaWZCJz+E7qoDeg3wke70ST8U=' |
| 51 | ), | 51 | ), |
| 52 | }, | 52 | }, |
| 53 | }, | 53 | }, |
| @@ -64,12 +64,35 @@ def config_file(tmp_path, config_data): | |||
| 64 | 64 | ||
| 65 | 65 | ||
| 66 | @pytest.fixture() | 66 | @pytest.fixture() |
| 67 | def long_encrypted_value(): | ||
| 68 | """enc. value corresponding to 'Nobody expects the Spanish inquisition'""" | ||
| 69 | |||
| 70 | return ( | ||
| 71 | 'enc-val$2$uYpZM1VfAGq0CDZL2duITs076CQj+hIFEgx+F4mn80o=$' | ||
| 72 | 'UWP5YeRsh5/2vZ2J1UOS+BJti73Kbp6C1pJmCo8hF' | ||
| 73 | 'Sujpe35X/XpzBegJJpo86AiCsNsUS6B6JM=' | ||
| 74 | ) | ||
| 75 | |||
| 76 | |||
| 77 | @pytest.fixture() | ||
| 78 | def long_value(): | ||
| 79 | """standard value (> 32 bytes)""" | ||
| 80 | return 'Nobody expects the Spanish inquisition' | ||
| 81 | |||
| 82 | |||
| 83 | @pytest.fixture() | ||
| 67 | def master_password(): | 84 | def master_password(): |
| 68 | """Master passord""" | 85 | """Master passord""" |
| 69 | return 'The very secret passwd' | 86 | return 'The very secret passwd' |
| 70 | 87 | ||
| 71 | 88 | ||
| 72 | @pytest.fixture() | 89 | @pytest.fixture() |
| 90 | def new_master_password(): | ||
| 91 | """Master passord""" | ||
| 92 | return 'New very secret passwd' | ||
| 93 | |||
| 94 | |||
| 95 | @pytest.fixture() | ||
| 73 | def non_random_bytes_32(): | 96 | def non_random_bytes_32(): |
| 74 | """always use the same bytes instead of os.urandom(32)""" | 97 | """always use the same bytes instead of os.urandom(32)""" |
| 75 | 98 | ||
| @@ -80,13 +103,13 @@ def non_random_bytes_32(): | |||
| 80 | 103 | ||
| 81 | 104 | ||
| 82 | @pytest.fixture() | 105 | @pytest.fixture() |
| 83 | def non_random_bytes_61(): | 106 | def non_random_bytes_57(): |
| 84 | """always use the same bytes instead of os.urandom(61)""" | 107 | """always use the same bytes instead of os.urandom(57)""" |
| 85 | 108 | ||
| 86 | return ( | 109 | return ( |
| 87 | b'D$\x99\xaa\xafiZ\xb4C\xa0%XTz)\xca\xedK\xcd\xa2F~\xff+\xa1[\xe2\xaa' | 110 | b'D$\x99\xaa\xafiZ\xb4C\xa0%XTz)\xca\xedK\xcd\xa2F~\xff+\xa1[\xe2\xaa' |
| 88 | b'\xb2\xd3\x07\x13\xedb\xc2\x84\xfe\tS\r\xf0\x02_\xef\xe3\xde\xf1?e' | 111 | b'\xb2\xd3\x07\x13\xedb\xc2\x84\xfe\tS\r\xf0\x02_\xef\xe3\xde\xf1?e' |
| 89 | b'\xa4s(Q\x04\xcd\xc7T\x01_D\xb1' | 112 | b'\xa4s(Q\x04\xcd\xc7T' |
| 90 | ) | 113 | ) |
| 91 | 114 | ||
| 92 | 115 | ||
| @@ -108,6 +131,32 @@ def password_hash(): | |||
| 108 | 131 | ||
| 109 | 132 | ||
| 110 | @pytest.fixture() | 133 | @pytest.fixture() |
| 134 | def short_encrypted_value(): | ||
| 135 | """enc. value corresponding to 'secret1'""" | ||
| 136 | |||
| 137 | return ( | ||
| 138 | 'enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviqrLTBxM=$' | ||
| 139 | '+YYrZbwTBuG0Pl+WMQrvxLUtq5j8qYuQqzoIwgoGt7AaWZCJz+E7qoDeg3wke70ST8U=' | ||
| 140 | ) | ||
| 141 | |||
| 142 | |||
| 143 | @pytest.fixture() | ||
| 144 | def short_encrypted_value_v1(): | ||
| 145 | """enc. value (enc-val 1) corresponding to 'secret1'""" | ||
| 146 | |||
| 147 | return ( | ||
| 148 | 'enc-val$1$/cXpEMoZrTlb9yokGhw8tLTSUkqnqJ4ZoAkurNgMYx' | ||
| 149 | 'w=$1VdkSMcZnLRwLiu1M8VlYcbelwmiVNY=' | ||
| 150 | ) | ||
| 151 | |||
| 152 | |||
| 153 | @pytest.fixture() | ||
| 154 | def short_value(): | ||
| 155 | """standard value (< 32 bytes)""" | ||
| 156 | return 'secret1' | ||
| 157 | |||
| 158 | |||
| 159 | @pytest.fixture() | ||
| 111 | def wrong_master_password(): | 160 | def wrong_master_password(): |
| 112 | """Wrong master passord""" | 161 | """Wrong master passord""" |
| 113 | return 'the very secret passwd' | 162 | return 'the very secret passwd' |
diff --git a/tests/test_cli.py b/tests/test_cli.py index 1693a2b..953abf4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py | |||
| @@ -44,14 +44,17 @@ def test_decrypt_v1(binput, capsys, config_file, master_password): | |||
| 44 | 44 | ||
| 45 | 45 | ||
| 46 | @unittest.mock.patch('builtins.input') | 46 | @unittest.mock.patch('builtins.input') |
| 47 | def test_decrypt_v2(binput, capsys, config_file, master_password): | 47 | def test_decrypt_v2( |
| 48 | binput, | ||
| 49 | capsys, | ||
| 50 | config_file, | ||
| 51 | master_password, | ||
| 52 | short_encrypted_value, | ||
| 53 | short_value, | ||
| 54 | ): | ||
| 48 | """Tests v2 decryption via the CLI interface""" | 55 | """Tests v2 decryption via the CLI interface""" |
| 49 | 56 | ||
| 50 | binput.return_value = ( | 57 | binput.return_value = short_encrypted_value |
| 51 | 'enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviq' | ||
| 52 | 'rLTBxM=$+Yo6Ya2MAVcBLTQHuATkyFc+dzYsL/E' | ||
| 53 | 'SvA6ofOUDsiKZvIff35cUHAmoNxVuGG+MXv4=' | ||
| 54 | ) | ||
| 55 | with unittest.mock.patch.dict( | 58 | with unittest.mock.patch.dict( |
| 56 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} | 59 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} |
| 57 | ): | 60 | ): |
| @@ -59,18 +62,27 @@ def test_decrypt_v2(binput, capsys, config_file, master_password): | |||
| 59 | main(['-c', f'{config_file}', '-d']) | 62 | main(['-c', f'{config_file}', '-d']) |
| 60 | assert exit_info.type == SystemExit | 63 | assert exit_info.type == SystemExit |
| 61 | assert exit_info.value.code == 0 | 64 | assert exit_info.value.code == 0 |
| 62 | assert capsys.readouterr().out.strip() == 'Decrypted value: bar' | 65 | assert capsys.readouterr().out.strip() == ( |
| 66 | f'Decrypted value: {short_value}' | ||
| 67 | ) | ||
| 63 | 68 | ||
| 64 | 69 | ||
| 65 | @unittest.mock.patch('os.urandom') | 70 | @unittest.mock.patch('os.urandom') |
| 66 | @unittest.mock.patch('builtins.input') | 71 | @unittest.mock.patch('builtins.input') |
| 67 | def test_encrypt_with_echo( | 72 | def test_encrypt_with_echo( |
| 68 | binput, urandom, capsys, non_random_bytes_61, config_file, master_password | 73 | binput, |
| 74 | urandom, | ||
| 75 | capsys, | ||
| 76 | non_random_bytes_57, | ||
| 77 | config_file, | ||
| 78 | master_password, | ||
| 79 | short_encrypted_value, | ||
| 80 | short_value, | ||
| 69 | ): | 81 | ): |
| 70 | """Tests encryption via the CLI interface""" | 82 | """Tests encryption via the CLI interface""" |
| 71 | 83 | ||
| 72 | binput.return_value = 'bar' | 84 | binput.return_value = short_value |
| 73 | urandom.return_value = non_random_bytes_61 | 85 | urandom.return_value = non_random_bytes_57 |
| 74 | with unittest.mock.patch.dict( | 86 | with unittest.mock.patch.dict( |
| 75 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} | 87 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} |
| 76 | ): | 88 | ): |
| @@ -79,21 +91,26 @@ def test_encrypt_with_echo( | |||
| 79 | assert exit_info.type == SystemExit | 91 | assert exit_info.type == SystemExit |
| 80 | assert exit_info.value.code == 0 | 92 | assert exit_info.value.code == 0 |
| 81 | assert capsys.readouterr().out.strip() == ( | 93 | assert capsys.readouterr().out.strip() == ( |
| 82 | 'Encrypted value: enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviq' | 94 | f'Encrypted value: {short_encrypted_value}' |
| 83 | 'rLTBxM=$+Yo6Ya2MAVcBLTQHuATkyFc+dzYsL/E' | ||
| 84 | 'SvA6ofOUDsiKZvIff35cUHAmoNxVuGG+MXv4=' | ||
| 85 | ) | 95 | ) |
| 86 | 96 | ||
| 87 | 97 | ||
| 88 | @unittest.mock.patch('os.urandom') | 98 | @unittest.mock.patch('os.urandom') |
| 89 | @unittest.mock.patch('getpass.getpass') | 99 | @unittest.mock.patch('getpass.getpass') |
| 90 | def test_encrypt_without_echo( | 100 | def test_encrypt_without_echo( |
| 91 | getpass, urandom, capsys, non_random_bytes_61, config_file, master_password | 101 | getpass, |
| 102 | urandom, | ||
| 103 | capsys, | ||
| 104 | non_random_bytes_57, | ||
| 105 | config_file, | ||
| 106 | master_password, | ||
| 107 | short_encrypted_value, | ||
| 108 | short_value, | ||
| 92 | ): | 109 | ): |
| 93 | """Tests encryption via the CLI interface""" | 110 | """Tests encryption via the CLI interface""" |
| 94 | 111 | ||
| 95 | getpass.return_value = 'bar' | 112 | getpass.return_value = short_value |
| 96 | urandom.return_value = non_random_bytes_61 | 113 | urandom.return_value = non_random_bytes_57 |
| 97 | with unittest.mock.patch.dict( | 114 | with unittest.mock.patch.dict( |
| 98 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} | 115 | os.environ, {'ETOOLKIT_MASTER_PASSWORD': master_password} |
| 99 | ): | 116 | ): |
| @@ -102,13 +119,11 @@ def test_encrypt_without_echo( | |||
| 102 | assert exit_info.type == SystemExit | 119 | assert exit_info.type == SystemExit |
| 103 | assert exit_info.value.code == 0 | 120 | assert exit_info.value.code == 0 |
| 104 | assert capsys.readouterr().out.strip() == ( | 121 | assert capsys.readouterr().out.strip() == ( |
| 105 | 'Encrypted value: enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviq' | 122 | f'Encrypted value: {short_encrypted_value}' |
| 106 | 'rLTBxM=$+Yo6Ya2MAVcBLTQHuATkyFc+dzYsL/E' | ||
| 107 | 'SvA6ofOUDsiKZvIff35cUHAmoNxVuGG+MXv4=' | ||
| 108 | ) | 123 | ) |
| 109 | 124 | ||
| 110 | 125 | ||
| 111 | def test_fetch_encrypted_value(config_file, master_password): | 126 | def test_fetch_encrypted_value(config_file, master_password, short_value): |
| 112 | """Tests decryption of encrypted value""" | 127 | """Tests decryption of encrypted value""" |
| 113 | 128 | ||
| 114 | with unittest.mock.patch.dict( | 129 | with unittest.mock.patch.dict( |
| @@ -116,7 +131,7 @@ def test_fetch_encrypted_value(config_file, master_password): | |||
| 116 | ): | 131 | ): |
| 117 | assert os.environ.get('ETOOLKIT_TEST_PASSWORD') is None | 132 | assert os.environ.get('ETOOLKIT_TEST_PASSWORD') is None |
| 118 | main(['-c', f'{config_file}', '-q', '-s', '/bin/false', 'secret']) | 133 | main(['-c', f'{config_file}', '-q', '-s', '/bin/false', 'secret']) |
| 119 | assert os.environ.get('ETOOLKIT_TEST_PASSWORD') == 'bar' | 134 | assert os.environ.get('ETOOLKIT_TEST_PASSWORD') == short_value |
| 120 | 135 | ||
| 121 | 136 | ||
| 122 | def test_list(capsys, config_file, nonexistent_config_file): | 137 | def test_list(capsys, config_file, nonexistent_config_file): |
diff --git a/tests/test_envtoolkit_instance.py b/tests/test_envtoolkit_instance.py index 0147c6f..9873d57 100644 --- a/tests/test_envtoolkit_instance.py +++ b/tests/test_envtoolkit_instance.py | |||
| @@ -41,7 +41,9 @@ def test_instantiation(config_data): | |||
| 41 | assert instance.master_password is None | 41 | assert instance.master_password is None |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | def test_get_environ(config_data, master_password, wrong_master_password): | 44 | def test_get_environ( |
| 45 | config_data, master_password, short_value, wrong_master_password | ||
| 46 | ): | ||
| 45 | """Tests the EtoolkitInstance.get_environ method""" | 47 | """Tests the EtoolkitInstance.get_environ method""" |
| 46 | 48 | ||
| 47 | instance = etoolkit.EtoolkitInstance('secret', config_data) | 49 | instance = etoolkit.EtoolkitInstance('secret', config_data) |
| @@ -61,7 +63,7 @@ def test_get_environ(config_data, master_password, wrong_master_password): | |||
| 61 | instance.master_password = master_password | 63 | instance.master_password = master_password |
| 62 | env = instance.get_environ() | 64 | env = instance.get_environ() |
| 63 | assert isinstance(env, dict) | 65 | assert isinstance(env, dict) |
| 64 | assert env['ETOOLKIT_TEST_PASSWORD'] == 'bar' | 66 | assert env['ETOOLKIT_TEST_PASSWORD'] == short_value |
| 65 | 67 | ||
| 66 | 68 | ||
| 67 | def test_get_full_name(config_data): | 69 | def test_get_full_name(config_data): |
diff --git a/tests/test_envtoolkit_instance_static.py b/tests/test_envtoolkit_instance_static.py index b3b24f0..ee5cf9e 100644 --- a/tests/test_envtoolkit_instance_static.py +++ b/tests/test_envtoolkit_instance_static.py | |||
| @@ -37,18 +37,14 @@ def test_confirm_password_prompt(getpass, password_hash, master_password): | |||
| 37 | ) | 37 | ) |
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | def test_decrypt_v1(master_password): | 40 | def test_decrypt_v1(master_password, short_encrypted_value_v1, short_value): |
| 41 | """Tests the static EtoolkitInstance.decrypt method""" | 41 | """Tests the static EtoolkitInstance.decrypt method""" |
| 42 | 42 | ||
| 43 | assert ( | 43 | assert ( |
| 44 | etoolkit.EtoolkitInstance.decrypt( | 44 | etoolkit.EtoolkitInstance.decrypt( |
| 45 | master_password, | 45 | master_password, short_encrypted_value_v1 |
| 46 | ( | ||
| 47 | 'enc-val$1$/cXpEMoZrTlb9yokGhw8tLTSUkqnqJ4ZoAkurNgMYx' | ||
| 48 | 'w=$1VdkSMcZnLRwLiu1M8VlYcbelwmiVNY=' | ||
| 49 | ), | ||
| 50 | ) | 46 | ) |
| 51 | == 'secret1' | 47 | == short_value |
| 52 | ) | 48 | ) |
| 53 | 49 | ||
| 54 | # now test with modified edata | 50 | # now test with modified edata |
| @@ -62,117 +58,106 @@ def test_decrypt_v1(master_password): | |||
| 62 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' | 58 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' |
| 63 | 59 | ||
| 64 | 60 | ||
| 65 | def test_decrypt_v2_no_padding(master_password): | 61 | def test_decrypt_v2_no_padding( |
| 62 | master_password, long_encrypted_value, long_value | ||
| 63 | ): | ||
| 66 | """Tests the static EtoolkitInstance.decrypt method for v2 - no padding""" | 64 | """Tests the static EtoolkitInstance.decrypt method for v2 - no padding""" |
| 67 | 65 | ||
| 68 | assert ( | 66 | assert ( |
| 69 | etoolkit.EtoolkitInstance.decrypt( | 67 | etoolkit.EtoolkitInstance.decrypt( |
| 70 | master_password, | 68 | master_password, long_encrypted_value |
| 71 | ( | ||
| 72 | 'enc-val$2$Wer5lECGyeZhhYS58N18WVx5Zzy+rrC+BPlq3Dw89wQ=$' | ||
| 73 | 'SQc0ox6Emf2m5rrumsiptpIZEujdpXXSR/' | ||
| 74 | '1VcfEZeBz4+KDSagr9ID+bkc4R2yFdxHnhig1eqQ8=' | ||
| 75 | ), | ||
| 76 | ) | 69 | ) |
| 77 | == 'Nobody expects the Spanish inquisition' | 70 | == long_value |
| 78 | ) | 71 | ) |
| 79 | 72 | ||
| 80 | # now test with modified edata | 73 | # now test with modified encrypted data |
| 81 | edata = ( | 74 | edata = long_encrypted_value[:60] + '5' + long_encrypted_value[61:] |
| 82 | 'enc-val$2$Wer5lECGyeZhhYS58N18WVx5Zzy+rrC+BPlq3Dw89wQ=$' | 75 | |
| 83 | 'SQc0ox6Emf2m4rrumsiptpIZEujdpXXSR/' | ||
| 84 | '1VcfEZeBz4+KDSagr9ID+bkc4R2yFdxHnhig1eqQ8=' | ||
| 85 | ) | ||
| 86 | with pytest.raises(etoolkit.EtoolkitInstanceError) as exc_info: | 76 | with pytest.raises(etoolkit.EtoolkitInstanceError) as exc_info: |
| 87 | etoolkit.EtoolkitInstance.decrypt(master_password, edata) | 77 | etoolkit.EtoolkitInstance.decrypt(master_password, edata) |
| 88 | assert exc_info.type is etoolkit.EtoolkitInstanceError | 78 | assert exc_info.type is etoolkit.EtoolkitInstanceError |
| 89 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' | 79 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' |
| 90 | 80 | ||
| 91 | 81 | ||
| 92 | def test_decrypt_v2_with_padding(master_password): | 82 | def test_decrypt_v2_with_padding( |
| 83 | master_password, short_encrypted_value, short_value | ||
| 84 | ): | ||
| 93 | """Tests the static EtoolkitInstance.decrypt method for v2 with padding""" | 85 | """Tests the static EtoolkitInstance.decrypt method for v2 with padding""" |
| 94 | 86 | ||
| 95 | assert ( | 87 | assert ( |
| 96 | etoolkit.EtoolkitInstance.decrypt( | 88 | etoolkit.EtoolkitInstance.decrypt( |
| 97 | master_password, | 89 | master_password, short_encrypted_value |
| 98 | ( | ||
| 99 | 'enc-val$2$//kzyUbDEWNoPC5dyukhB8de8+IVaLR2ngx2HwkfOuM=$' | ||
| 100 | 'rhRona4wP9nhnXjcHqwkjFDsiVVVjYanAs' | ||
| 101 | 'N4kknNkgC0ix4RtJQHYDeTzw1rrR1vb2w=' | ||
| 102 | ), | ||
| 103 | ) | 90 | ) |
| 104 | == 'secret1' | 91 | == short_value |
| 105 | ) | 92 | ) |
| 106 | 93 | ||
| 107 | # now test with modified edata | 94 | # now test with modified edata |
| 108 | edata = ( | 95 | edata = short_encrypted_value[:60] + '5' + short_encrypted_value[61:] |
| 109 | 'enc-val$2$//kzyUbDEWNoPC5dyukhB8de8+IVaLR2ngx2HwkfOuM=$' | ||
| 110 | 'rhRona4wP8nhnXjcHqwkjFDsiVVVjYanAsN4kknNkgC0ix4RtJQHYDeTzw1rrR1vb2w=' | ||
| 111 | ) | ||
| 112 | with pytest.raises(etoolkit.EtoolkitInstanceError) as exc_info: | 96 | with pytest.raises(etoolkit.EtoolkitInstanceError) as exc_info: |
| 113 | etoolkit.EtoolkitInstance.decrypt(master_password, edata) | 97 | etoolkit.EtoolkitInstance.decrypt(master_password, edata) |
| 114 | assert exc_info.type is etoolkit.EtoolkitInstanceError | 98 | assert exc_info.type is etoolkit.EtoolkitInstanceError |
| 115 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' | 99 | assert exc_info.value.args[0] == f'Invalid tag when decrypting: {edata}' |
| 116 | 100 | ||
| 117 | 101 | ||
| 118 | def test_encrypt_no_padding(master_password): | 102 | def test_encrypt_no_padding(master_password, long_value): |
| 119 | """Tests the static EtoolkitInstance.encrypt method with a long string""" | 103 | """Tests the static EtoolkitInstance.encrypt method with a long string""" |
| 120 | 104 | ||
| 121 | edata = etoolkit.EtoolkitInstance.encrypt( | 105 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, long_value) |
| 122 | master_password, 'Nobody expects the Spanish inquisition' | ||
| 123 | ) | ||
| 124 | assert edata.startswith('enc-val$2$') | 106 | assert edata.startswith('enc-val$2$') |
| 125 | assert len(edata) == 131 | 107 | assert len(edata) == 131 |
| 126 | # the edata should always be different because of random salting | 108 | # the edata should always be different because of random salting |
| 127 | assert edata != etoolkit.EtoolkitInstance.encrypt( | 109 | assert edata != etoolkit.EtoolkitInstance.encrypt( |
| 128 | master_password, 'Nobody expects the Spanish inquisition' | 110 | master_password, long_value |
| 129 | ) | 111 | ) |
| 130 | 112 | ||
| 131 | 113 | ||
| 132 | def test_encrypt_with_padding(master_password): | 114 | def test_encrypt_with_padding(master_password, short_value): |
| 133 | """Tests the static EtoolkitInstance.encrypt method with a short string""" | 115 | """Tests the static EtoolkitInstance.encrypt method with a short string""" |
| 134 | 116 | ||
| 135 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, 'bar') | 117 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, short_value) |
| 136 | assert edata.startswith('enc-val$2$') | 118 | assert edata.startswith('enc-val$2$') |
| 137 | assert len(edata) == 123 | 119 | assert len(edata) == 123 |
| 138 | # the edata should always be different because of random salting | 120 | # the edata should always be different because of random salting |
| 139 | assert edata != etoolkit.EtoolkitInstance.encrypt(master_password, 'bar') | 121 | assert edata != etoolkit.EtoolkitInstance.encrypt( |
| 122 | master_password, short_value | ||
| 123 | ) | ||
| 140 | 124 | ||
| 141 | 125 | ||
| 142 | @unittest.mock.patch('os.urandom') | 126 | @unittest.mock.patch('os.urandom') |
| 143 | def test_encrypt_staticly_no_padding( | 127 | def test_encrypt_staticly_no_padding( |
| 144 | urandom, master_password, non_random_bytes_32 | 128 | urandom, |
| 129 | master_password, | ||
| 130 | non_random_bytes_32, | ||
| 131 | long_encrypted_value, | ||
| 132 | long_value, | ||
| 145 | ): | 133 | ): |
| 146 | """Tests the EtoolkitInstance.encrypt method always with the same salt""" | 134 | """Tests the EtoolkitInstance.encrypt method always with the same salt""" |
| 147 | 135 | ||
| 148 | urandom.return_value = non_random_bytes_32 | 136 | urandom.return_value = non_random_bytes_32 |
| 149 | edata = etoolkit.EtoolkitInstance.encrypt( | 137 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, long_value) |
| 150 | master_password, 'Nobody expects the Spanish inquisition' | 138 | assert edata == long_encrypted_value |
| 151 | ) | ||
| 152 | assert edata == ( | ||
| 153 | 'enc-val$2$uYpZM1VfAGq0CDZL2duITs076CQj+hIFEgx+F4mn80o=$' | ||
| 154 | 'UX/5YeRsh5/2vZ2J1UOS+BJti73Kbp6C1pJmC' | ||
| 155 | 'o8hFSujpe35X/XpzAiYv4BV1LNwnSYECsotsgs=' | ||
| 156 | ) | ||
| 157 | assert len(edata) == 131 | 139 | assert len(edata) == 131 |
| 158 | assert edata == etoolkit.EtoolkitInstance.encrypt( | 140 | assert edata == etoolkit.EtoolkitInstance.encrypt( |
| 159 | master_password, 'Nobody expects the Spanish inquisition' | 141 | master_password, long_value |
| 160 | ) | 142 | ) |
| 161 | 143 | ||
| 162 | 144 | ||
| 163 | @unittest.mock.patch('os.urandom') | 145 | @unittest.mock.patch('os.urandom') |
| 164 | def test_encrypt_staticly_with_padding( | 146 | def test_encrypt_staticly_with_padding( |
| 165 | urandom, master_password, non_random_bytes_61 | 147 | urandom, |
| 148 | master_password, | ||
| 149 | non_random_bytes_57, | ||
| 150 | short_encrypted_value, | ||
| 151 | short_value, | ||
| 166 | ): | 152 | ): |
| 167 | """Tests the EtoolkitInstance.encrypt method always with the same salt""" | 153 | """Tests the EtoolkitInstance.encrypt method always with the same salt""" |
| 168 | 154 | ||
| 169 | urandom.return_value = non_random_bytes_61 | 155 | urandom.return_value = non_random_bytes_57 |
| 170 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, 'bar') | 156 | edata = etoolkit.EtoolkitInstance.encrypt(master_password, short_value) |
| 171 | assert edata == ( | 157 | assert edata == short_encrypted_value |
| 172 | 'enc-val$2$RCSZqq9pWrRDoCVYVHopyu1LzaJGfv8roVviqrLTBxM=$' | 158 | assert edata == etoolkit.EtoolkitInstance.encrypt( |
| 173 | '+Yo6Ya2MAVcBLTQHuATkyFc+dzYsL/ESvA6ofOUDsiKZvIff35cUHAmoNxVuGG+MXv4=' | 159 | master_password, short_value |
| 174 | ) | 160 | ) |
| 175 | assert edata == etoolkit.EtoolkitInstance.encrypt(master_password, 'bar') | ||
| 176 | 161 | ||
| 177 | 162 | ||
| 178 | def test_get_new_password_hash(master_password): | 163 | def test_get_new_password_hash(master_password): |
| @@ -208,3 +193,38 @@ def test_password_matches( | |||
| 208 | assert not etoolkit.EtoolkitInstance.password_matches( | 193 | assert not etoolkit.EtoolkitInstance.password_matches( |
| 209 | wrong_master_password, password_hash | 194 | wrong_master_password, password_hash |
| 210 | ) | 195 | ) |
| 196 | |||
| 197 | |||
| 198 | @unittest.mock.patch('os.urandom') | ||
| 199 | def test_reencrypt_staticly_with_padding( | ||
| 200 | urandom, | ||
| 201 | master_password, | ||
| 202 | new_master_password, | ||
| 203 | non_random_bytes_57, | ||
| 204 | short_encrypted_value, | ||
| 205 | short_encrypted_value_v1, | ||
| 206 | short_value, | ||
| 207 | ): | ||
| 208 | """Tests the EtoolkitInstance.reencrypt method always with the same salt""" | ||
| 209 | |||
| 210 | urandom.return_value = non_random_bytes_57 | ||
| 211 | # reencrypt (migrate) v1 to current using the same password | ||
| 212 | edata = etoolkit.EtoolkitInstance.reencrypt( | ||
| 213 | master_password, master_password, short_encrypted_value_v1 | ||
| 214 | ) | ||
| 215 | assert edata == short_encrypted_value | ||
| 216 | |||
| 217 | # same version, same salt, same edata | ||
| 218 | assert edata == etoolkit.EtoolkitInstance.reencrypt( | ||
| 219 | master_password, master_password, edata | ||
| 220 | ) | ||
| 221 | |||
| 222 | # use different password | ||
| 223 | edata = etoolkit.EtoolkitInstance.reencrypt( | ||
| 224 | master_password, new_master_password, edata | ||
| 225 | ) | ||
| 226 | assert edata != short_encrypted_value | ||
| 227 | assert ( | ||
| 228 | etoolkit.EtoolkitInstance.decrypt(new_master_password, edata) | ||
| 229 | == short_value | ||
| 230 | ) | ||
