summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSimeon Simeonov2026-05-01 14:34:04 +0200
committerSimeon Simeonov2026-05-01 14:34:04 +0200
commitbfae04723bd3155801f079ab5238018ec8a0cb09 (patch)
tree7db35cefe64d00bb23b26513fa13afbf26c073dd /tests
parent751c74e7de1c78a151fdd8b76f220d8411a2108a (diff)
Redesign API by introducing otp2289.OTPResponse typeHEADv2.0.0nextmaster
Diffstat (limited to 'tests')
-rw-r--r--tests/test_generator.py278
-rw-r--r--tests/test_server.py4
-rw-r--r--tests/test_static.py38
3 files changed, 215 insertions, 105 deletions
diff --git a/tests/test_generator.py b/tests/test_generator.py
index 08947e5..68d3bfe 100644
--- a/tests/test_generator.py
+++ b/tests/test_generator.py
@@ -35,26 +35,26 @@ def test_caller_exceptions() -> None:
35 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_MD5 35 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_MD5
36 ) 36 )
37 with pytest.raises(otp2289.OTPGeneratorError) as exc_info: 37 with pytest.raises(otp2289.OTPGeneratorError) as exc_info:
38 gen.generate_otp_words('3') # ty: ignore[invalid-argument-type] 38 gen.generate_otp_response('3') # ty: ignore[invalid-argument-type]
39 assert exc_info.type is otp2289.OTPGeneratorError 39 assert exc_info.type is otp2289.OTPGeneratorError
40 assert exc_info.value.args[0] == 'Step value MUST be an int' 40 assert exc_info.value.args[0] == 'Step value MUST be an int'
41 with pytest.raises(otp2289.OTPGeneratorError) as exc_info: 41 with pytest.raises(otp2289.OTPGeneratorError) as exc_info:
42 gen.generate_otp_hexdigest(-1) 42 gen.generate_otp_response(-1)
43 assert exc_info.type is otp2289.OTPGeneratorError 43 assert exc_info.type is otp2289.OTPGeneratorError
44 assert exc_info.value.args[0] == 'Step value MUST be >= 0' 44 assert exc_info.value.args[0] == 'Step value MUST be >= 0'
45 with pytest.raises(otp2289.OTPChallengeError) as exc_info: 45 with pytest.raises(otp2289.OTPChallengeError) as exc_info:
46 gen.generate_otp_hexdigest_from_challenge( 46 gen.generate_otp_response_from_challenge(
47 b'md5 fbd TeSt' # ty: ignore[invalid-argument-type] 47 b'md5 fbd TeSt' # ty: ignore[invalid-argument-type]
48 ) 48 )
49 assert exc_info.type is otp2289.OTPChallengeError 49 assert exc_info.type is otp2289.OTPChallengeError
50 assert exc_info.value.args[0] == 'Challenge must be str' 50 assert exc_info.value.args[0] == 'Challenge must be str'
51 with pytest.raises(otp2289.OTPChallengeError) as exc_info: 51 with pytest.raises(otp2289.OTPChallengeError) as exc_info:
52 gen.generate_otp_hexdigest_from_challenge('md5 fbd TeSt') 52 gen.generate_otp_response_from_challenge('md5 fbd TeSt')
53 assert exc_info.type is otp2289.OTPChallengeError 53 assert exc_info.type is otp2289.OTPChallengeError
54 assert exc_info.value.args[0] == 'Invalid challenge' 54 assert exc_info.value.args[0] == 'Invalid challenge'
55 with pytest.raises(otp2289.generator.OTPChallengeError) as exc_info: 55 with pytest.raises(otp2289.OTPChallengeError) as exc_info:
56 gen.generate_otp_hexdigest_from_challenge('otp-md5 fbd TeSt') 56 gen.generate_otp_response_from_challenge('otp-md5 fbd TeSt')
57 assert exc_info.type is otp2289.generator.OTPChallengeError 57 assert exc_info.type is otp2289.OTPChallengeError
58 assert exc_info.value.args[0] == 'Invalid challenge' 58 assert exc_info.value.args[0] == 'Invalid challenge'
59 59
60 60
@@ -102,9 +102,9 @@ def test_constructor_exceptions() -> None:
102 assert exc_info.type is otp2289.OTPGeneratorError 102 assert exc_info.type is otp2289.OTPGeneratorError
103 assert exc_info.value.args[0] == 'hash_algo must be an int or a str' 103 assert exc_info.value.args[0] == 'hash_algo must be an int or a str'
104 # test the package structure as well 104 # test the package structure as well
105 with pytest.raises(otp2289.generator.OTPGeneratorError) as exc_info: 105 with pytest.raises(otp2289.OTPGeneratorError) as exc_info:
106 otp2289.generator.OTPGenerator(b'This is a test.', 'TeSt', 'foo') 106 otp2289.OTPGenerator(b'This is a test.', 'TeSt', 'foo')
107 assert exc_info.type is otp2289.generator.OTPGeneratorError 107 assert exc_info.type is otp2289.OTPGeneratorError
108 assert exc_info.value.args[0] == ( 108 assert exc_info.value.args[0] == (
109 'foo is not supported by this version of the hashlib module' 109 'foo is not supported by this version of the hashlib module'
110 ) 110 )
@@ -133,59 +133,148 @@ def test_md5() -> None:
133 gen = otp2289.OTPGenerator( 133 gen = otp2289.OTPGenerator(
134 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_MD5 134 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_MD5
135 ) 135 )
136 res_words = gen.generate_otp_words(0) 136 response = gen.generate_otp_response(0)
137 res_hex = gen.generate_otp_hexdigest(0) 137 assert isinstance(response, otp2289.OTPResponse)
138 assert isinstance(res_words, str) 138 assert isinstance(response.words, str)
139 assert isinstance(res_hex, str) 139 assert isinstance(response.hexdigest, str)
140 assert res_hex == '0x9e876134d90499dd' 140 assert response.hexdigest == '0x9e876134d90499dd'
141 assert res_words == 'INCH SEA ANNE LONG AHEM TOUR' 141 assert response.words == 'INCH SEA ANNE LONG AHEM TOUR'
142
142 # step 1 143 # step 1
143 assert gen.generate_otp_hexdigest(1) == '0x7965e05436f5029f' 144 response = gen.generate_otp_response(1)
144 assert gen.generate_otp_words(1) == 'EASE OIL FUM CURE AWRY AVIS' 145 assert response.hexdigest == '0x7965e05436f5029f'
145 assert gen.generate_otp_hexdigest_from_challenge('otp-md5 1 TeSt') == ( 146 assert response.words == 'EASE OIL FUM CURE AWRY AVIS'
146 '0x7965e05436f5029f' 147 assert (
148 gen.generate_otp_response_from_challenge('otp-md5 1 TeSt').hexdigest
149 == '0x7965e05436f5029f'
147 ) 150 )
148 assert gen.generate_otp_words_from_challenge('otp-md5 1 TeSt') == ( 151 assert (
149 'EASE OIL FUM CURE AWRY AVIS' 152 gen.generate_otp_response_from_challenge('otp-md5 1 TeSt').words
153 == 'EASE OIL FUM CURE AWRY AVIS'
150 ) 154 )
155
151 # step 99 156 # step 99
152 assert gen.generate_otp_hexdigest(99) == '0x50fe1962c4965880' 157 response = gen.generate_otp_response(99)
153 assert gen.generate_otp_words(99) == 'BAIL TUFT BITS GANG CHEF THY' 158 assert response.hexdigest == '0x50fe1962c4965880'
154 assert gen.generate_otp_hexdigest_from_challenge('otp-md5 99 TeSt') == ( 159 assert response.words == 'BAIL TUFT BITS GANG CHEF THY'
155 '0x50fe1962c4965880' 160 assert (
161 gen.generate_otp_response_from_challenge('otp-md5 99 TeSt').hexdigest
162 == '0x50fe1962c4965880'
156 ) 163 )
157 assert gen.generate_otp_words_from_challenge('otp-md5 99 TeSt') == ( 164 assert (
158 'BAIL TUFT BITS GANG CHEF THY' 165 gen.generate_otp_response_from_challenge('otp-md5 99 TeSt').words
166 == 'BAIL TUFT BITS GANG CHEF THY'
159 ) 167 )
168
160 # iterator test 169 # iterator test
161 hexdigests = list(gen.hexdigest_range(105)) # testing the range itself 170 hexdigests = list(gen.otp_response_range(105)) # testing the range itself
162 words = list(gen.words_range(99)) 171 words = list(gen.otp_response_range(99))
163 hexdigests.reverse() 172 hexdigests.reverse()
164 words.reverse() 173 words.reverse()
165 assert hexdigests[0] == '0x9e876134d90499dd' 174 assert hexdigests[0].hexdigest == '0x9e876134d90499dd'
166 assert hexdigests[1] == '0x7965e05436f5029f' 175 assert hexdigests[1].hexdigest == '0x7965e05436f5029f'
167 assert hexdigests[99] == '0x50fe1962c4965880' 176 assert hexdigests[99].hexdigest == '0x50fe1962c4965880'
168 assert words[0] == 'INCH SEA ANNE LONG AHEM TOUR' 177 assert words[0].words == 'INCH SEA ANNE LONG AHEM TOUR'
169 assert words[1] == 'EASE OIL FUM CURE AWRY AVIS' 178 assert words[1].words == 'EASE OIL FUM CURE AWRY AVIS'
170 assert words[99] == 'BAIL TUFT BITS GANG CHEF THY' 179 assert words[99].words == 'BAIL TUFT BITS GANG CHEF THY'
180
171 # pass='AbCdEfGhIjK', seed='alpha1' 181 # pass='AbCdEfGhIjK', seed='alpha1'
172 gen = otp2289.OTPGenerator(b'AbCdEfGhIjK', 'alpha1', otp2289.OTP_ALGO_MD5) 182 gen = otp2289.OTPGenerator(b'AbCdEfGhIjK', 'alpha1', otp2289.OTP_ALGO_MD5)
173 assert gen.generate_otp_hexdigest(0) == '0x87066dd9644bf206' 183 response = gen.generate_otp_response(0)
174 assert gen.generate_otp_words(0) == 'FULL PEW DOWN ONCE MORT ARC' 184 assert response.hexdigest == '0x87066dd9644bf206'
175 assert gen.generate_otp_hexdigest(1) == '0x7cd34c1040add14b' 185 assert response.words == 'FULL PEW DOWN ONCE MORT ARC'
176 assert gen.generate_otp_words(1) == 'FACT HOOF AT FIST SITE KENT' 186 response = gen.generate_otp_response(1)
177 assert gen.generate_otp_hexdigest(99) == '0x5aa37a81f212146c' 187 assert response.hexdigest == '0x7cd34c1040add14b'
178 assert gen.generate_otp_words(99) == 'BODE HOP JAKE STOW JUT RAP' 188 assert response.words == 'FACT HOOF AT FIST SITE KENT'
189 response = gen.generate_otp_response(99)
190 assert response.hexdigest == '0x5aa37a81f212146c'
191 assert response.words == 'BODE HOP JAKE STOW JUT RAP'
192
179 # pass="OTP's are good", seed='correct' 193 # pass="OTP's are good", seed='correct'
180 gen = otp2289.OTPGenerator( 194 gen = otp2289.OTPGenerator(
181 b"OTP's are good", 'correct', otp2289.OTP_ALGO_MD5 195 b"OTP's are good", 'correct', otp2289.OTP_ALGO_MD5
182 ) 196 )
183 assert gen.generate_otp_hexdigest(0) == '0xf205753943de4cf9' 197 response = gen.generate_otp_response(0)
184 assert gen.generate_otp_words(0) == 'ULAN NEW ARMY FUSE SUIT EYED' 198 assert response.hexdigest == '0xf205753943de4cf9'
185 assert gen.generate_otp_hexdigest(1) == '0xddcdac956f234937' 199 assert response.words == 'ULAN NEW ARMY FUSE SUIT EYED'
186 assert gen.generate_otp_words(1) == 'SKIM CULT LOB SLAM POE HOWL' 200 response = gen.generate_otp_response(1)
187 assert gen.generate_otp_hexdigest(99) == '0xb203e28fa525be47' 201 assert response.hexdigest == '0xddcdac956f234937'
188 assert gen.generate_otp_words(99) == 'LONG IVY JULY AJAR BOND LEE' 202 assert response.words == 'SKIM CULT LOB SLAM POE HOWL'
203 response = gen.generate_otp_response(99)
204 assert response.hexdigest == '0xb203e28fa525be47'
205 assert response.words == 'LONG IVY JULY AJAR BOND LEE'
206
207
208def test_otp_response() -> None:
209 """Tests OTPResponse"""
210 gen = otp2289.OTPGenerator(
211 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_MD5
212 )
213 response = gen.generate_otp_response(0)
214 assert response.response_bytes == bytes(response)
215
216 # From 'RFC-2289 Appendix C - OTP Verification Examples'
217 # hexdigest: 9e876134d90499dd
218 # words: INCH SEA ANNE LONG AHEM TOUR
219 response_from_tokens = otp2289.OTPResponse.from_tokens(
220 'INCH SEA ANNE LONG AHEM TOUR'
221 )
222 response_from_hex1 = otp2289.OTPResponse.from_hex('9e876134d90499dd')
223 response_from_hex2 = otp2289.OTPResponse.from_hex('0x9e876134d90499dd')
224 assert (
225 response_from_tokens.response_bytes
226 == response_from_hex1.response_bytes
227 )
228 assert (
229 response_from_tokens.response_bytes
230 == response_from_hex2.response_bytes
231 )
232
233 # same tests, only using __eq__
234 assert response_from_tokens == response_from_hex1
235 assert response_from_tokens == response_from_hex2
236
237
238def test_otp_response_exceptions() -> None:
239 """Tests OTPResponse exceptions"""
240 with pytest.raises(otp2289.OTPResponseError) as exc_info:
241 otp2289.OTPResponse.from_hex(
242 b'9e876134d90499dd' # ty: ignore[invalid-argument-type]
243 )
244 assert exc_info.type is otp2289.OTPResponseError
245 assert exc_info.value.args[0] == 'OT-hex must be a str'
246 with pytest.raises(otp2289.OTPResponseError) as exc_info:
247 otp2289.OTPResponse.from_hex('9e876134d90499d')
248 assert exc_info.type is otp2289.OTPResponseError
249 assert exc_info.value.args[0] == (
250 'The length of the hex should be 16 (representing 64 bits digest)'
251 )
252 with pytest.raises(otp2289.OTPResponseError) as exc_info:
253 otp2289.OTPResponse.from_hex('9e876134d90499dg')
254 assert exc_info.type is otp2289.OTPResponseError
255 assert exc_info.value.args[0] == 'Invalid OT-hex'
256
257 # .from_tokens
258 with pytest.raises(otp2289.OTPResponseError) as exc_info:
259 otp2289.OTPResponse.from_tokens(
260 b'INCH SEA ANNE LONG AHEM TOUR' # ty: ignore[invalid-argument-type]
261 )
262 assert exc_info.type is otp2289.OTPResponseError
263 assert exc_info.value.args[0] == 'tokens must be a str'
264 with pytest.raises(otp2289.OTPResponseError) as exc_info:
265 otp2289.OTPResponse.from_tokens('INCH SEA ANNE LONG AHEM')
266 assert exc_info.type is otp2289.OTPResponseError
267 assert exc_info.value.args[0] == 'Tokens-string does not contain 6 tokens'
268 with pytest.raises(otp2289.OTPResponseError) as exc_info:
269 otp2289.OTPResponse.from_tokens('INCH SEA ANNE LONG AHEM SIMEON')
270 assert exc_info.type is otp2289.OTPResponseError
271 assert exc_info.value.args[0] == (
272 'One or more words not present in RFC1760'
273 )
274 with pytest.raises(otp2289.OTPResponseError) as exc_info:
275 otp2289.OTPResponse.from_tokens('INCH SEA ANNE LONG AHEM LEE')
276 assert exc_info.type is otp2289.OTPResponseError
277 assert exc_info.value.args[0] == 'Invalid bit checksum'
189 278
190 279
191def test_sha1() -> None: 280def test_sha1() -> None:
@@ -198,54 +287,71 @@ def test_sha1() -> None:
198 gen = otp2289.OTPGenerator( 287 gen = otp2289.OTPGenerator(
199 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_SHA1 288 b'This is a test.', 'TeSt', otp2289.OTP_ALGO_SHA1
200 ) 289 )
201 res_hex = gen.generate_otp_hexdigest(step=0) 290 response = gen.generate_otp_response(step=0)
202 res_words = gen.generate_otp_words(step=0) 291 assert isinstance(response, otp2289.OTPResponse)
203 assert isinstance(res_words, str) 292 assert isinstance(response.words, str)
204 assert isinstance(res_hex, str) 293 assert isinstance(response.hexdigest, str)
205 assert res_hex == '0xbb9e6ae1979d8ff4' 294 assert response.hexdigest == '0xbb9e6ae1979d8ff4'
206 assert res_words == 'MILT VARY MAST OK SEES WENT' 295 assert response.words == 'MILT VARY MAST OK SEES WENT'
207 assert gen.generate_otp_hexdigest(1) == '0x63d936639734385b' 296 response = gen.generate_otp_response(1)
208 assert gen.generate_otp_words(1) == 'CART OTTO HIVE ODE VAT NUT' 297 assert response.hexdigest == '0x63d936639734385b'
209 assert gen.generate_otp_hexdigest_from_challenge('otp-sha1 1 TeSt') == ( 298 assert response.words == 'CART OTTO HIVE ODE VAT NUT'
210 '0x63d936639734385b' 299 assert (
300 gen.generate_otp_response_from_challenge('otp-sha1 1 TeSt').hexdigest
301 == '0x63d936639734385b'
211 ) 302 )
212 assert gen.generate_otp_words_from_challenge('otp-sha1 1 TeSt') == ( 303 assert (
213 'CART OTTO HIVE ODE VAT NUT' 304 gen.generate_otp_response_from_challenge('otp-sha1 1 TeSt').words
305 == 'CART OTTO HIVE ODE VAT NUT'
214 ) 306 )
215 assert gen.generate_otp_hexdigest(99) == '0x87fec7768b73ccf9' 307 response = gen.generate_otp_response(99)
216 assert gen.generate_otp_words(99) == 'GAFF WAIT SKID GIG SKY EYED' 308 assert response.hexdigest == '0x87fec7768b73ccf9'
217 assert gen.generate_otp_hexdigest_from_challenge('otp-sha1 99 TeSt') == ( 309 assert response.words == 'GAFF WAIT SKID GIG SKY EYED'
218 '0x87fec7768b73ccf9' 310 assert (
311 gen.generate_otp_response_from_challenge(
312 'otp-sha1 99 TeSt'
313 ).hexdigest
314 == '0x87fec7768b73ccf9'
219 ) 315 )
220 assert gen.generate_otp_words_from_challenge('otp-sha1 99 TeSt') == ( 316 assert (
221 'GAFF WAIT SKID GIG SKY EYED' 317 gen.generate_otp_response_from_challenge('otp-sha1 99 TeSt').words
318 == 'GAFF WAIT SKID GIG SKY EYED'
222 ) 319 )
320
223 # iterator test 321 # iterator test
224 hexdigests = list(gen.hexdigest_range(105)) 322 hexdigests = list(gen.otp_response_range(105))
225 words = list(gen.words_range(99)) 323 words = list(gen.otp_response_range(99))
226 hexdigests.reverse() 324 hexdigests.reverse()
227 words.reverse() 325 words.reverse()
228 assert hexdigests[0] == '0xbb9e6ae1979d8ff4' 326 assert hexdigests[0].hexdigest == '0xbb9e6ae1979d8ff4'
229 assert hexdigests[1] == '0x63d936639734385b' 327 assert hexdigests[1].hexdigest == '0x63d936639734385b'
230 assert hexdigests[99] == '0x87fec7768b73ccf9' 328 assert hexdigests[99].hexdigest == '0x87fec7768b73ccf9'
231 assert words[0] == 'MILT VARY MAST OK SEES WENT' 329 assert words[0].words == 'MILT VARY MAST OK SEES WENT'
232 assert words[1] == 'CART OTTO HIVE ODE VAT NUT' 330 assert words[1].words == 'CART OTTO HIVE ODE VAT NUT'
233 assert words[99] == 'GAFF WAIT SKID GIG SKY EYED' 331 assert words[99].words == 'GAFF WAIT SKID GIG SKY EYED'
332
234 # pass='AbCdEfGhIjK', seed='alpha1' 333 # pass='AbCdEfGhIjK', seed='alpha1'
235 gen = otp2289.OTPGenerator(b'AbCdEfGhIjK', 'alpha1', otp2289.OTP_ALGO_SHA1) 334 gen = otp2289.OTPGenerator(b'AbCdEfGhIjK', 'alpha1', otp2289.OTP_ALGO_SHA1)
236 assert gen.generate_otp_hexdigest(0) == '0xad85f658ebe383c9' 335 response = gen.generate_otp_response(0)
237 assert gen.generate_otp_words(0) == 'LEST OR HEEL SCOT ROB SUIT' 336 assert response.hexdigest == '0xad85f658ebe383c9'
238 assert gen.generate_otp_hexdigest(1) == '0xd07ce229b5cf119b' 337 assert response.words == 'LEST OR HEEL SCOT ROB SUIT'
239 assert gen.generate_otp_words(1) == 'RITE TAKE GELD COST TUNE RECK' 338 response = gen.generate_otp_response(1)
240 assert gen.generate_otp_hexdigest(99) == '0x27bc71035aaf3dc6' 339 assert response.hexdigest == '0xd07ce229b5cf119b'
241 assert gen.generate_otp_words(99) == 'MAY STAR TIN LYON VEDA STAN' 340 assert response.words == 'RITE TAKE GELD COST TUNE RECK'
341 response = gen.generate_otp_response(99)
342 assert response.hexdigest == '0x27bc71035aaf3dc6'
343 assert response.words == 'MAY STAR TIN LYON VEDA STAN'
344
242 # pass="OTP's are good", seed='correct' 345 # pass="OTP's are good", seed='correct'
243 gen = otp2289.OTPGenerator( 346 gen = otp2289.OTPGenerator(
244 b"OTP's are good", 'correct', otp2289.OTP_ALGO_SHA1 347 b"OTP's are good", 'correct', otp2289.OTP_ALGO_SHA1
245 ) 348 )
246 assert gen.generate_otp_hexdigest(0) == '0xd51f3e99bf8e6f0b' 349 response = gen.generate_otp_response(0)
247 assert gen.generate_otp_words(0) == 'RUST WELT KICK FELL TAIL FRAU' 350 assert response.hexdigest == '0xd51f3e99bf8e6f0b'
248 assert gen.generate_otp_hexdigest(1) == '0x82aeb52d943774e4' 351 assert response.words == 'RUST WELT KICK FELL TAIL FRAU'
249 assert gen.generate_otp_words(1) == 'FLIT DOSE ALSO MEW DRUM DEFY' 352 response = gen.generate_otp_response(1)
250 assert gen.generate_otp_hexdigest(99) == '0x4f296a74fe1567ec' 353 assert response.hexdigest == '0x82aeb52d943774e4'
251 assert gen.generate_otp_words(99) == 'AURA ALOE HURL WING BERG WAIT' 354 assert response.words == 'FLIT DOSE ALSO MEW DRUM DEFY'
355 response = gen.generate_otp_response(99)
356 assert response.hexdigest == '0x4f296a74fe1567ec'
357 assert response.words == 'AURA ALOE HURL WING BERG WAIT'
diff --git a/tests/test_server.py b/tests/test_server.py
index 3099cf7..41a6aea 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -75,6 +75,8 @@ def test_state_validation_md5() -> None:
75 assert state.validated is False 75 assert state.validated is False
76 assert state.response_validates('0x9e876134d90499dd') is True 76 assert state.response_validates('0x9e876134d90499dd') is True
77 assert state.response_validates('INCH SEA ANNE LONG AHEM TOUR') is True 77 assert state.response_validates('INCH SEA ANNE LONG AHEM TOUR') is True
78 response = otp2289.OTPResponse(bytes.fromhex('9e876134d90499dd'))
79 assert state.response_validates(response) is True
78 assert state.ot_hex == '7965e05436f5029f' 80 assert state.ot_hex == '7965e05436f5029f'
79 assert state.validated is True 81 assert state.validated is True
80 82
@@ -87,6 +89,8 @@ def test_state_validation_sha1() -> None:
87 assert state.validated is False 89 assert state.validated is False
88 assert state.response_validates('0xbb9e6ae1979d8ff4') is True 90 assert state.response_validates('0xbb9e6ae1979d8ff4') is True
89 assert state.response_validates('MILT VARY MAST OK SEES WENT') is True 91 assert state.response_validates('MILT VARY MAST OK SEES WENT') is True
92 response = otp2289.OTPResponse(bytes.fromhex('bb9e6ae1979d8ff4'))
93 assert state.response_validates(response) is True
90 assert state.ot_hex == '63d936639734385b' 94 assert state.ot_hex == '63d936639734385b'
91 assert state.validated is True 95 assert state.validated is True
92 96
diff --git a/tests/test_static.py b/tests/test_static.py
index 589fc17..7268e84 100644
--- a/tests/test_static.py
+++ b/tests/test_static.py
@@ -32,58 +32,58 @@ import otp2289
32def test_bytes_and_tokens() -> None: 32def test_bytes_and_tokens() -> None:
33 """Tests the official hex and tokens defined in RFC2289""" 33 """Tests the official hex and tokens defined in RFC2289"""
34 assert bytes.fromhex('9e876134d90499dd') == ( 34 assert bytes.fromhex('9e876134d90499dd') == (
35 otp2289.OTPGenerator.tokens_to_bytes('INCH SEA ANNE LONG AHEM TOUR') 35 otp2289.OTPResponse.tokens_to_bytes('INCH SEA ANNE LONG AHEM TOUR')
36 ) 36 )
37 assert bytes.fromhex('7965e05436f5029f') == ( 37 assert bytes.fromhex('7965e05436f5029f') == (
38 otp2289.OTPGenerator.tokens_to_bytes('EASE OIL FUM CURE AWRY AVIS') 38 otp2289.OTPResponse.tokens_to_bytes('EASE OIL FUM CURE AWRY AVIS')
39 ) 39 )
40 assert bytes.fromhex('50fe1962c4965880') == ( 40 assert bytes.fromhex('50fe1962c4965880') == (
41 otp2289.OTPGenerator.tokens_to_bytes('BAIL TUFT BITS GANG CHEF THY') 41 otp2289.OTPResponse.tokens_to_bytes('BAIL TUFT BITS GANG CHEF THY')
42 ) 42 )
43 assert bytes.fromhex('87066dd9644bf206') == ( 43 assert bytes.fromhex('87066dd9644bf206') == (
44 otp2289.OTPGenerator.tokens_to_bytes('FULL PEW DOWN ONCE MORT ARC') 44 otp2289.OTPResponse.tokens_to_bytes('FULL PEW DOWN ONCE MORT ARC')
45 ) 45 )
46 assert bytes.fromhex('7cd34c1040add14b') == ( 46 assert bytes.fromhex('7cd34c1040add14b') == (
47 otp2289.OTPGenerator.tokens_to_bytes('FACT HOOF AT FIST SITE KENT') 47 otp2289.OTPResponse.tokens_to_bytes('FACT HOOF AT FIST SITE KENT')
48 ) 48 )
49 assert bytes.fromhex('5aa37a81f212146c') == ( 49 assert bytes.fromhex('5aa37a81f212146c') == (
50 otp2289.OTPGenerator.tokens_to_bytes('BODE HOP JAKE STOW JUT RAP') 50 otp2289.OTPResponse.tokens_to_bytes('BODE HOP JAKE STOW JUT RAP')
51 ) 51 )
52 assert bytes.fromhex('f205753943de4cf9') == ( 52 assert bytes.fromhex('f205753943de4cf9') == (
53 otp2289.OTPGenerator.tokens_to_bytes('ULAN NEW ARMY FUSE SUIT EYED') 53 otp2289.OTPResponse.tokens_to_bytes('ULAN NEW ARMY FUSE SUIT EYED')
54 ) 54 )
55 assert bytes.fromhex('ddcdac956f234937') == ( 55 assert bytes.fromhex('ddcdac956f234937') == (
56 otp2289.OTPGenerator.tokens_to_bytes('SKIM CULT LOB SLAM POE HOWL') 56 otp2289.OTPResponse.tokens_to_bytes('SKIM CULT LOB SLAM POE HOWL')
57 ) 57 )
58 assert bytes.fromhex('b203e28fa525be47') == ( 58 assert bytes.fromhex('b203e28fa525be47') == (
59 otp2289.OTPGenerator.tokens_to_bytes('LONG IVY JULY AJAR BOND LEE') 59 otp2289.OTPResponse.tokens_to_bytes('LONG IVY JULY AJAR BOND LEE')
60 ) 60 )
61 assert bytes.fromhex('bb9e6ae1979d8ff4') == ( 61 assert bytes.fromhex('bb9e6ae1979d8ff4') == (
62 otp2289.OTPGenerator.tokens_to_bytes('MILT VARY MAST OK SEES WENT') 62 otp2289.OTPResponse.tokens_to_bytes('MILT VARY MAST OK SEES WENT')
63 ) 63 )
64 assert bytes.fromhex('63d936639734385b') == ( 64 assert bytes.fromhex('63d936639734385b') == (
65 otp2289.OTPGenerator.tokens_to_bytes('CART OTTO HIVE ODE VAT NUT') 65 otp2289.OTPResponse.tokens_to_bytes('CART OTTO HIVE ODE VAT NUT')
66 ) 66 )
67 assert bytes.fromhex('87fec7768b73ccf9') == ( 67 assert bytes.fromhex('87fec7768b73ccf9') == (
68 otp2289.OTPGenerator.tokens_to_bytes('GAFF WAIT SKID GIG SKY EYED') 68 otp2289.OTPResponse.tokens_to_bytes('GAFF WAIT SKID GIG SKY EYED')
69 ) 69 )
70 assert bytes.fromhex('ad85f658ebe383c9') == ( 70 assert bytes.fromhex('ad85f658ebe383c9') == (
71 otp2289.OTPGenerator.tokens_to_bytes('LEST OR HEEL SCOT ROB SUIT') 71 otp2289.OTPResponse.tokens_to_bytes('LEST OR HEEL SCOT ROB SUIT')
72 ) 72 )
73 assert bytes.fromhex('d07ce229b5cf119b') == ( 73 assert bytes.fromhex('d07ce229b5cf119b') == (
74 otp2289.OTPGenerator.tokens_to_bytes('RITE TAKE GELD COST TUNE RECK') 74 otp2289.OTPResponse.tokens_to_bytes('RITE TAKE GELD COST TUNE RECK')
75 ) 75 )
76 assert bytes.fromhex('27bc71035aaf3dc6') == ( 76 assert bytes.fromhex('27bc71035aaf3dc6') == (
77 otp2289.OTPGenerator.tokens_to_bytes('MAY STAR TIN LYON VEDA STAN') 77 otp2289.OTPResponse.tokens_to_bytes('MAY STAR TIN LYON VEDA STAN')
78 ) 78 )
79 assert bytes.fromhex('d51f3e99bf8e6f0b') == ( 79 assert bytes.fromhex('d51f3e99bf8e6f0b') == (
80 otp2289.OTPGenerator.tokens_to_bytes('RUST WELT KICK FELL TAIL FRAU') 80 otp2289.OTPResponse.tokens_to_bytes('RUST WELT KICK FELL TAIL FRAU')
81 ) 81 )
82 assert bytes.fromhex('82aeb52d943774e4') == ( 82 assert bytes.fromhex('82aeb52d943774e4') == (
83 otp2289.OTPGenerator.tokens_to_bytes('FLIT DOSE ALSO MEW DRUM DEFY') 83 otp2289.OTPResponse.tokens_to_bytes('FLIT DOSE ALSO MEW DRUM DEFY')
84 ) 84 )
85 assert bytes.fromhex('4f296a74fe1567ec') == ( 85 assert bytes.fromhex('4f296a74fe1567ec') == (
86 otp2289.OTPGenerator.tokens_to_bytes('AURA ALOE HURL WING BERG WAIT') 86 otp2289.OTPResponse.tokens_to_bytes('AURA ALOE HURL WING BERG WAIT')
87 ) 87 )
88 88
89 89
@@ -92,4 +92,4 @@ def test_random_bytes() -> None:
92 for _ in range(10): 92 for _ in range(10):
93 rnd_bytes = os.urandom(8) # 64 bits 93 rnd_bytes = os.urandom(8) # 64 bits
94 tokens = otp2289.OTPResponse.bytes_to_tokens(rnd_bytes) 94 tokens = otp2289.OTPResponse.bytes_to_tokens(rnd_bytes)
95 assert rnd_bytes == otp2289.OTPGenerator.tokens_to_bytes(tokens) 95 assert rnd_bytes == otp2289.OTPResponse.tokens_to_bytes(tokens)