Created
February 5, 2014 13:09
-
-
Save denismakogon/8823279 to your computer and use it in GitHub Desktop.
pbkdf2 implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hmac | |
import struct | |
import hashlib | |
import binascii | |
def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'): | |
""" | |
Similar to smart_bytes, except that lazy instances are resolved to | |
strings, rather than kept as lazy objects. | |
If strings_only is True, don't convert (some) non-string-like objects. | |
""" | |
return s.decode('utf-8', errors).encode(encoding, errors) | |
def pbkdf2(password, salt, iterations, dklen=0, digest=None): | |
assert iterations > 0 | |
if not digest: | |
digest = hashlib.sha256 | |
password = force_bytes(password) | |
salt = force_bytes(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) | |
inner, outer = digest(), digest() | |
if len(password) > inner.block_size: | |
password = digest(password).digest() | |
password += b'\x00' * (inner.block_size - len(password)) | |
inner.update(password.translate(hmac.trans_36)) | |
outer.update(password.translate(hmac.trans_5C)) | |
def F(i): | |
u = salt + struct.pack(b'>I', i) | |
result = 0 | |
for j in xrange(int(iterations)): | |
dig1, dig2 = inner.copy(), outer.copy() | |
dig1.update(u) | |
dig2.update(dig1.digest()) | |
u = dig2.hexdigest() | |
result ^= _bin_to_long(u) | |
return _long_to_bin(result, hex_format_string) | |
T = [F(x) for x in range(1, l)] | |
return b''.join(T) + F(l)[:r] | |
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')) | |
if __name__ == "__main__": | |
path = "/home/dmakogon/Documents/Trove/Trove-confs/templates/mysql/heat.template" | |
ololo = pbkdf2('lol', 'lol', 5, dklen=32) | |
print str(ololo.decode('ascii')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment