mirror of https://github.com/django/django.git
[py3] Ported django.utils.crypto.
This commit is contained in:
parent
b55e07771f
commit
127b461b11
|
@ -50,7 +50,7 @@ def salted_hmac(key_salt, value, secret=None):
|
||||||
# line is redundant and could be replaced by key = key_salt + secret, since
|
# line is redundant and could be replaced by key = key_salt + secret, since
|
||||||
# the hmac module does the same thing for keys longer than the block size.
|
# the hmac module does the same thing for keys longer than the block size.
|
||||||
# However, we need to ensure that we *always* do this.
|
# However, we need to ensure that we *always* do this.
|
||||||
return hmac.new(key, msg=value, digestmod=hashlib.sha1)
|
return hmac.new(key, msg=smart_bytes(value), digestmod=hashlib.sha1)
|
||||||
|
|
||||||
|
|
||||||
def get_random_string(length=12,
|
def get_random_string(length=12,
|
||||||
|
@ -99,7 +99,7 @@ def _bin_to_long(x):
|
||||||
|
|
||||||
This is a clever optimization for fast xor vector math
|
This is a clever optimization for fast xor vector math
|
||||||
"""
|
"""
|
||||||
return int(x.encode('hex'), 16)
|
return int(binascii.hexlify(x), 16)
|
||||||
|
|
||||||
|
|
||||||
def _long_to_bin(x, hex_format_string):
|
def _long_to_bin(x, hex_format_string):
|
||||||
|
@ -112,13 +112,14 @@ def _long_to_bin(x, hex_format_string):
|
||||||
|
|
||||||
def _fast_hmac(key, msg, digest):
|
def _fast_hmac(key, msg, digest):
|
||||||
"""
|
"""
|
||||||
A trimmed down version of Python's HMAC implementation
|
A trimmed down version of Python's HMAC implementation.
|
||||||
|
|
||||||
|
This function operates on bytes.
|
||||||
"""
|
"""
|
||||||
dig1, dig2 = digest(), digest()
|
dig1, dig2 = digest(), digest()
|
||||||
key = smart_bytes(key)
|
|
||||||
if len(key) > dig1.block_size:
|
if len(key) > dig1.block_size:
|
||||||
key = digest(key).digest()
|
key = digest(key).digest()
|
||||||
key += chr(0) * (dig1.block_size - len(key))
|
key += b'\x00' * (dig1.block_size - len(key))
|
||||||
dig1.update(key.translate(_trans_36))
|
dig1.update(key.translate(_trans_36))
|
||||||
dig1.update(msg)
|
dig1.update(msg)
|
||||||
dig2.update(key.translate(_trans_5c))
|
dig2.update(key.translate(_trans_5c))
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import binascii
|
||||||
import math
|
import math
|
||||||
import timeit
|
import timeit
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -108,15 +110,15 @@ class TestUtilsCryptoPBKDF2(unittest.TestCase):
|
||||||
"c4007d5298f9033c0241d5ab69305e7b64eceeb8d"
|
"c4007d5298f9033c0241d5ab69305e7b64eceeb8d"
|
||||||
"834cfec"),
|
"834cfec"),
|
||||||
},
|
},
|
||||||
# Check leading zeros are not stripped (#17481)
|
# Check leading zeros are not stripped (#17481)
|
||||||
{
|
{
|
||||||
"args": {
|
"args": {
|
||||||
"password": chr(186),
|
"password": b'\xba',
|
||||||
"salt": "salt",
|
"salt": "salt",
|
||||||
"iterations": 1,
|
"iterations": 1,
|
||||||
"dklen": 20,
|
"dklen": 20,
|
||||||
"digest": hashlib.sha1,
|
"digest": hashlib.sha1,
|
||||||
},
|
},
|
||||||
"result": '0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b',
|
"result": '0053d3b91a7f1e54effebd6d68771e8a6e0b2c5b',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -124,12 +126,14 @@ class TestUtilsCryptoPBKDF2(unittest.TestCase):
|
||||||
def test_public_vectors(self):
|
def test_public_vectors(self):
|
||||||
for vector in self.rfc_vectors:
|
for vector in self.rfc_vectors:
|
||||||
result = pbkdf2(**vector['args'])
|
result = pbkdf2(**vector['args'])
|
||||||
self.assertEqual(result.encode('hex'), vector['result'])
|
self.assertEqual(binascii.hexlify(result).decode('ascii'),
|
||||||
|
vector['result'])
|
||||||
|
|
||||||
def test_regression_vectors(self):
|
def test_regression_vectors(self):
|
||||||
for vector in self.regression_vectors:
|
for vector in self.regression_vectors:
|
||||||
result = pbkdf2(**vector['args'])
|
result = pbkdf2(**vector['args'])
|
||||||
self.assertEqual(result.encode('hex'), vector['result'])
|
self.assertEqual(binascii.hexlify(result).decode('ascii'),
|
||||||
|
vector['result'])
|
||||||
|
|
||||||
def test_performance_scalability(self):
|
def test_performance_scalability(self):
|
||||||
"""
|
"""
|
||||||
|
@ -140,11 +144,11 @@ class TestUtilsCryptoPBKDF2(unittest.TestCase):
|
||||||
# to run the test suite and false positives caused by imprecise
|
# to run the test suite and false positives caused by imprecise
|
||||||
# measurement.
|
# measurement.
|
||||||
n1, n2 = 200000, 800000
|
n1, n2 = 200000, 800000
|
||||||
elapsed = lambda f: timeit.Timer(f,
|
elapsed = lambda f: timeit.Timer(f,
|
||||||
'from django.utils.crypto import pbkdf2').timeit(number=1)
|
'from django.utils.crypto import pbkdf2').timeit(number=1)
|
||||||
t1 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n1)
|
t1 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n1)
|
||||||
t2 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n2)
|
t2 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n2)
|
||||||
measured_scale_exponent = math.log(t2 / t1, n2 / n1)
|
measured_scale_exponent = math.log(t2 / t1, n2 / n1)
|
||||||
# This should be less than 1. We allow up to 1.2 so that tests don't
|
# This should be less than 1. We allow up to 1.2 so that tests don't
|
||||||
# fail nondeterministically too often.
|
# fail nondeterministically too often.
|
||||||
self.assertLess(measured_scale_exponent, 1.2)
|
self.assertLess(measured_scale_exponent, 1.2)
|
||||||
|
|
Loading…
Reference in New Issue