summaryrefslogtreecommitdiff
path: root/Lib/test/test_hashlib.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_hashlib.py')
-rw-r--r--Lib/test/test_hashlib.py428
1 files changed, 408 insertions, 20 deletions
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index c9b113e6ef..f748b46190 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
@@ -19,6 +20,7 @@ import unittest
import warnings
from test import support
from test.support import _4G, bigmemtest, import_fresh_module
+from http.client import HTTPException
# Were we compiled --with-pydebug or with #define Py_DEBUG?
COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
@@ -26,6 +28,21 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
+try:
+ import _blake2
+except ImportError:
+ _blake2 = None
+
+requires_blake2 = unittest.skipUnless(_blake2, 'requires _blake2')
+
+try:
+ import _sha3
+except ImportError:
+ _sha3 = None
+
+requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
+
+
def hexstr(s):
assert isinstance(s, bytes), repr(s)
h = "0123456789abcdef"
@@ -35,10 +52,33 @@ def hexstr(s):
return r
+URL = "http://www.pythontest.net/hashlib/{}.txt"
+
+def read_vectors(hash_name):
+ url = URL.format(hash_name)
+ try:
+ testdata = support.open_urlresource(url)
+ except (OSError, HTTPException):
+ raise unittest.SkipTest("Could not retrieve {}".format(url))
+ with testdata:
+ for line in testdata:
+ line = line.strip()
+ if line.startswith('#') or not line:
+ continue
+ parts = line.split(',')
+ parts[0] = bytes.fromhex(parts[0])
+ yield parts
+
+
class HashLibTestCase(unittest.TestCase):
supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
'sha224', 'SHA224', 'sha256', 'SHA256',
- 'sha384', 'SHA384', 'sha512', 'SHA512')
+ 'sha384', 'SHA384', 'sha512', 'SHA512',
+ 'blake2b', 'blake2s',
+ 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
+ 'shake_128', 'shake_256')
+
+ shakes = {'shake_128', 'shake_256'}
# Issue #14693: fallback modules are always compiled under POSIX
_warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG
@@ -56,6 +96,11 @@ class HashLibTestCase(unittest.TestCase):
algorithms = set()
for algorithm in self.supported_hash_names:
algorithms.add(algorithm.lower())
+
+ _blake2 = self._conditional_import_module('_blake2')
+ if _blake2:
+ algorithms.update({'blake2b', 'blake2s'})
+
self.constructors_to_test = {}
for algorithm in algorithms:
self.constructors_to_test[algorithm] = set()
@@ -64,10 +109,10 @@ class HashLibTestCase(unittest.TestCase):
# of hashlib.new given the algorithm name.
for algorithm, constructors in self.constructors_to_test.items():
constructors.add(getattr(hashlib, algorithm))
- def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
+ def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs):
if data is None:
- return hashlib.new(_alg)
- return hashlib.new(_alg, data)
+ return hashlib.new(_alg, **kwargs)
+ return hashlib.new(_alg, data, **kwargs)
constructors.add(_test_algorithm_via_hashlib_new)
_hashlib = self._conditional_import_module('_hashlib')
@@ -99,6 +144,18 @@ class HashLibTestCase(unittest.TestCase):
if _sha512:
add_builtin_constructor('sha384')
add_builtin_constructor('sha512')
+ if _blake2:
+ add_builtin_constructor('blake2s')
+ add_builtin_constructor('blake2b')
+
+ _sha3 = self._conditional_import_module('_sha3')
+ if _sha3:
+ add_builtin_constructor('sha3_224')
+ add_builtin_constructor('sha3_256')
+ add_builtin_constructor('sha3_384')
+ add_builtin_constructor('sha3_512')
+ add_builtin_constructor('shake_128')
+ add_builtin_constructor('shake_256')
super(HashLibTestCase, self).__init__(*args, **kwargs)
@@ -111,7 +168,10 @@ class HashLibTestCase(unittest.TestCase):
a = array.array("b", range(10))
for cons in self.hash_constructors:
c = cons(a)
- c.hexdigest()
+ if c.name in self.shakes:
+ c.hexdigest(16)
+ else:
+ c.hexdigest()
def test_algorithms_guaranteed(self):
self.assertEqual(hashlib.algorithms_guaranteed,
@@ -155,14 +215,21 @@ class HashLibTestCase(unittest.TestCase):
def test_hexdigest(self):
for cons in self.hash_constructors:
h = cons()
- self.assertIsInstance(h.digest(), bytes)
- self.assertEqual(hexstr(h.digest()), h.hexdigest())
+ if h.name in self.shakes:
+ self.assertIsInstance(h.digest(16), bytes)
+ self.assertEqual(hexstr(h.digest(16)), h.hexdigest(16))
+ else:
+ self.assertIsInstance(h.digest(), bytes)
+ self.assertEqual(hexstr(h.digest()), h.hexdigest())
def test_name_attribute(self):
for cons in self.hash_constructors:
h = cons()
self.assertIsInstance(h.name, str)
- self.assertIn(h.name, self.supported_hash_names)
+ if h.name in self.supported_hash_names:
+ self.assertIn(h.name, self.supported_hash_names)
+ else:
+ self.assertNotIn(h.name, self.supported_hash_names)
self.assertEqual(h.name, hashlib.new(h.name).name)
def test_large_update(self):
@@ -177,40 +244,46 @@ class HashLibTestCase(unittest.TestCase):
m1.update(bees)
m1.update(cees)
m1.update(dees)
+ if m1.name in self.shakes:
+ args = (16,)
+ else:
+ args = ()
m2 = cons()
m2.update(aas + bees + cees + dees)
- self.assertEqual(m1.digest(), m2.digest())
+ self.assertEqual(m1.digest(*args), m2.digest(*args))
m3 = cons(aas + bees + cees + dees)
- self.assertEqual(m1.digest(), m3.digest())
+ self.assertEqual(m1.digest(*args), m3.digest(*args))
# verify copy() doesn't touch original
m4 = cons(aas + bees + cees)
- m4_digest = m4.digest()
+ m4_digest = m4.digest(*args)
m4_copy = m4.copy()
m4_copy.update(dees)
- self.assertEqual(m1.digest(), m4_copy.digest())
- self.assertEqual(m4.digest(), m4_digest)
+ self.assertEqual(m1.digest(*args), m4_copy.digest(*args))
+ self.assertEqual(m4.digest(*args), m4_digest)
- def check(self, name, data, hexdigest):
+ def check(self, name, data, hexdigest, shake=False, **kwargs):
+ length = len(hexdigest)//2
hexdigest = hexdigest.lower()
constructors = self.constructors_to_test[name]
# 2 is for hashlib.name(...) and hashlib.new(name, ...)
self.assertGreaterEqual(len(constructors), 2)
for hash_object_constructor in constructors:
- m = hash_object_constructor(data)
- computed = m.hexdigest()
+ m = hash_object_constructor(data, **kwargs)
+ computed = m.hexdigest() if not shake else m.hexdigest(length)
self.assertEqual(
computed, hexdigest,
"Hash algorithm %s constructed using %s returned hexdigest"
" %r for %d byte input data that should have hashed to %r."
% (name, hash_object_constructor,
computed, len(data), hexdigest))
- computed = m.digest()
+ computed = m.digest() if not shake else m.digest(length)
digest = bytes.fromhex(hexdigest)
self.assertEqual(computed, digest)
- self.assertEqual(len(digest), m.digest_size)
+ if not shake:
+ self.assertEqual(len(digest), m.digest_size)
def check_no_unicode(self, algorithm_name):
# Unicode objects are not allowed as input.
@@ -226,13 +299,35 @@ class HashLibTestCase(unittest.TestCase):
self.check_no_unicode('sha384')
self.check_no_unicode('sha512')
- def check_blocksize_name(self, name, block_size=0, digest_size=0):
+ @requires_blake2
+ def test_no_unicode_blake2(self):
+ self.check_no_unicode('blake2b')
+ self.check_no_unicode('blake2s')
+
+ @requires_sha3
+ def test_no_unicode_sha3(self):
+ self.check_no_unicode('sha3_224')
+ self.check_no_unicode('sha3_256')
+ self.check_no_unicode('sha3_384')
+ self.check_no_unicode('sha3_512')
+ self.check_no_unicode('shake_128')
+ self.check_no_unicode('shake_256')
+
+ def check_blocksize_name(self, name, block_size=0, digest_size=0,
+ digest_length=None):
constructors = self.constructors_to_test[name]
for hash_object_constructor in constructors:
m = hash_object_constructor()
self.assertEqual(m.block_size, block_size)
self.assertEqual(m.digest_size, digest_size)
- self.assertEqual(len(m.digest()), digest_size)
+ if digest_length:
+ self.assertEqual(len(m.digest(digest_length)),
+ digest_length)
+ self.assertEqual(len(m.hexdigest(digest_length)),
+ 2*digest_length)
+ else:
+ self.assertEqual(len(m.digest()), digest_size)
+ self.assertEqual(len(m.hexdigest()), 2*digest_size)
self.assertEqual(m.name, name)
# split for sha3_512 / _sha3.sha3 object
self.assertIn(name.split("_")[0], repr(m))
@@ -245,6 +340,38 @@ class HashLibTestCase(unittest.TestCase):
self.check_blocksize_name('sha384', 128, 48)
self.check_blocksize_name('sha512', 128, 64)
+ @requires_sha3
+ def test_blocksize_name_sha3(self):
+ self.check_blocksize_name('sha3_224', 144, 28)
+ self.check_blocksize_name('sha3_256', 136, 32)
+ self.check_blocksize_name('sha3_384', 104, 48)
+ self.check_blocksize_name('sha3_512', 72, 64)
+ self.check_blocksize_name('shake_128', 168, 0, 32)
+ self.check_blocksize_name('shake_256', 136, 0, 64)
+
+ def check_sha3(self, name, capacity, rate, suffix):
+ constructors = self.constructors_to_test[name]
+ for hash_object_constructor in constructors:
+ m = hash_object_constructor()
+ self.assertEqual(capacity + rate, 1600)
+ self.assertEqual(m._capacity_bits, capacity)
+ self.assertEqual(m._rate_bits, rate)
+ self.assertEqual(m._suffix, suffix)
+
+ @requires_sha3
+ def test_extra_sha3(self):
+ self.check_sha3('sha3_224', 448, 1152, b'\x06')
+ self.check_sha3('sha3_256', 512, 1088, b'\x06')
+ self.check_sha3('sha3_384', 768, 832, b'\x06')
+ self.check_sha3('sha3_512', 1024, 576, b'\x06')
+ self.check_sha3('shake_128', 256, 1344, b'\x1f')
+ self.check_sha3('shake_256', 512, 1088, b'\x1f')
+
+ @requires_blake2
+ def test_blocksize_name_blake2(self):
+ self.check_blocksize_name('blake2b', 128, 64)
+ self.check_blocksize_name('blake2s', 64, 32)
+
def test_case_md5_0(self):
self.check('md5', b'', 'd41d8cd98f00b204e9800998ecf8427e')
@@ -373,6 +500,221 @@ class HashLibTestCase(unittest.TestCase):
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"+
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b")
+ def check_blake2(self, constructor, salt_size, person_size, key_size,
+ digest_size, max_offset):
+ self.assertEqual(constructor.SALT_SIZE, salt_size)
+ for i in range(salt_size + 1):
+ constructor(salt=b'a' * i)
+ salt = b'a' * (salt_size + 1)
+ self.assertRaises(ValueError, constructor, salt=salt)
+
+ self.assertEqual(constructor.PERSON_SIZE, person_size)
+ for i in range(person_size+1):
+ constructor(person=b'a' * i)
+ person = b'a' * (person_size + 1)
+ self.assertRaises(ValueError, constructor, person=person)
+
+ self.assertEqual(constructor.MAX_DIGEST_SIZE, digest_size)
+ for i in range(1, digest_size + 1):
+ constructor(digest_size=i)
+ self.assertRaises(ValueError, constructor, digest_size=-1)
+ self.assertRaises(ValueError, constructor, digest_size=0)
+ self.assertRaises(ValueError, constructor, digest_size=digest_size+1)
+
+ self.assertEqual(constructor.MAX_KEY_SIZE, key_size)
+ for i in range(key_size+1):
+ constructor(key=b'a' * i)
+ key = b'a' * (key_size + 1)
+ self.assertRaises(ValueError, constructor, key=key)
+ self.assertEqual(constructor().hexdigest(),
+ constructor(key=b'').hexdigest())
+
+ for i in range(0, 256):
+ constructor(fanout=i)
+ self.assertRaises(ValueError, constructor, fanout=-1)
+ self.assertRaises(ValueError, constructor, fanout=256)
+
+ for i in range(1, 256):
+ constructor(depth=i)
+ self.assertRaises(ValueError, constructor, depth=-1)
+ self.assertRaises(ValueError, constructor, depth=0)
+ self.assertRaises(ValueError, constructor, depth=256)
+
+ for i in range(0, 256):
+ constructor(node_depth=i)
+ self.assertRaises(ValueError, constructor, node_depth=-1)
+ self.assertRaises(ValueError, constructor, node_depth=256)
+
+ for i in range(0, digest_size + 1):
+ constructor(inner_size=i)
+ self.assertRaises(ValueError, constructor, inner_size=-1)
+ self.assertRaises(ValueError, constructor, inner_size=digest_size+1)
+
+ constructor(leaf_size=0)
+ constructor(leaf_size=(1<<32)-1)
+ self.assertRaises(OverflowError, constructor, leaf_size=-1)
+ self.assertRaises(OverflowError, constructor, leaf_size=1<<32)
+
+ constructor(node_offset=0)
+ constructor(node_offset=max_offset)
+ self.assertRaises(OverflowError, constructor, node_offset=-1)
+ self.assertRaises(OverflowError, constructor, node_offset=max_offset+1)
+
+ constructor(
+ string=b'',
+ key=b'',
+ salt=b'',
+ person=b'',
+ digest_size=17,
+ fanout=1,
+ depth=1,
+ leaf_size=256,
+ node_offset=512,
+ node_depth=1,
+ inner_size=7,
+ last_node=True
+ )
+
+ def blake2_rfc7693(self, constructor, md_len, in_len):
+ def selftest_seq(length, seed):
+ mask = (1<<32)-1
+ a = (0xDEAD4BAD * seed) & mask
+ b = 1
+ out = bytearray(length)
+ for i in range(length):
+ t = (a + b) & mask
+ a, b = b, t
+ out[i] = (t >> 24) & 0xFF
+ return out
+ outer = constructor(digest_size=32)
+ for outlen in md_len:
+ for inlen in in_len:
+ indata = selftest_seq(inlen, inlen)
+ key = selftest_seq(outlen, outlen)
+ unkeyed = constructor(indata, digest_size=outlen)
+ outer.update(unkeyed.digest())
+ keyed = constructor(indata, key=key, digest_size=outlen)
+ outer.update(keyed.digest())
+ return outer.hexdigest()
+
+ @requires_blake2
+ def test_blake2b(self):
+ self.check_blake2(hashlib.blake2b, 16, 16, 64, 64, (1<<64)-1)
+ b2b_md_len = [20, 32, 48, 64]
+ b2b_in_len = [0, 3, 128, 129, 255, 1024]
+ self.assertEqual(
+ self.blake2_rfc7693(hashlib.blake2b, b2b_md_len, b2b_in_len),
+ "c23a7800d98123bd10f506c61e29da5603d763b8bbad2e737f5e765a7bccd475")
+
+ @requires_blake2
+ def test_case_blake2b_0(self):
+ self.check('blake2b', b"",
+ "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419"+
+ "d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce")
+
+ @requires_blake2
+ def test_case_blake2b_1(self):
+ self.check('blake2b', b"abc",
+ "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"+
+ "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")
+
+ @requires_blake2
+ def test_blake2b_vectors(self):
+ for msg, key, md in read_vectors('blake2b'):
+ key = bytes.fromhex(key)
+ self.check('blake2b', msg, md, key=key)
+
+ @requires_blake2
+ def test_blake2s(self):
+ self.check_blake2(hashlib.blake2s, 8, 8, 32, 32, (1<<48)-1)
+ b2s_md_len = [16, 20, 28, 32]
+ b2s_in_len = [0, 3, 64, 65, 255, 1024]
+ self.assertEqual(
+ self.blake2_rfc7693(hashlib.blake2s, b2s_md_len, b2s_in_len),
+ "6a411f08ce25adcdfb02aba641451cec53c598b24f4fc787fbdc88797f4c1dfe")
+
+ @requires_blake2
+ def test_case_blake2s_0(self):
+ self.check('blake2s', b"",
+ "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9")
+
+ @requires_blake2
+ def test_case_blake2s_1(self):
+ self.check('blake2s', b"abc",
+ "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982")
+
+ @requires_blake2
+ def test_blake2s_vectors(self):
+ for msg, key, md in read_vectors('blake2s'):
+ key = bytes.fromhex(key)
+ self.check('blake2s', msg, md, key=key)
+
+ @requires_sha3
+ def test_case_sha3_224_0(self):
+ self.check('sha3_224', b"",
+ "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")
+
+ @requires_sha3
+ def test_case_sha3_224_vector(self):
+ for msg, md in read_vectors('sha3_224'):
+ self.check('sha3_224', msg, md)
+
+ @requires_sha3
+ def test_case_sha3_256_0(self):
+ self.check('sha3_256', b"",
+ "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
+
+ @requires_sha3
+ def test_case_sha3_256_vector(self):
+ for msg, md in read_vectors('sha3_256'):
+ self.check('sha3_256', msg, md)
+
+ @requires_sha3
+ def test_case_sha3_384_0(self):
+ self.check('sha3_384', b"",
+ "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a"+
+ "c3713831264adb47fb6bd1e058d5f004")
+
+ @requires_sha3
+ def test_case_sha3_384_vector(self):
+ for msg, md in read_vectors('sha3_384'):
+ self.check('sha3_384', msg, md)
+
+ @requires_sha3
+ def test_case_sha3_512_0(self):
+ self.check('sha3_512', b"",
+ "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6"+
+ "15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")
+
+ @requires_sha3
+ def test_case_sha3_512_vector(self):
+ for msg, md in read_vectors('sha3_512'):
+ self.check('sha3_512', msg, md)
+
+ @requires_sha3
+ def test_case_shake_128_0(self):
+ self.check('shake_128', b"",
+ "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26",
+ True)
+ self.check('shake_128', b"", "7f9c", True)
+
+ @requires_sha3
+ def test_case_shake128_vector(self):
+ for msg, md in read_vectors('shake_128'):
+ self.check('shake_128', msg, md, True)
+
+ @requires_sha3
+ def test_case_shake_256_0(self):
+ self.check('shake_256', b"",
+ "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f",
+ True)
+ self.check('shake_256', b"", "46b9", True)
+
+ @requires_sha3
+ def test_case_shake256_vector(self):
+ for msg, md in read_vectors('shake_256'):
+ self.check('shake_256', msg, md, True)
+
def test_gil(self):
# Check things work fine with an input larger than the size required
# for multithreaded operation (which is hardwired to 2048).
@@ -447,6 +789,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 +874,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()