66import pytest
77
88from passlib import hash
9- from passlib .handlers .bcrypt import (
10- IDENT_2 ,
11- IDENT_2A ,
12- IDENT_2B ,
13- IDENT_2X ,
14- IDENT_2Y ,
15- )
9+ from passlib .handlers .bcrypt import IDENT_2 , IDENT_2A , IDENT_2B , IDENT_2X , IDENT_2Y
10+ from passlib .handlers .bcrypt import bcrypt as bcrypt_handler
1611from passlib .utils import repeat_string , to_bytes
12+ from passlib .utils .handlers import GenericHandler
1713from tests .test_handlers import UPASS_TABLE
1814from tests .utils import TEST_MODE , HandlerCase
1915from tests .utils_ import no_warnings
@@ -26,101 +22,7 @@ class _bcrypt_test(HandlerCase):
2622 reduce_default_rounds = True
2723 fuzz_salts_need_bcrypt_repair = True
2824
29- known_correct_hashes = [
30- #
31- # from JTR 1.7.9
32- #
33- ("U*U*U*U*" , "$2a$05$c92SVSfjeiCD6F2nAD6y0uBpJDjdRkt0EgeC4/31Rf2LUZbDRDE.O" ),
34- ("U*U***U" , "$2a$05$WY62Xk2TXZ7EvVDQ5fmjNu7b0GEzSzUXUh2cllxJwhtOeMtWV3Ujq" ),
35- ("U*U***U*" , "$2a$05$Fa0iKV3E2SYVUlMknirWU.CFYGvJ67UwVKI1E2FP6XeLiZGcH3MJi" ),
36- ("*U*U*U*U" , "$2a$05$.WRrXibc1zPgIdRXYfv.4uu6TD1KWf0VnHzq/0imhUhuxSxCyeBs2" ),
37- ("" , "$2a$05$Otz9agnajgrAe0.kFVF9V.tzaStZ2s1s4ZWi/LY4sw2k/MTVFj/IO" ),
38- #
39- # test vectors from http://www.openwall.com/crypt v1.2
40- # note that this omits any hashes that depend on crypt_blowfish's
41- # various CVE-2011-2483 workarounds (hash 2a and \xff\xff in password,
42- # and any 2x hashes); and only contain hashes which are correct
43- # under both crypt_blowfish 1.2 AND OpenBSD.
44- #
45- ("U*U" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW" ),
46- ("U*U*" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK" ),
47- ("U*U*U" , "$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a" ),
48- ("" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy" ),
49- (
50- "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
51- "0123456789chars after 72 are ignored" ,
52- "$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui" ,
53- ),
54- (b"\xa3 " , "$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq" ),
55- (
56- b"\xff \xa3 345" ,
57- "$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e" ,
58- ),
59- (b"\xa3 ab" , "$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS" ),
60- (
61- b"\xaa " * 72 + b"chars after 72 are ignored as usual" ,
62- "$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6" ,
63- ),
64- (
65- b"\xaa \x55 " * 36 ,
66- "$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy" ,
67- ),
68- (
69- b"\x55 \xaa \xff " * 24 ,
70- "$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe" ,
71- ),
72- # keeping one of their 2y tests, because we are supporting that.
73- (b"\xa3 " , "$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq" ),
74- #
75- # 8bit bug (fixed in 2y/2b)
76- #
77- # NOTE: see assert_lacks_8bit_bug() for origins of this test vector.
78- (b"\xd1 \x91 " , "$2y$05$6bNw2HLQYeqHYyBfLMsv/OUcZd0LKP39b87nBw3.S2tVZSqiQX6eu" ),
79- #
80- # bsd wraparound bug (fixed in 2b)
81- #
82- # NOTE: if backend is vulnerable, password will hash the same as '0'*72
83- # ("$2a$04$R1lJ2gkNaoPGdafE.H.16.nVyh2niHsGJhayOHLMiXlI45o8/DU.6"),
84- # rather than same as ("0123456789"*8)[:72]
85- # 255 should be sufficient, but checking
86- (
87- ("0123456789" * 26 )[:254 ],
88- "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
89- ),
90- (
91- ("0123456789" * 26 )[:255 ],
92- "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
93- ),
94- (
95- ("0123456789" * 26 )[:256 ],
96- "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
97- ),
98- (
99- ("0123456789" * 26 )[:257 ],
100- "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
101- ),
102- #
103- # from py-bcrypt tests
104- #
105- ("" , "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." ),
106- ("a" , "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" ),
107- ("abc" , "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" ),
108- (
109- "abcdefghijklmnopqrstuvwxyz" ,
110- "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" ,
111- ),
112- (
113- "~!@#$%^&*() ~!@#$%^&*()PNBFRD" ,
114- "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" ,
115- ),
116- #
117- # custom test vectors
118- #
119- # ensures utf-8 used for unicode
120- (UPASS_TABLE , "$2a$05$Z17AXnnlpzddNUvnC6cZNOSwMA/8oNiKnHTHTwLlBijfucQQlHjaG" ),
121- # ensure 2b support
122- (UPASS_TABLE , "$2b$05$Z17AXnnlpzddNUvnC6cZNOSwMA/8oNiKnHTHTwLlBijfucQQlHjaG" ),
123- ]
25+ known_correct_hashes = []
12426
12527 if TEST_MODE ("full" ):
12628 #
@@ -356,8 +258,153 @@ def test_needs_update_w_padding(self):
356258 assert not bcrypt .needs_update (GOOD1 )
357259
358260
261+ @pytest .mark .usefixtures ("bcrypt_backend_raises_on_wraparound_unittest" )
262+ class bcrypt_test (_bcrypt_test ):
263+ __test__ = False
264+
265+ def test_secret_with_truncate_size (self ) -> None :
266+ if not self .bcrypt_backend_raises_on_wraparound : # type: ignore[attr-defined]
267+ super ().test_secret_with_truncate_size ()
268+
269+ def test_77_fuzz_input (self , threaded : bool = False ) -> None :
270+ if not self .bcrypt_backend_raises_on_wraparound : # type: ignore[attr-defined]
271+ super ().test_77_fuzz_input (threaded = threaded )
272+
273+
359274# create test cases for specific backends
360- bcrypt_bcrypt_test = _bcrypt_test .create_backend_case ("bcrypt" )
275+ bcrypt_bcrypt_test = bcrypt_test .create_backend_case ("bcrypt" )
276+
277+
278+ @pytest .fixture (scope = "session" )
279+ def handler () -> type [GenericHandler ]:
280+ return bcrypt_handler
281+
282+
283+ @pytest .mark .parametrize (
284+ ("secret" , "hash" ),
285+ [
286+ #
287+ # from JTR 1.7.9
288+ #
289+ ("U*U*U*U*" , "$2a$05$c92SVSfjeiCD6F2nAD6y0uBpJDjdRkt0EgeC4/31Rf2LUZbDRDE.O" ),
290+ ("U*U***U" , "$2a$05$WY62Xk2TXZ7EvVDQ5fmjNu7b0GEzSzUXUh2cllxJwhtOeMtWV3Ujq" ),
291+ ("U*U***U*" , "$2a$05$Fa0iKV3E2SYVUlMknirWU.CFYGvJ67UwVKI1E2FP6XeLiZGcH3MJi" ),
292+ ("*U*U*U*U" , "$2a$05$.WRrXibc1zPgIdRXYfv.4uu6TD1KWf0VnHzq/0imhUhuxSxCyeBs2" ),
293+ ("" , "$2a$05$Otz9agnajgrAe0.kFVF9V.tzaStZ2s1s4ZWi/LY4sw2k/MTVFj/IO" ),
294+ #
295+ # test vectors from http://www.openwall.com/crypt v1.2
296+ # note that this omits any hashes that depend on crypt_blowfish's
297+ # various CVE-2011-2483 workarounds (hash 2a and \xff\xff in password,
298+ # and any 2x hashes); and only contain hashes which are correct
299+ # under both crypt_blowfish 1.2 AND OpenBSD.
300+ #
301+ ("U*U" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW" ),
302+ ("U*U*" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK" ),
303+ ("U*U*U" , "$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a" ),
304+ ("" , "$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy" ),
305+ (
306+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
307+ "0123456789chars after 72 are ignored" ,
308+ "$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui" ,
309+ ),
310+ (b"\xa3 " , "$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq" ),
311+ (
312+ b"\xff \xa3 345" ,
313+ "$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e" ,
314+ ),
315+ (b"\xa3 ab" , "$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS" ),
316+ (
317+ b"\xaa " * 72 + b"chars after 72 are ignored as usual" ,
318+ "$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6" ,
319+ ),
320+ (
321+ b"\xaa \x55 " * 36 ,
322+ "$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy" ,
323+ ),
324+ (
325+ b"\x55 \xaa \xff " * 24 ,
326+ "$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe" ,
327+ ),
328+ # keeping one of their 2y tests, because we are supporting that.
329+ (b"\xa3 " , "$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq" ),
330+ #
331+ # 8bit bug (fixed in 2y/2b)
332+ #
333+ # NOTE: see assert_lacks_8bit_bug() for origins of this test vector.
334+ (b"\xd1 \x91 " , "$2y$05$6bNw2HLQYeqHYyBfLMsv/OUcZd0LKP39b87nBw3.S2tVZSqiQX6eu" ),
335+ #
336+ # bsd wraparound bug (fixed in 2b)
337+ #
338+ # NOTE: if backend is vulnerable, password will hash the same as '0'*72
339+ # ("$2a$04$R1lJ2gkNaoPGdafE.H.16.nVyh2niHsGJhayOHLMiXlI45o8/DU.6"),
340+ # rather than same as ("0123456789"*8)[:72]
341+ # 255 should be sufficient, but checking
342+ (
343+ ("0123456789" * 26 )[:254 ],
344+ "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
345+ ),
346+ (
347+ ("0123456789" * 26 )[:255 ],
348+ "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
349+ ),
350+ (
351+ ("0123456789" * 26 )[:256 ],
352+ "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
353+ ),
354+ (
355+ ("0123456789" * 26 )[:257 ],
356+ "$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi" ,
357+ ),
358+ #
359+ # from py-bcrypt tests
360+ #
361+ ("" , "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." ),
362+ ("a" , "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" ),
363+ ("abc" , "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" ),
364+ (
365+ "abcdefghijklmnopqrstuvwxyz" ,
366+ "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" ,
367+ ),
368+ (
369+ "~!@#$%^&*() ~!@#$%^&*()PNBFRD" ,
370+ "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" ,
371+ ),
372+ #
373+ # custom test vectors
374+ #
375+ # ensures utf-8 used for unicode
376+ (UPASS_TABLE , "$2a$05$Z17AXnnlpzddNUvnC6cZNOSwMA/8oNiKnHTHTwLlBijfucQQlHjaG" ),
377+ # ensure 2b support
378+ (UPASS_TABLE , "$2b$05$Z17AXnnlpzddNUvnC6cZNOSwMA/8oNiKnHTHTwLlBijfucQQlHjaG" ),
379+ ],
380+ )
381+ def test_known_hashes (
382+ secret : str ,
383+ hash : str ,
384+ bcrypt_backend_raises_on_wraparound : bool ,
385+ handler : GenericHandler ,
386+ ) -> None :
387+ assert handler .truncate_size
388+
389+ if bcrypt_backend_raises_on_wraparound and len (secret ) > handler .truncate_size :
390+ return
391+
392+ assert handler .verify (secret = secret , hash = hash )
393+
394+
395+ def test_with_truncate_size (
396+ handler : GenericHandler ,
397+ bcrypt_backend_raises_on_wraparound : bool ,
398+ ) -> None :
399+ if bcrypt_backend_raises_on_wraparound :
400+ return
401+
402+ assert handler .truncate_size
403+
404+ long_secret = "abc" * handler .truncate_size
405+
406+ hashed = handler .hash (secret = long_secret )
407+ assert handler .verify (secret = long_secret [: handler .truncate_size ], hash = hashed )
361408
362409
363410class _bcrypt_sha256_test (HandlerCase ):
@@ -591,5 +638,4 @@ def test_calc_digest_v2(self):
591638 assert result == bcrypt_digest
592639
593640
594- # create test cases for specific backends
595641bcrypt_sha256_bcrypt_test = _bcrypt_sha256_test .create_backend_case ("bcrypt" )
0 commit comments