summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2016-09-06 18:22:28 (GMT)
committerChristian Heimes <christian@python.org>2016-09-06 18:22:28 (GMT)
commit39093e9e6836b98dc67979e4e888e4bc639caa07 (patch)
treec5be5c5ad31e520580ca9f30d019c47cebb66886 /Lib
parentac041c0aa721e2672dfb684562b08ad5465b76b1 (diff)
downloadcpython-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.py6
-rw-r--r--Lib/test/test_hashlib.py47
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()