def test_smix(self): from otp.ai.passlib.crypto.scrypt._builtin import ScryptEngine rng = self.getRandom() input = hb( '\n f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd\n 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad\n 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29\n 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7\n 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb\n cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0\n 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b\n 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89\n ' ) output = hb( '\n 79 cc c1 93 62 9d eb ca 04 7f 0b 70 60 4b f6 b6\n 2c e3 dd 4a 96 26 e3 55 fa fc 61 98 e6 ea 2b 46\n d5 84 13 67 3b 99 b0 29 d6 65 c3 57 60 1f b4 26\n a0 b2 f4 bb a2 00 ee 9f 0a 43 d1 9b 57 1a 9c 71\n ef 11 42 e6 5d 5a 26 6f dd ca 83 2c e5 9f aa 7c\n ac 0b 9c f1 be 2b ff ca 30 0d 01 ee 38 76 19 c4\n ae 12 fd 44 38 f2 03 a0 e4 e1 c4 7e c3 14 86 1f\n 4e 90 87 cb 33 39 6a 68 73 e8 f9 d2 53 9a 4b 8e\n ' ) engine = ScryptEngine(n=16, r=1, p=rng.randint(1, 1023)) self.assertEqual(engine.smix(input), output)
def test_salsa(self): from otp.ai.passlib.crypto.scrypt._builtin import salsa20 input = unpack_uint32_list( hb('\n 7e 87 9a 21 4f 3e c9 86 7c a9 40 e6 41 71 8f 26\n ba ee 55 5b 8c 61 c1 b5 0d f8 46 11 6d cd 3b 1d\n ee 24 f3 19 df 9b 3d 85 14 12 1e 4b 5a c5 aa 32\n 76 02 1d 29 09 c7 48 29 ed eb c6 8d b8 b8 c2 5e\n ' )) output = unpack_uint32_list( hb('\n a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05\n 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29\n b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba\n e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81\n ' )) self.assertEqual(salsa20(input), output) input = list(range(16)) output = unpack_uint32_list( hb('\n f518dd4fb98883e0a87954c05cab867083bb8808552810752285a05822f56c16\n 9d4a2a0fd2142523d758c60b36411b682d53860514b871d27659042a5afa475d\n ' )) self.assertEqual(salsa20(input), output)
def test_b64s_encode(self): from otp.ai.passlib.utils.binary import b64s_encode self.assertEqual(b64s_encode(hb('69b7')), 'abc') self.assertRaises(TypeError if PY3 else UnicodeEncodeError, b64s_encode, hb('69b7').decode('latin-1')) self.assertEqual(b64s_encode(hb('69b71d')), 'abcd') self.assertEqual(b64s_encode(hb('69b71d79')), 'abcdeQ') self.assertEqual(b64s_encode(hb('69b71d79f8')), 'abcdefg') self.assertEqual(b64s_encode(hb('69bfbf')), 'ab+/')
def test_ab64_decode(self): from otp.ai.passlib.utils.binary import ab64_decode self.assertEqual(ab64_decode('abc'), hb('69b7')) self.assertEqual(ab64_decode(u('abc')), hb('69b7')) self.assertRaises(ValueError, ab64_decode, u('ab\xff')) self.assertRaises(TypeError, ab64_decode, 'ab\xff') self.assertRaises(TypeError, ab64_decode, 'ab!') self.assertRaises(TypeError, ab64_decode, u('ab!')) self.assertEqual(ab64_decode('abcd'), hb('69b71d')) self.assertRaises(ValueError, ab64_decode, 'abcde') self.assertEqual(ab64_decode('abcdef'), hb('69b71d79')) self.assertEqual(ab64_decode('abcdeQ'), hb('69b71d79')) self.assertEqual(ab64_decode('abcdefg'), hb('69b71d79f8')) self.assertEqual(ab64_decode('ab+/'), hb('69bfbf')) self.assertEqual(ab64_decode('ab./'), hb('69bfbf'))
class Pbkdf1_Test(TestCase): descriptionPrefix = 'passlib.utils.pbkdf2.pbkdf1()' pbkdf1_tests = [ ( 'password', hb('78578E5A5D63CB06'), 1000, 16, 'sha1', hb('dc19847e05c64d2faf10ebfb4a3d2a20')), ('password', 'salt', 1000, 0, 'md5', ''), ( 'password', 'salt', 1000, 1, 'md5', hb('84')), ( 'password', 'salt', 1000, 8, 'md5', hb('8475c6a8531a5d27')), ( 'password', 'salt', 1000, 16, 'md5', hb('8475c6a8531a5d27e386cd496457812c')), ( 'password', 'salt', 1000, None, 'md5', hb('8475c6a8531a5d27e386cd496457812c')), ( 'password', 'salt', 1000, None, 'sha1', hb('4a8fd48e426ed081b535be5769892fa396293efb'))] if not JYTHON: pbkdf1_tests.append(( 'password', 'salt', 1000, None, 'md4', hb('f7f2e91100a8f96190f2dd177cb26453'))) def setUp(self): super(Pbkdf1_Test, self).setUp() warnings.filterwarnings('ignore', '.*passlib.utils.pbkdf2.*deprecated', DeprecationWarning) def test_known(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf1 for secret, salt, rounds, keylen, digest, correct in self.pbkdf1_tests: result = pbkdf1(secret, salt, rounds, keylen, digest) self.assertEqual(result, correct) def test_border(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf1 def helper(secret='secret', salt='salt', rounds=1, keylen=1, hash='md5'): return pbkdf1(secret, salt, rounds, keylen, hash) helper() self.assertRaises(TypeError, helper, secret=1) self.assertRaises(TypeError, helper, salt=1) self.assertRaises(ValueError, helper, hash='missing') self.assertRaises(ValueError, helper, rounds=0) self.assertRaises(TypeError, helper, rounds='1') self.assertRaises(ValueError, helper, keylen=-1) self.assertRaises(ValueError, helper, keylen=17, hash='md5') self.assertRaises(TypeError, helper, keylen='1')
class _CommonScryptTest(TestCase): @classproperty def descriptionPrefix(cls): return 'passlib.utils.scrypt.scrypt() <%s backend>' % cls.backend backend = None def setUp(self): scrypt_mod._set_backend(self.backend) super(_CommonScryptTest, self).setUp() reference_vectors = [ ('', '', 16, 1, 1, 64, hb('\n 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97\n f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42\n fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17\n e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06\n ' )), ('password', 'NaCl', 1024, 8, 16, 64, hb('\n fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe\n 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62\n 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da\n c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40\n ' )), ('pleaseletmein', 'SodiumChloride', 16384, 8, 1, 64, hb('\n 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb\n fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2\n d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9\n e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87\n ' )), ('pleaseletmein', 'SodiumChloride', 1048576, 8, 1, 64, hb('\n 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81\n ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47\n 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3\n 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4\n ' )) ] def test_reference_vectors(self): for secret, salt, n, r, p, keylen, result in self.reference_vectors: if n >= 1024 and TEST_MODE(max='default'): continue if n > 16384 and self.backend == 'builtin': continue log.debug('scrypt reference vector: %r %r n=%r r=%r p=%r', secret, salt, n, r, p) self.assertEqual(scrypt_mod.scrypt(secret, salt, n, r, p, keylen), result) _already_tested_others = None def test_other_backends(self): if self._already_tested_others: raise self.skipTest('already run under %r backend test' % self._already_tested_others) self._already_tested_others = self.backend rng = self.getRandom() orig = scrypt_mod.backend available = set(name for name in scrypt_mod.backend_values if scrypt_mod._has_backend(name)) scrypt_mod._set_backend(orig) available.discard(self.backend) if not available: raise self.skipTest('no other backends found') warnings.filterwarnings('ignore', '(?i)using builtin scrypt backend', category=exc.PasslibSecurityWarning) for _ in range(10): secret = getrandbytes(rng, rng.randint(0, 64)) salt = getrandbytes(rng, rng.randint(0, 64)) n = 1 << rng.randint(1, 10) r = rng.randint(1, 8) p = rng.randint(1, 3) ks = rng.randint(1, 64) previous = None backends = set() for name in available: scrypt_mod._set_backend(name) self.assertNotIn(scrypt_mod._scrypt, backends) backends.add(scrypt_mod._scrypt) result = hexstr(scrypt_mod.scrypt(secret, salt, n, r, p, ks)) self.assertEqual(len(result), 2 * ks) if previous is not None: self.assertEqual( result, previous, msg='%r output differs from others %r: %r' % (name, available, [secret, salt, n, r, p, ks])) return def test_backend(self): scrypt_mod.backend = None scrypt_mod._scrypt = None self.assertRaises(TypeError, scrypt_mod.scrypt, 's', 's', 2, 2, 2, 16) scrypt_mod._set_backend(self.backend) self.assertEqual(scrypt_mod.backend, self.backend) scrypt_mod.scrypt('s', 's', 2, 2, 2, 16) self.assertRaises(ValueError, scrypt_mod._set_backend, 'xxx') self.assertEqual(scrypt_mod.backend, self.backend) return def test_secret_param(self): def run_scrypt(secret): return hexstr(scrypt_mod.scrypt(secret, 'salt', 2, 2, 2, 16)) TEXT = u('abc\\u00defg') self.assertEqual(run_scrypt(TEXT), '05717106997bfe0da42cf4779a2f8bd8') TEXT_UTF8 = 'abc\xc3\x9efg' self.assertEqual(run_scrypt(TEXT_UTF8), '05717106997bfe0da42cf4779a2f8bd8') TEXT_LATIN1 = 'abc\xdefg' self.assertEqual(run_scrypt(TEXT_LATIN1), '770825d10eeaaeaf98e8a3c40f9f441d') self.assertEqual(run_scrypt(''), 'ca1399e5fae5d3b9578dcd2b1faff6e2') self.assertRaises(TypeError, run_scrypt, None) self.assertRaises(TypeError, run_scrypt, 1) return def test_salt_param(self): def run_scrypt(salt): return hexstr(scrypt_mod.scrypt('secret', salt, 2, 2, 2, 16)) TEXT = u('abc\\u00defg') self.assertEqual(run_scrypt(TEXT), 'a748ec0f4613929e9e5f03d1ab741d88') TEXT_UTF8 = 'abc\xc3\x9efg' self.assertEqual(run_scrypt(TEXT_UTF8), 'a748ec0f4613929e9e5f03d1ab741d88') TEXT_LATIN1 = 'abc\xdefg' self.assertEqual(run_scrypt(TEXT_LATIN1), '91d056fb76fb6e9a7d1cdfffc0a16cd1') self.assertRaises(TypeError, run_scrypt, None) self.assertRaises(TypeError, run_scrypt, 1) return def test_n_param(self): def run_scrypt(n): return hexstr(scrypt_mod.scrypt('secret', 'salt', n, 2, 2, 16)) self.assertRaises(ValueError, run_scrypt, -1) self.assertRaises(ValueError, run_scrypt, 0) self.assertRaises(ValueError, run_scrypt, 1) self.assertEqual(run_scrypt(2), 'dacf2bca255e2870e6636fa8c8957a66') self.assertRaises(ValueError, run_scrypt, 3) self.assertRaises(ValueError, run_scrypt, 15) self.assertEqual(run_scrypt(16), '0272b8fc72bc54b1159340ed99425233') def test_r_param(self): def run_scrypt(r, n=2, p=2): return hexstr(scrypt_mod.scrypt('secret', 'salt', n, r, p, 16)) self.assertRaises(ValueError, run_scrypt, -1) self.assertRaises(ValueError, run_scrypt, 0) self.assertEqual(run_scrypt(1), '3d630447d9f065363b8a79b0b3670251') self.assertEqual(run_scrypt(2), 'dacf2bca255e2870e6636fa8c8957a66') self.assertEqual(run_scrypt(5), '114f05e985a903c27237b5578e763736') self.assertRaises(ValueError, run_scrypt, 1073741824, p=1) self.assertRaises(ValueError, run_scrypt, 1073741824 / 2, p=2) def test_p_param(self): def run_scrypt(p, n=2, r=2): return hexstr(scrypt_mod.scrypt('secret', 'salt', n, r, p, 16)) self.assertRaises(ValueError, run_scrypt, -1) self.assertRaises(ValueError, run_scrypt, 0) self.assertEqual(run_scrypt(1), 'f2960ea8b7d48231fcec1b89b784a6fa') self.assertEqual(run_scrypt(2), 'dacf2bca255e2870e6636fa8c8957a66') self.assertEqual(run_scrypt(5), '848a0eeb2b3543e7f543844d6ca79782') self.assertRaises(ValueError, run_scrypt, 1073741824, r=1) self.assertRaises(ValueError, run_scrypt, 1073741824 / 2, r=2) def test_keylen_param(self): rng = self.getRandom() def run_scrypt(keylen): return hexstr(scrypt_mod.scrypt('secret', 'salt', 2, 2, 2, keylen)) self.assertRaises(ValueError, run_scrypt, -1) self.assertRaises(ValueError, run_scrypt, 0) self.assertEqual(run_scrypt(1), 'da') ksize = rng.randint(0, 1024) self.assertEqual(len(run_scrypt(ksize)), 2 * ksize) self.assertRaises(ValueError, run_scrypt, 137438953441L)
engine = ScryptEngine(r=r, n=1 << rng.randint(1, 32), p=rng.randint(1, 1023)) target = [rng.randint(0, 4294967296L) for _ in range(2 * r * 16)] engine.bmix(input, target) self.assertEqual(target, list(output)) if r == 1: del engine.bmix target = [ rng.randint(0, 4294967296L) for _ in range(2 * r * 16) ] engine.bmix(input, target) self.assertEqual(target, list(output)) input = unpack_uint32_list( hb('\n f7 ce 0b 65 3d 2d 72 a4 10 8c f5 ab e9 12 ff dd\n 77 76 16 db bb 27 a7 0e 82 04 f3 ae 2d 0f 6f ad\n 89 f6 8f 48 11 d1 e8 7b cc 3b d7 40 0a 9f fd 29\n 09 4f 01 84 63 95 74 f3 9a e5 a1 31 52 17 bc d7\n\n 89 49 91 44 72 13 bb 22 6c 25 b5 4d a8 63 70 fb\n cd 98 43 80 37 46 66 bb 8f fc b5 bf 40 c2 54 b0\n 67 d2 7c 51 ce 4a d5 fe d8 29 c9 0b 50 5a 57 1b\n 7f 4d 1c ad 6a 52 3c da 77 0e 67 bc ea af 7e 89\n ' ), 32) output = unpack_uint32_list( hb('\n a4 1f 85 9c 66 08 cc 99 3b 81 ca cb 02 0c ef 05\n 04 4b 21 81 a2 fd 33 7d fd 7b 1c 63 96 68 2f 29\n b4 39 31 68 e3 c9 e6 bc fe 6b c5 b7 a0 6d 96 ba\n e4 24 cc 10 2c 91 74 5c 24 ad 67 3d c7 61 8f 81\n\n 20 ed c9 75 32 38 81 a8 05 40 f6 4c 16 2d cd 3c\n 21 07 7c fe 5f 8d 5f e2 b1 a4 16 8f 95 36 78 b7\n 7d 3b 3d 80 3b 60 e4 ab 92 09 96 e5 9b 4d 53 b6\n 5d 2a 22 58 77 d5 ed f5 84 2c b9 f1 4e ef e4 25\n ' ), 32) r = 2 input = unpack_uint32_list(seed_bytes('bmix with r=2', 128 * r)) output = unpack_uint32_list( hb('\n ba240854954f4585f3d0573321f10beee96f12acdc1feb498131e40512934fd7\n 43e8139c17d0743c89d09ac8c3582c273c60ab85db63e410d049a9e17a42c6a1\n\n 6c7831b11bf370266afdaff997ae1286920dea1dedf0f4a1795ba710ba9017f1\n a374400766f13ebd8969362de2d153965e9941bdde0768fa5b53e8522f116ce0\n\n d14774afb88f46cd919cba4bc64af7fca0ecb8732d1fc2191e0d7d1b6475cb2e\n e3db789ee478d056c4eb6c6e28b99043602dbb8dfb60c6e048bf90719da8d57d\n\n 3c42250e40ab79a1ada6aae9299b9790f767f54f388d024a1465b30cbbe9eb89\n 002d4f5c215c4259fac4d083bac5fb0b47463747d568f40bb7fa87c42f0a1dc1\n ' ), 32 * r) check_bmix(r, input, output) r = 3 input = unpack_uint32_list(seed_bytes('bmix with r=3', 128 * r)) output = unpack_uint32_list( hb('\n 11ddd8cf60c61f59a6e5b128239bdc77b464101312c88bd1ccf6be6e75461b29\n 7370d4770c904d0b09c402573cf409bf2db47b91ba87d5a3de469df8fb7a003c\n\n 95a66af96dbdd88beddc8df51a2f72a6f588d67e7926e9c2b676c875da13161e\n b6262adac39e6b3003e9a6fbc8c1a6ecf1e227c03bc0af3e5f8736c339b14f84\n\n c7ae5b89f5e16d0faf8983551165f4bb712d97e4f81426e6b78eb63892d3ff54\n 80bf406c98e479496d0f76d23d728e67d2a3d2cdbc4a932be6db36dc37c60209\n\n a5ca76ca2d2979f995f73fe8182eefa1ce0ba0d4fc27d5b827cb8e67edd6552f\n 00a5b3ab6b371bd985a158e728011314eb77f32ade619b3162d7b5078a19886c\n\n 06f12bc8ae8afa46489e5b0239954d5216967c928982984101e4a88bae1f60ae\n 3f8a456e169a8a1c7450e7955b8a13a202382ae19d41ce8ef8b6a15eeef569a7\n\n 20f54c48e44cb5543dda032c1a50d5ddf2919030624978704eb8db0290052a1f\n 5d88989b0ef931b6befcc09e9d5162320e71e80b89862de7e2f0b6c67229b93f\n ' ), 32 * r) check_bmix(r, input, output)
class Pbkdf2Test(TestCase): descriptionPrefix = 'passlib.crypto.digest.pbkdf2_hmac() <backends: %s>' % ( ', ').join(PBKDF2_BACKENDS) pbkdf2_test_vectors = [ (hb('cdedb5281bb2f801565a1122b2563515'), 'password', 'ATHENA.MIT.EDUraeburn', 1, 16), (hb('01dbee7f4a9e243e988b62c73cda935d'), 'password', 'ATHENA.MIT.EDUraeburn', 2, 16), (hb('01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86' ), 'password', 'ATHENA.MIT.EDUraeburn', 2, 32), (hb('5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13' ), 'password', 'ATHENA.MIT.EDUraeburn', 1200, 32), (hb('d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee' ), 'password', '\x124VxxV4\x12', 5, 32), (hb('139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1' ), 'X' * 64, 'pass phrase equals block size', 1200, 32), (hb('9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a' ), 'X' * 65, 'pass phrase exceeds block size', 1200, 32), (hb('0c60c80f961f0e71f3a9b524af6012062fe037a6'), 'password', 'salt', 1, 20), (hb('ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'), 'password', 'salt', 2, 20), (hb('4b007901b765489abead49d926f721d065a429c1'), 'password', 'salt', 4096, 20), (hb('3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038'), 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25), (hb('56fa6aa75548099dcc37d7f03425e0c3'), 'pass\x00word', 'sa\x00lt', 4096, 16), (hb('887CFF169EA8335235D8004242AA7D6187A41E3187DF0CE14E256D85ED97A97357AAA8FF0A3871AB9EEFF458392F462F495487387F685B7472FC6C29E293F0A0' ), 'hello', hb('9290F727ED06C38BA4549EF7DE25CF5642659211B7FC076F2D28FEFD71784BB8D8F6FB244A8CC5C06240631B97008565A120764C0EE9C2CB0073994D79080136' ), 10000, 64, 'sha512'), (hb('55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783' ), 'passwd', 'salt', 1, 64, 'sha256'), (hb('4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d' ), 'Password', 'NaCl', 80000, 64, 'sha256'), (hb('120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b' ), 'password', 'salt', 1, 32, 'sha256'), (hb('ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43' ), 'password', 'salt', 2, 32, 'sha256'), (hb('c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a' ), 'password', 'salt', 4096, 32, 'sha256'), (hb('348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9' ), 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 40, 'sha256'), (hb('9e83f279c040f2a11aa4a02b24c418f2d3cb39560c9627fa4f47e3bcc2897c3d' ), '', 'salt', 1024, 32, 'sha256'), (hb('ea5808411eb0c7e830deab55096cee582761e22a9bc034e3ece925225b07bf46' ), 'password', '', 1024, 32, 'sha256'), (hb('89b69d0516f829893c696226650a8687'), 'pass\x00word', 'sa\x00lt', 4096, 16, 'sha256'), (hb('867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252' ), 'password', 'salt', 1, 32, 'sha512'), (hb('e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53c' ), 'password', 'salt', 2, 32, 'sha512'), (hb('d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5' ), 'password', 'salt', 4096, 32, 'sha512'), (hb('6e23f27638084b0f7ea1734e0d9841f55dd29ea60a834466f3396bac801fac1eeb63802f03a0b4acd7603e3699c8b74437be83ff01ad7f55dac1ef60f4d56480c35ee68fd52c6936' ), 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 1, 72, 'sha512'), (hb('0c60c80f961f0e71f3a9b524af6012062fe037a6'), 'password', 'salt', 1, 20, 'sha1'), (hb('e248fb6b13365146f8ac6307cc222812'), 'secret', 'salt', 10, 16, 'sha1'), (hb('e248fb6b13365146f8ac6307cc2228127872da6d'), 'secret', 'salt', 10, None, 'sha1'), (hb('b1d5485772e6f76d5ebdc11b38d3eff0a5b2bd50dc11f937e86ecacd0cd40d1b9113e0734e3b76a3' ), 'secret', 'salt', 62, 40, 'md5'), (hb('ea014cc01f78d3883cac364bb5d054e2be238fb0b6081795a9d84512126e3129062104d2183464c4' ), 'secret', 'salt', 62, 40, 'md4') ] def test_known(self): for row in self.pbkdf2_test_vectors: correct, secret, salt, rounds, keylen = row[:5] digest = row[5] if len(row) == 6 else 'sha1' result = pbkdf2_hmac(digest, secret, salt, rounds, keylen) self.assertEqual(result, correct) def test_backends(self): from otp.ai.passlib.crypto.digest import PBKDF2_BACKENDS try: import fastpbkdf2 has_fastpbkdf2 = True except ImportError: has_fastpbkdf2 = False else: self.assertEqual('fastpbkdf2' in PBKDF2_BACKENDS, has_fastpbkdf2) try: from hashlib import pbkdf2_hmac has_hashlib_ssl = pbkdf2_hmac.__module__ != 'hashlib' except ImportError: has_hashlib_ssl = False self.assertEqual('hashlib-ssl' in PBKDF2_BACKENDS, has_hashlib_ssl) from otp.ai.passlib.utils.compat import PY3 if PY3: self.assertIn('builtin-from-bytes', PBKDF2_BACKENDS) else: self.assertIn('builtin-unpack', PBKDF2_BACKENDS) def test_border(self): def helper(secret='password', salt='salt', rounds=1, keylen=None, digest='sha1'): return pbkdf2_hmac(digest, secret, salt, rounds, keylen) helper() self.assertRaises(ValueError, helper, rounds=-1) self.assertRaises(ValueError, helper, rounds=0) self.assertRaises(TypeError, helper, rounds='x') helper(keylen=1) self.assertRaises(ValueError, helper, keylen=-1) self.assertRaises(ValueError, helper, keylen=0) self.assertRaises(OverflowError, helper, keylen=20 * 4294967295L + 1) self.assertRaises(TypeError, helper, keylen='x') self.assertRaises(TypeError, helper, salt=5) self.assertRaises(TypeError, helper, secret=5) self.assertRaises(ValueError, helper, digest='foo') self.assertRaises(TypeError, helper, digest=5) return def test_default_keylen(self): def helper(secret='password', salt='salt', rounds=1, keylen=None, digest='sha1'): return pbkdf2_hmac(digest, secret, salt, rounds, keylen) self.assertEqual(len(helper(digest='sha1')), 20) self.assertEqual(len(helper(digest='sha256')), 32) return
class Pbkdf2_Test(TestCase): descriptionPrefix = 'passlib.utils.pbkdf2.pbkdf2()' pbkdf2_test_vectors = [ ( hb('cdedb5281bb2f801565a1122b2563515'), 'password', 'ATHENA.MIT.EDUraeburn', 1, 16), ( hb('01dbee7f4a9e243e988b62c73cda935d'), 'password', 'ATHENA.MIT.EDUraeburn', 2, 16), ( hb('01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86'), 'password', 'ATHENA.MIT.EDUraeburn', 2, 32), ( hb('5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13'), 'password', 'ATHENA.MIT.EDUraeburn', 1200, 32), ( hb('d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee'), 'password', '\x124VxxV4\x12', 5, 32), ( hb('139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1'), 'X' * 64, 'pass phrase equals block size', 1200, 32), ( hb('9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a'), 'X' * 65, 'pass phrase exceeds block size', 1200, 32), ( hb('0c60c80f961f0e71f3a9b524af6012062fe037a6'), 'password', 'salt', 1, 20), ( hb('ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'), 'password', 'salt', 2, 20), ( hb('4b007901b765489abead49d926f721d065a429c1'), 'password', 'salt', 4096, 20), ( hb('3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038'), 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25), ( hb('56fa6aa75548099dcc37d7f03425e0c3'), 'pass\x00word', 'sa\x00lt', 4096, 16), ( hb('887CFF169EA8335235D8004242AA7D6187A41E3187DF0CE14E256D85ED97A97357AAA8FF0A3871AB9EEFF458392F462F495487387F685B7472FC6C29E293F0A0'), 'hello', hb('9290F727ED06C38BA4549EF7DE25CF5642659211B7FC076F2D28FEFD71784BB8D8F6FB244A8CC5C06240631B97008565A120764C0EE9C2CB0073994D79080136'), 10000, 64, 'hmac-sha512'), ( hb('e248fb6b13365146f8ac6307cc222812'), 'secret', 'salt', 10, 16, 'hmac-sha1'), ( hb('e248fb6b13365146f8ac6307cc2228127872da6d'), 'secret', 'salt', 10, None, 'hmac-sha1')] def setUp(self): super(Pbkdf2_Test, self).setUp() warnings.filterwarnings('ignore', '.*passlib.utils.pbkdf2.*deprecated', DeprecationWarning) def test_known(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf2 for row in self.pbkdf2_test_vectors: correct, secret, salt, rounds, keylen = row[:5] prf = row[5] if len(row) == 6 else 'hmac-sha1' result = pbkdf2(secret, salt, rounds, keylen, prf) self.assertEqual(result, correct) def test_border(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf2 def helper(secret='password', salt='salt', rounds=1, keylen=None, prf='hmac-sha1'): return pbkdf2(secret, salt, rounds, keylen, prf) helper() self.assertRaises(ValueError, helper, rounds=-1) self.assertRaises(ValueError, helper, rounds=0) self.assertRaises(TypeError, helper, rounds='x') self.assertRaises(ValueError, helper, keylen=-1) self.assertRaises(ValueError, helper, keylen=0) helper(keylen=1) self.assertRaises(OverflowError, helper, keylen=20 * 4294967295L + 1) self.assertRaises(TypeError, helper, keylen='x') self.assertRaises(TypeError, helper, salt=5) self.assertRaises(TypeError, helper, secret=5) self.assertRaises(ValueError, helper, prf='hmac-foo') self.assertRaises(NotImplementedError, helper, prf='foo') self.assertRaises(TypeError, helper, prf=5) return def test_default_keylen(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf2 def helper(secret='password', salt='salt', rounds=1, keylen=None, prf='hmac-sha1'): return pbkdf2(secret, salt, rounds, keylen, prf) self.assertEqual(len(helper(prf='hmac-sha1')), 20) self.assertEqual(len(helper(prf='hmac-sha256')), 32) return def test_custom_prf(self): from otp.ai.passlib.utils.pbkdf2 import pbkdf2 def prf(key, msg): return hashlib.md5(key + msg + 'fooey').digest() self.assertRaises(NotImplementedError, pbkdf2, 'secret', 'salt', 1000, 20, prf)