diff options
author | Christian Heimes <christian@python.org> | 2016-09-06 18:22:28 (GMT) |
---|---|---|
committer | Christian Heimes <christian@python.org> | 2016-09-06 18:22:28 (GMT) |
commit | 39093e9e6836b98dc67979e4e888e4bc639caa07 (patch) | |
tree | c5be5c5ad31e520580ca9f30d019c47cebb66886 /Lib | |
parent | ac041c0aa721e2672dfb684562b08ad5465b76b1 (diff) | |
download | cpython-39093e9e6836b98dc67979e4e888e4bc639caa07.zip cpython-39093e9e6836b98dc67979e4e888e4bc639caa07.tar.gz cpython-39093e9e6836b98dc67979e4e888e4bc639caa07.tar.bz2 |
Issue #27928: Add scrypt (password-based key derivation function) to hashlib module (requires OpenSSL 1.1.0).
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/hashlib.py | 6 | ||||
-rw-r--r-- | Lib/test/test_hashlib.py | 47 |
2 files changed, 53 insertions, 0 deletions
diff --git a/Lib/hashlib.py b/Lib/hashlib.py index 316cece..348ea14 100644 --- a/Lib/hashlib.py +++ b/Lib/hashlib.py @@ -202,6 +202,12 @@ except ImportError: return dkey[:dklen] +try: + # OpenSSL's scrypt requires OpenSSL 1.1+ + from _hashlib import scrypt +except ImportError: + pass + for __func_name in __always_supported: # try them all, some may not work due to the OpenSSL diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index c9b113e..b010a74 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -7,6 +7,7 @@ # import array +from binascii import unhexlify import hashlib import itertools import os @@ -447,6 +448,12 @@ class KDFTests(unittest.TestCase): (b'pass\0word', b'sa\0lt', 4096, 16), ] + scrypt_test_vectors = [ + (b'', b'', 16, 1, 1, unhexlify('77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906')), + (b'password', b'NaCl', 1024, 8, 16, unhexlify('fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640')), + (b'pleaseletmein', b'SodiumChloride', 16384, 8, 1, unhexlify('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887')), + ] + pbkdf2_results = { "sha1": [ # official test vectors from RFC 6070 @@ -526,5 +533,45 @@ class KDFTests(unittest.TestCase): self._test_pbkdf2_hmac(c_hashlib.pbkdf2_hmac) + @unittest.skipUnless(hasattr(c_hashlib, 'scrypt'), + ' test requires OpenSSL > 1.1') + def test_scrypt(self): + for password, salt, n, r, p, expected in self.scrypt_test_vectors: + result = hashlib.scrypt(password, salt=salt, n=n, r=r, p=p) + self.assertEqual(result, expected) + + # this values should work + hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1) + # password and salt must be bytes-like + with self.assertRaises(TypeError): + hashlib.scrypt('password', salt=b'salt', n=2, r=8, p=1) + with self.assertRaises(TypeError): + hashlib.scrypt(b'password', salt='salt', n=2, r=8, p=1) + # require keyword args + with self.assertRaises(TypeError): + hashlib.scrypt(b'password') + with self.assertRaises(TypeError): + hashlib.scrypt(b'password', b'salt') + with self.assertRaises(TypeError): + hashlib.scrypt(b'password', 2, 8, 1, salt=b'salt') + for n in [-1, 0, 1, None]: + with self.assertRaises((ValueError, OverflowError, TypeError)): + hashlib.scrypt(b'password', salt=b'salt', n=n, r=8, p=1) + for r in [-1, 0, None]: + with self.assertRaises((ValueError, OverflowError, TypeError)): + hashlib.scrypt(b'password', salt=b'salt', n=2, r=r, p=1) + for p in [-1, 0, None]: + with self.assertRaises((ValueError, OverflowError, TypeError)): + hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=p) + for maxmem in [-1, None]: + with self.assertRaises((ValueError, OverflowError, TypeError)): + hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1, + maxmem=maxmem) + for dklen in [-1, None]: + with self.assertRaises((ValueError, OverflowError, TypeError)): + hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1, + dklen=dklen) + + if __name__ == "__main__": unittest.main() |