aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wqflask/wqflask/pbkdf2.py144
1 files changed, 12 insertions, 132 deletions
diff --git a/wqflask/wqflask/pbkdf2.py b/wqflask/wqflask/pbkdf2.py
index 917b9d31..aea5b06c 100644
--- a/wqflask/wqflask/pbkdf2.py
+++ b/wqflask/wqflask/pbkdf2.py
@@ -1,140 +1,20 @@
-# -*- coding: utf-8 -*-
-"""
- pbkdf2
- ~~~~~~
-
- This module implements pbkdf2 for Python. It also has some basic
- tests that ensure that it works. The implementation is straightforward
- and uses stdlib only stuff and can be easily be copy/pasted into
- your favourite application.
-
- Use this as replacement for bcrypt that does not need a c implementation
- of a modified blowfish crypto algo.
-
- Example usage:
-
- >>> pbkdf2_hex('what i want to hash', 'the random salt')
- 'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9'
-
- How to use this:
-
- 1. Use a constant time string compare function to compare the stored hash
- with the one you're generating::
-
- def safe_str_cmp(a, b):
- if len(a) != len(b):
- return False
- rv = 0
- for x, y in izip(a, b):
- rv |= ord(x) ^ ord(y)
- return rv == 0
-
- 2. Use `os.urandom` to generate a proper salt of at least 8 byte.
- Use a unique salt per hashed password.
-
- 3. Store ``algorithm$salt:costfactor$hash`` in the database so that
- you can upgrade later easily to a different algorithm if you need
- one. For instance ``PBKDF2-256$thesalt:10000$deadbeef...``.
-
-
- :copyright: (c) Copyright 2011 by Armin Ronacher.
- :license: BSD, see LICENSE for more details.
-"""
-import hmac
import hashlib
-from struct import Struct
-from operator import xor
-from itertools import starmap
+from werkzeug.security import safe_str_cmp as ssc
-_pack_int = Struct('>I').pack
-
-def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
- """Like :func:`pbkdf2_bin` but returns a hex encoded string."""
- return pbkdf2_bin(data, salt, iterations, keylen, hashfunc).encode('hex')
-
-
-def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
- """Returns a binary digest for the PBKDF2 hash algorithm of `data`
- with the given `salt`. It iterates `iterations` time and produces a
- key of `keylen` bytes. By default SHA-1 is used as hash function,
- a different hashlib `hashfunc` can be provided.
+# Replace this because it just wraps around Python3's internal
+# functions. Added this during migration.
+def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc="sha1"):
+ """Wrapper function of python's hashlib.pbkdf2_hmac.
"""
- hashfunc = hashfunc or hashlib.sha1
- mac = hmac.new(data, None, hashfunc)
- def _pseudorandom(x, mac=mac):
- h = mac.copy()
- h.update(x)
- return list(map(ord, h.digest()))
- buf = []
- for block in range(1, -(-keylen // mac.digest_size) + 1):
- rv = u = _pseudorandom(salt + _pack_int(block))
- for i in range(iterations - 1):
- u = _pseudorandom(''.join(map(chr, u)))
- rv = list(starmap(xor, zip(rv, u)))
- buf.extend(rv)
- return ''.join(map(chr, buf))[:keylen]
+ dk = hashlib.pbkdf2_hmac(hashfunc,
+ bytes(data, "utf-8"), # password
+ bytes(salt, "utf-8"), # salt
+ iterations,
+ keylen)
+ return dk.hex()
def safe_str_cmp(a, b):
- if len(a) != len(b):
- return False
- rv = 0
- for x, y in zip(a, b):
- rv |= ord(x) ^ ord(y)
- return rv == 0
-
-
-
-def test():
- failed = []
- def check(data, salt, iterations, keylen, expected):
- rv = pbkdf2_hex(data, salt, iterations, keylen)
- if rv != expected:
- print('Test failed:')
- print((' Expected: %s' % expected))
- print((' Got: %s' % rv))
- print(' Parameters:')
- print((' data=%s' % data))
- print((' salt=%s' % salt))
- print((' iterations=%d' % iterations))
- print()
- failed.append(1)
-
- # From RFC 6070
- check('password', 'salt', 1, 20,
- '0c60c80f961f0e71f3a9b524af6012062fe037a6')
- check('password', 'salt', 2, 20,
- 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957')
- check('password', 'salt', 4096, 20,
- '4b007901b765489abead49d926f721d065a429c1')
- check('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
- 4096, 25, '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038')
- check('pass\x00word', 'sa\x00lt', 4096, 16,
- '56fa6aa75548099dcc37d7f03425e0c3')
- # This one is from the RFC but it just takes for ages
- ##check('password', 'salt', 16777216, 20,
- ## 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')
-
- # From Crypt-PBKDF2
- check('password', 'ATHENA.MIT.EDUraeburn', 1, 16,
- 'cdedb5281bb2f801565a1122b2563515')
- check('password', 'ATHENA.MIT.EDUraeburn', 1, 32,
- 'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837')
- check('password', 'ATHENA.MIT.EDUraeburn', 2, 16,
- '01dbee7f4a9e243e988b62c73cda935d')
- check('password', 'ATHENA.MIT.EDUraeburn', 2, 32,
- '01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86')
- check('password', 'ATHENA.MIT.EDUraeburn', 1200, 32,
- '5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13')
- check('X' * 64, 'pass phrase equals block size', 1200, 32,
- '139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1')
- check('X' * 65, 'pass phrase exceeds block size', 1200, 32,
- '9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a')
-
- raise SystemExit(bool(failed))
-
-
-if __name__ == '__main__':
- test()
+ return ssc(a, b)