diff options
| author | Simeon Simeonov | 2024-05-13 21:52:13 +0200 |
|---|---|---|
| committer | Simeon Simeonov | 2024-05-13 21:52:13 +0200 |
| commit | 08a3280b062af83ee50fa139d7827d954907886e (patch) | |
| tree | 8e1d3f3117d05b3ad779d070ec30ddbbe242e62b /tests/test_envtoolkit_instance_static.py | |
| parent | bb9a844e22134a2537652ea14f93e82acb4ee380 (diff) | |
Implement re-encryption support2.0.0
Diffstat (limited to 'tests/test_envtoolkit_instance_static.py')
| -rw-r--r-- | tests/test_envtoolkit_instance_static.py | 136 |
1 files changed, 78 insertions, 58 deletions
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 | ) | ||
