@@ -1184,12 +1184,6 @@ class KDFTests(unittest.TestCase):
1184
1184
(b'pass\0 word' , b'sa\0 lt' , 4096 , 16 ),
1185
1185
]
1186
1186
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
-
1193
1187
pbkdf2_results = {
1194
1188
"sha1" : [
1195
1189
# official test vectors from RFC 6070
@@ -1281,46 +1275,6 @@ def _test_pbkdf2_hmac(self, pbkdf2, supported):
1281
1275
def test_pbkdf2_hmac_c (self ):
1282
1276
self ._test_pbkdf2_hmac (openssl_hashlib .pbkdf2_hmac , openssl_md_meth_names )
1283
1277
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
-
1324
1278
def test_normalized_name (self ):
1325
1279
self .assertNotIn ("blake2b512" , hashlib .algorithms_available )
1326
1280
self .assertNotIn ("sha3-512" , hashlib .algorithms_available )
@@ -1362,5 +1316,76 @@ def readable(self):
1362
1316
hashlib .file_digest (NonBlocking (), hashlib .sha256 )
1363
1317
1364
1318
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
+
1365
1390
if __name__ == "__main__" :
1366
1391
unittest .main ()
0 commit comments