parent
932274921c
commit
211f637569
@ -1,115 +0,0 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) Django Software Foundation and individual contributors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of Django nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import hmac
|
||||
import struct
|
||||
import base64
|
||||
import hashlib
|
||||
import binascii
|
||||
import operator
|
||||
|
||||
from functools import reduce
|
||||
|
||||
|
||||
def _bin_to_long(x):
|
||||
"""
|
||||
Convert a binary string into a long integer
|
||||
|
||||
This is a clever optimization for fast xor vector math
|
||||
"""
|
||||
return int(binascii.hexlify(x), 16)
|
||||
|
||||
|
||||
def _long_to_bin(x, hex_format_string):
|
||||
"""
|
||||
Convert a long integer into a binary string.
|
||||
hex_format_string is like "%020x" for padding 10 characters.
|
||||
"""
|
||||
return binascii.unhexlify((hex_format_string % x).encode('ascii'))
|
||||
|
||||
|
||||
def _fast_hmac(key, msg, digest):
|
||||
"""
|
||||
A trimmed down version of Python's HMAC implementation.
|
||||
|
||||
This function operates on bytes.
|
||||
"""
|
||||
dig1, dig2 = digest(), digest()
|
||||
if len(key) > dig1.block_size:
|
||||
key = digest(key).digest()
|
||||
key += b'\x00' * (dig1.block_size - len(key))
|
||||
dig1.update(key.translate(hmac.trans_36))
|
||||
dig1.update(msg)
|
||||
dig2.update(key.translate(hmac.trans_5C))
|
||||
dig2.update(dig1.digest())
|
||||
return dig2
|
||||
|
||||
|
||||
def _pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
||||
"""
|
||||
Implements PBKDF2 as defined in RFC 2898, section 5.2
|
||||
|
||||
HMAC+SHA256 is used as the default pseudo random function.
|
||||
|
||||
Right now 10,000 iterations is the recommended default which takes
|
||||
100ms on a 2.2Ghz Core 2 Duo. This is probably the bare minimum
|
||||
for security given 1000 iterations was recommended in 2001. This
|
||||
code is very well optimized for CPython and is only four times
|
||||
slower than openssl's implementation.
|
||||
"""
|
||||
|
||||
assert iterations > 0
|
||||
if not digest:
|
||||
digest = hashlib.sha1
|
||||
password = b'' + password
|
||||
salt = b'' + salt
|
||||
hlen = digest().digest_size
|
||||
if not dklen:
|
||||
dklen = hlen
|
||||
if dklen > (2 ** 32 - 1) * hlen:
|
||||
raise OverflowError('dklen too big')
|
||||
l = -(-dklen // hlen)
|
||||
r = dklen - (l - 1) * hlen
|
||||
|
||||
hex_format_string = "%%0%ix" % (hlen * 2)
|
||||
|
||||
def F(i):
|
||||
def U():
|
||||
u = salt + struct.pack(b'>I', i)
|
||||
for j in range(int(iterations)):
|
||||
u = _fast_hmac(password, u, digest).digest()
|
||||
yield _bin_to_long(u)
|
||||
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
|
||||
|
||||
T = [F(x) for x in range(1, l + 1)]
|
||||
return b''.join(T[:-1]) + T[-1][:r]
|
||||
|
||||
pbkdf2 = lambda text, salt, iterations, dklen: base64.b16encode(
|
||||
_pbkdf2(text.encode('utf-8'), salt, iterations, dklen)).lower()
|
Loading…
Reference in new issue