2013-07-01 20:22:27 +08:00
|
|
|
import hashlib
|
|
|
|
import unittest
|
2011-12-23 11:53:56 +08:00
|
|
|
|
2021-01-14 05:33:42 +08:00
|
|
|
from django.test import SimpleTestCase
|
2020-01-08 23:27:26 +08:00
|
|
|
from django.utils.crypto import (
|
2021-01-14 05:33:42 +08:00
|
|
|
InvalidAlgorithm,
|
|
|
|
constant_time_compare,
|
|
|
|
pbkdf2,
|
|
|
|
salted_hmac,
|
2020-01-08 23:27:26 +08:00
|
|
|
)
|
2012-08-21 04:45:13 +08:00
|
|
|
|
|
|
|
|
2020-01-08 23:27:26 +08:00
|
|
|
class TestUtilsCryptoMisc(SimpleTestCase):
|
2012-08-21 04:45:13 +08:00
|
|
|
def test_constant_time_compare(self):
|
|
|
|
# It's hard to test for constant time, just test the result.
|
|
|
|
self.assertTrue(constant_time_compare(b"spam", b"spam"))
|
|
|
|
self.assertFalse(constant_time_compare(b"spam", b"eggs"))
|
2012-08-21 14:44:16 +08:00
|
|
|
self.assertTrue(constant_time_compare("spam", "spam"))
|
|
|
|
self.assertFalse(constant_time_compare("spam", "eggs"))
|
2011-12-23 11:53:56 +08:00
|
|
|
|
2020-01-08 23:23:08 +08:00
|
|
|
def test_salted_hmac(self):
|
|
|
|
tests = [
|
|
|
|
((b"salt", b"value"), {}, "b51a2e619c43b1ca4f91d15c57455521d71d61eb"),
|
|
|
|
(("salt", "value"), {}, "b51a2e619c43b1ca4f91d15c57455521d71d61eb"),
|
|
|
|
(
|
|
|
|
("salt", "value"),
|
|
|
|
{"secret": "abcdefg"},
|
|
|
|
"8bbee04ccddfa24772d1423a0ba43bd0c0e24b76",
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("salt", "value"),
|
|
|
|
{"secret": "x" * hashlib.sha1().block_size},
|
|
|
|
"bd3749347b412b1b0a9ea65220e55767ac8e96b0",
|
|
|
|
),
|
2020-01-08 23:27:26 +08:00
|
|
|
(
|
|
|
|
("salt", "value"),
|
|
|
|
{"algorithm": "sha256"},
|
|
|
|
"ee0bf789e4e009371a5372c90f73fcf17695a8439c9108b0480f14e347b3f9ec",
|
|
|
|
),
|
|
|
|
(
|
|
|
|
("salt", "value"),
|
|
|
|
{
|
|
|
|
"algorithm": "blake2b",
|
|
|
|
"secret": "x" * hashlib.blake2b().block_size,
|
|
|
|
},
|
|
|
|
"fc6b9800a584d40732a07fa33fb69c35211269441823bca431a143853c32f"
|
|
|
|
"e836cf19ab881689528ede647dac412170cd5d3407b44c6d0f44630690c54"
|
|
|
|
"ad3d58",
|
|
|
|
),
|
2020-01-08 23:23:08 +08:00
|
|
|
]
|
|
|
|
for args, kwargs, digest in tests:
|
|
|
|
with self.subTest(args=args, kwargs=kwargs):
|
|
|
|
self.assertEqual(salted_hmac(*args, **kwargs).hexdigest(), digest)
|
|
|
|
|
2020-01-08 23:27:26 +08:00
|
|
|
def test_invalid_algorithm(self):
|
|
|
|
msg = "'whatever' is not an algorithm accepted by the hashlib module."
|
|
|
|
with self.assertRaisesMessage(InvalidAlgorithm, msg):
|
|
|
|
salted_hmac("salt", "value", algorithm="whatever")
|
|
|
|
|
2011-12-23 11:53:56 +08:00
|
|
|
|
|
|
|
class TestUtilsCryptoPBKDF2(unittest.TestCase):
|
2021-04-05 07:29:58 +08:00
|
|
|
# https://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-06
|
2011-12-23 11:53:56 +08:00
|
|
|
rfc_vectors = [
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 1,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
|
|
|
"result": "0c60c80f961f0e71f3a9b524af6012062fe037a6",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 2,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
|
|
|
"result": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 4096,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
|
|
|
"result": "4b007901b765489abead49d926f721d065a429c1",
|
|
|
|
},
|
|
|
|
# # this takes way too long :(
|
|
|
|
# {
|
|
|
|
# "args": {
|
|
|
|
# "password": "password",
|
|
|
|
# "salt": "salt",
|
|
|
|
# "iterations": 16777216,
|
|
|
|
# "dklen": 20,
|
|
|
|
# "digest": hashlib.sha1,
|
|
|
|
# },
|
|
|
|
# "result": "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984",
|
|
|
|
# },
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "passwordPASSWORDpassword",
|
|
|
|
"salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt",
|
|
|
|
"iterations": 4096,
|
|
|
|
"dklen": 25,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
|
|
|
"result": "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "pass\0word",
|
|
|
|
"salt": "sa\0lt",
|
|
|
|
"iterations": 4096,
|
|
|
|
"dklen": 16,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
|
|
|
"result": "56fa6aa75548099dcc37d7f03425e0c3",
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
regression_vectors = [
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 1,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha256,
|
|
|
|
},
|
|
|
|
"result": "120fb6cffcf8b32c43e7225256c4f837a86548c9",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 1,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha512,
|
|
|
|
},
|
|
|
|
"result": "867f70cf1ade02cff3752599a3a53dc4af34c7a6",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"args": {
|
|
|
|
"password": "password",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 1000,
|
|
|
|
"dklen": 0,
|
|
|
|
"digest": hashlib.sha512,
|
|
|
|
},
|
|
|
|
"result": (
|
|
|
|
"afe6c5530785b6cc6b1c6453384731bd5ee432ee"
|
|
|
|
"549fd42fb6695779ad8a1c5bf59de69c48f774ef"
|
|
|
|
"c4007d5298f9033c0241d5ab69305e7b64eceeb8d"
|
|
|
|
"834cfec"
|
|
|
|
),
|
|
|
|
},
|
2012-08-05 22:12:10 +08:00
|
|
|
# Check leading zeros are not stripped (#17481)
|
2012-02-02 12:44:17 +08:00
|
|
|
{
|
2012-08-05 22:12:10 +08:00
|
|
|
"args": {
|
|
|
|
"password": b"\xba",
|
|
|
|
"salt": "salt",
|
|
|
|
"iterations": 1,
|
|
|
|
"dklen": 20,
|
|
|
|
"digest": hashlib.sha1,
|
|
|
|
},
|
2012-02-02 12:44:17 +08:00
|
|
|
"result": "0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b",
|
|
|
|
},
|
2011-12-23 11:53:56 +08:00
|
|
|
]
|
|
|
|
|
|
|
|
def test_public_vectors(self):
|
|
|
|
for vector in self.rfc_vectors:
|
|
|
|
result = pbkdf2(**vector["args"])
|
2017-11-23 03:25:32 +08:00
|
|
|
self.assertEqual(result.hex(), vector["result"])
|
2011-12-23 11:53:56 +08:00
|
|
|
|
|
|
|
def test_regression_vectors(self):
|
|
|
|
for vector in self.regression_vectors:
|
|
|
|
result = pbkdf2(**vector["args"])
|
2017-11-23 03:25:32 +08:00
|
|
|
self.assertEqual(result.hex(), vector["result"])
|
2017-09-27 22:36:26 +08:00
|
|
|
|
|
|
|
def test_default_hmac_alg(self):
|
|
|
|
kwargs = {
|
|
|
|
"password": b"password",
|
|
|
|
"salt": b"salt",
|
|
|
|
"iterations": 1,
|
|
|
|
"dklen": 20,
|
|
|
|
}
|
|
|
|
self.assertEqual(
|
|
|
|
pbkdf2(**kwargs),
|
|
|
|
hashlib.pbkdf2_hmac(hash_name=hashlib.sha256().name, **kwargs),
|
|
|
|
)
|