Rename and regroup all test...
Marco Ricci authored 4 months ago
|
1) # SPDX-FileCopyrightText: 2024 Marco Ricci <m@the13thletter.info>
2) #
3) # SPDX-License-Identifier: MIT
4)
5) """Test passphrase generation via derivepassphrase.Vault."""
6)
7) from __future__ import annotations
8)
9) import math
10) from typing import Any
11)
12) import derivepassphrase
13) import pytest
14)
15) Vault = derivepassphrase.Vault
16)
17) class TestVault:
18)
19) phrase = b'She cells C shells bye the sea shoars'
20) google_phrase = rb': 4TVH#5:aZl8LueOT\{'
21) twitter_phrase = rb"[ (HN_N:lI&<ro=)3'g9"
22)
23) @pytest.mark.parametrize(['service', 'expected'], [
24) (b'google', google_phrase),
25) ('twitter', twitter_phrase),
26) ])
27) def test_200_basic_configuration(self, service, expected):
28) assert Vault(phrase=self.phrase).generate(service) == expected
29)
30) def test_201_phrase_dependence(self):
31) assert (
32) Vault(phrase=(self.phrase + b'X')).generate('google') ==
33) b'n+oIz6sL>K*lTEWYRO%7'
34) )
35)
36) def test_202_reproducibility_and_bytes_service_name(self):
37) assert (
38) Vault(phrase=self.phrase).generate(b'google') ==
39) Vault(phrase=self.phrase).generate('google')
40) )
41)
42) def test_203_reproducibility_and_bytearray_service_name(self):
43) assert (
44) Vault(phrase=self.phrase).generate(b'google') ==
45) Vault(phrase=self.phrase).generate(bytearray(b'google'))
46) )
47)
48) def test_210_nonstandard_length(self):
49) assert (
50) Vault(phrase=self.phrase, length=4).generate('google')
51) == b'xDFu'
52) )
53)
54) def test_211_repetition_limit(self):
55) assert (
56) Vault(phrase=b'', length=24, symbol=0, number=0,
57) repeat=1).generate('asd') ==
58) b'IVTDzACftqopUXqDHPkuCIhV'
59) )
60)
61) def test_212_without_symbols(self):
62) assert (
63) Vault(phrase=self.phrase, symbol=0).generate('google') ==
64) b'XZ4wRe0bZCazbljCaMqR'
65) )
66)
67) def test_213_no_numbers(self):
68) assert (
69) Vault(phrase=self.phrase, number=0).generate('google') ==
70) b'_*$TVH.%^aZl(LUeOT?>'
71) )
72)
73) def test_214_no_lowercase_letters(self):
74) assert (
75) Vault(phrase=self.phrase, lower=0).generate('google') ==
76) b':{?)+7~@OA:L]!0E$)(+'
77) )
78)
79) def test_215_at_least_5_digits(self):
80) assert (
81) Vault(phrase=self.phrase, length=8, number=5)
82) .generate('songkick') == b'i0908.7['
83) )
84)
85) def test_216_lots_of_spaces(self):
86) assert (
87) Vault(phrase=self.phrase, space=12)
88) .generate('songkick') == b' c 6 Bq % 5fR '
89) )
90)
91) def test_217_all_character_classes(self):
92) assert (
93) Vault(phrase=self.phrase, lower=2, upper=2, number=1,
94) space=3, dash=2, symbol=1)
95) .generate('google') == b': : fv_wqt>a-4w1S R'
96) )
97)
98) def test_218_only_numbers_and_very_high_repetition_limit(self):
99) generated = Vault(phrase=b'', length=40, lower=0, upper=0, space=0,
100) dash=0, symbol=0, repeat=4).generate('abcdef')
101) forbidden_substrings = {b'0000', b'1111', b'2222', b'3333', b'4444',
102) b'5555', b'6666', b'7777', b'8888', b'9999'}
103) for substring in forbidden_substrings:
104) assert substring not in generated
105)
106) def test_219_very_limited_character_set(self):
107) generated = Vault(phrase=b'', length=24, lower=0, upper=0,
108) space=0, symbol=0).generate('testing')
109) assert b'763252593304946694588866' == generated
110)
111) def test_220_character_set_subtraction(self):
112) assert Vault._subtract(b'be', b'abcdef') == bytearray(b'acdf')
113)
114) @pytest.mark.parametrize(['length', 'settings', 'entropy'], [
115) (20, {}, math.log2(math.factorial(20)) + 20 * math.log2(94)),
116) (
117) 20,
118) {'upper': 0, 'number': 0, 'space': 0, 'symbol': 0},
119) math.log2(math.factorial(20)) + 20 * math.log2(26)
120) ),
121) (0, {}, float('-inf')),
122) (0, {'lower': 0, 'number': 0, 'space': 0, 'symbol': 0}, float('-inf')),
123) (1, {}, math.log2(94)),
124) (1, {'upper': 0, 'lower': 0, 'number': 0, 'symbol': 0}, 0.0),
125) ])
126) def test_221_entropy(
127) self, length: int, settings: dict[str, int], entropy: int
128) ) -> None:
129) v = Vault(length=length, **settings) # type: ignore[arg-type]
130) assert math.isclose(v._entropy(), entropy)
131) assert v._estimate_sufficient_hash_length() > 0
132) if math.isfinite(entropy) and entropy:
133) assert (
134) v._estimate_sufficient_hash_length(1.0) ==
135) math.ceil(entropy / 8)
136) )
137) assert v._estimate_sufficient_hash_length(8.0) >= entropy
138)
139) def test_222_hash_length_estimation(self) -> None:
|