@@ -1184,12 +1184,6 @@ class KDFTests(unittest.TestCase):
11841184 (b'pass\0 word' , b'sa\0 lt' , 4096 , 16 ),
11851185 ]
11861186
1187- scrypt_test_vectors = [
1188- (b'' , b'' , 16 , 1 , 1 , unhexlify ('77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906' )),
1189- (b'password' , b'NaCl' , 1024 , 8 , 16 , unhexlify ('fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640' )),
1190- (b'pleaseletmein' , b'SodiumChloride' , 16384 , 8 , 1 , unhexlify ('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887' )),
1191- ]
1192-
11931187 pbkdf2_results = {
11941188 "sha1" : [
11951189 # official test vectors from RFC 6070
@@ -1281,46 +1275,6 @@ def _test_pbkdf2_hmac(self, pbkdf2, supported):
12811275 def test_pbkdf2_hmac_c (self ):
12821276 self ._test_pbkdf2_hmac (openssl_hashlib .pbkdf2_hmac , openssl_md_meth_names )
12831277
1284- @unittest .skipUnless (hasattr (hashlib , 'scrypt' ),
1285- ' test requires OpenSSL > 1.1' )
1286- @unittest .skipIf (get_fips_mode (), reason = "scrypt is blocked in FIPS mode" )
1287- def test_scrypt (self ):
1288- for password , salt , n , r , p , expected in self .scrypt_test_vectors :
1289- result = hashlib .scrypt (password , salt = salt , n = n , r = r , p = p )
1290- self .assertEqual (result , expected )
1291-
1292- # this values should work
1293- hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 )
1294- # password and salt must be bytes-like
1295- with self .assertRaises (TypeError ):
1296- hashlib .scrypt ('password' , salt = b'salt' , n = 2 , r = 8 , p = 1 )
1297- with self .assertRaises (TypeError ):
1298- hashlib .scrypt (b'password' , salt = 'salt' , n = 2 , r = 8 , p = 1 )
1299- # require keyword args
1300- with self .assertRaises (TypeError ):
1301- hashlib .scrypt (b'password' )
1302- with self .assertRaises (TypeError ):
1303- hashlib .scrypt (b'password' , b'salt' )
1304- with self .assertRaises (TypeError ):
1305- hashlib .scrypt (b'password' , 2 , 8 , 1 , salt = b'salt' )
1306- for n in [- 1 , 0 , 1 , None ]:
1307- with self .assertRaises ((ValueError , OverflowError , TypeError )):
1308- hashlib .scrypt (b'password' , salt = b'salt' , n = n , r = 8 , p = 1 )
1309- for r in [- 1 , 0 , None ]:
1310- with self .assertRaises ((ValueError , OverflowError , TypeError )):
1311- hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = r , p = 1 )
1312- for p in [- 1 , 0 , None ]:
1313- with self .assertRaises ((ValueError , OverflowError , TypeError )):
1314- hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = p )
1315- for maxmem in [- 1 , None ]:
1316- with self .assertRaises ((ValueError , OverflowError , TypeError )):
1317- hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 ,
1318- maxmem = maxmem )
1319- for dklen in [- 1 , None ]:
1320- with self .assertRaises ((ValueError , OverflowError , TypeError )):
1321- hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 ,
1322- dklen = dklen )
1323-
13241278 def test_normalized_name (self ):
13251279 self .assertNotIn ("blake2b512" , hashlib .algorithms_available )
13261280 self .assertNotIn ("sha3-512" , hashlib .algorithms_available )
@@ -1362,5 +1316,76 @@ def readable(self):
13621316 hashlib .file_digest (NonBlocking (), hashlib .sha256 )
13631317
13641318
1319+ @unittest .skipUnless (hasattr (hashlib , 'scrypt' ), 'requires OpenSSL 1.1+' )
1320+ @unittest .skipIf (get_fips_mode (), reason = "scrypt is blocked in FIPS mode" )
1321+ class TestScrypt (unittest .TestCase ):
1322+
1323+ scrypt_test_vectors = [
1324+ (b'' , b'' , 16 , 1 , 1 , unhexlify ('77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906' )),
1325+ (b'password' , b'NaCl' , 1024 , 8 , 16 , unhexlify ('fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640' )),
1326+ (b'pleaseletmein' , b'SodiumChloride' , 16384 , 8 , 1 , unhexlify ('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887' )),
1327+ ]
1328+
1329+ def test_scrypt (self ):
1330+ for password , salt , n , r , p , expected in self .scrypt_test_vectors :
1331+ result = hashlib .scrypt (password , salt = salt , n = n , r = r , p = p )
1332+ self .assertEqual (result , expected )
1333+
1334+ # these parameters must be valid
1335+ hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 )
1336+ hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 , maxmem = 0 )
1337+ hashlib .scrypt (b'password' , salt = b'salt' , n = 2 , r = 8 , p = 1 , dklen = 1 )
1338+
1339+ def test_scrypt_types (self ):
1340+ # password and salt must be bytes-like
1341+ with self .assertRaises (TypeError ):
1342+ hashlib .scrypt ('password' , salt = b'salt' , n = 2 , r = 8 , p = 1 )
1343+ with self .assertRaises (TypeError ):
1344+ hashlib .scrypt (b'password' , salt = 'salt' , n = 2 , r = 8 , p = 1 )
1345+ # require keyword args
1346+ with self .assertRaises (TypeError ):
1347+ hashlib .scrypt (b'password' )
1348+ with self .assertRaises (TypeError ):
1349+ hashlib .scrypt (b'password' , b'salt' )
1350+ with self .assertRaises (TypeError ):
1351+ hashlib .scrypt (b'password' , 2 , 8 , 1 , salt = b'salt' )
1352+
1353+ def test_scrypt_validate (self ):
1354+ def scrypt (password = b"password" , / , ** kwargs ):
1355+ # overwrite well-defined parameters with bad ones
1356+ kwargs = dict (salt = b'salt' , n = 2 , r = 8 , p = 1 ) | kwargs
1357+ return hashlib .scrypt (password , ** kwargs )
1358+
1359+ for param_name in ('n' , 'r' , 'p' , 'maxmem' , 'dklen' ):
1360+ param = {param_name : None }
1361+ with self .subTest (** param ):
1362+ self .assertRaises (TypeError , scrypt , ** param )
1363+
1364+ self .assertRaises (ValueError , scrypt , n = 0 )
1365+ self .assertRaises (ValueError , scrypt , n = - 1 )
1366+ self .assertRaises (ValueError , scrypt , n = 1 )
1367+
1368+ self .assertRaises (ValueError , scrypt , r = 0 )
1369+ self .assertRaises (ValueError , scrypt , r = - 1 )
1370+
1371+ self .assertRaises (ValueError , scrypt , p = - 1 )
1372+ self .assertRaises (ValueError , scrypt , p = 0 )
1373+
1374+ self .assertRaises (ValueError , scrypt , maxmem = - 1 )
1375+ # OpenSSL hard limit for 'maxmem' is an 'uint64_t' but for now,
1376+ # we do not use the 'uint64' Clinic converter but the 'long' one.
1377+ self .assertRaises (OverflowError , scrypt , maxmem = (1 << 64 ))
1378+ # Historically, Python allowed 'maxmem' to be at most INT_MAX,
1379+ # which is at most 2**32-1 (on Windows, sizeof(long) == 4, so
1380+ # an OverflowError will be raised instead of a ValueError).
1381+ numeric_exc_types = (OverflowError , ValueError )
1382+ self .assertRaises (numeric_exc_types , scrypt , maxmem = (1 << 32 ))
1383+
1384+ self .assertRaises (ValueError , scrypt , dklen = - 1 )
1385+ self .assertRaises (ValueError , scrypt , dklen = 0 )
1386+ MAX_DKLEN = ((1 << 32 ) - 1 ) * 32 # see RFC 7914
1387+ self .assertRaises (numeric_exc_types , scrypt , dklen = MAX_DKLEN + 1 )
1388+
1389+
13651390if __name__ == "__main__" :
13661391 unittest .main ()
0 commit comments