source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/contrib/pbkdf2.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 4.7 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3    pbkdf2
4    ~~~~~~
5
6    This module implements pbkdf2 for Python.  It also has some basic
7    tests that ensure that it works.  The implementation is straightforward
8    and uses stdlib only stuff and can be easily be copy/pasted into
9    your favourite application.
10
11    Use this as replacement for bcrypt that does not need a c implementation
12    of a modified blowfish crypto algo.
13
14    Example usage:
15
16    >>> pbkdf2_hex('what i want to hash', 'the random salt')
17    'fa7cc8a2b0a932f8e6ea42f9787e9d36e592e0c222ada6a9'
18
19    How to use this:
20
21    1.  Use a constant time string compare function to compare the stored hash
22        with the one you're generating::
23
24            def safe_str_cmp(a, b):
25                if len(a) != len(b):
26                    return False
27                rv = 0
28                for x, y in izip(a, b):
29                    rv |= ord(x) ^ ord(y)
30                return rv == 0
31
32    2.  Use `os.urandom` to generate a proper salt of at least 8 byte.
33        Use a unique salt per hashed password.
34
35    3.  Store ``algorithm$salt:costfactor$hash`` in the database so that
36        you can upgrade later easily to a different algorithm if you need
37        one.  For instance ``PBKDF2-256$thesalt:10000$deadbeef...``.
38
39
40    :copyright: (c) Copyright 2011 by Armin Ronacher.
41    :license: BSD, see LICENSE for more details.
42"""
43import hmac
44import hashlib
45from struct import Struct
46from operator import xor
47from itertools import izip, starmap
48
49
50_pack_int = Struct('>I').pack
51
52
53def pbkdf2_hex(data, salt, iterations=1000, keylen=24, hashfunc=None):
54    """Like :func:`pbkdf2_bin` but returns a hex encoded string."""
55    return pbkdf2_bin(data, salt, iterations, keylen, hashfunc).encode('hex')
56
57
58def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
59    """Returns a binary digest for the PBKDF2 hash algorithm of `data`
60    with the given `salt`.  It iterates `iterations` time and produces a
61    key of `keylen` bytes.  By default SHA-1 is used as hash function,
62    a different hashlib `hashfunc` can be provided.
63    """
64    hashfunc = hashfunc or hashlib.sha1
65    mac = hmac.new(data, None, hashfunc)
66    def _pseudorandom(x, mac=mac):
67        h = mac.copy()
68        h.update(x)
69        return map(ord, h.digest())
70    buf = []
71    for block in xrange(1, -(-keylen // mac.digest_size) + 1):
72        rv = u = _pseudorandom(salt + _pack_int(block))
73        for i in xrange(iterations - 1):
74            u = _pseudorandom(''.join(map(chr, u)))
75            rv = starmap(xor, izip(rv, u))
76        buf.extend(rv)
77    return ''.join(map(chr, buf))[:keylen]
78
79
80def test():
81    failed = []
82    def check(data, salt, iterations, keylen, expected):
83        rv = pbkdf2_hex(data, salt, iterations, keylen)
84        if rv != expected:
85            print('Test failed:')
86            print('  Expected:   %s' % expected)
87            print('  Got:        %s' % rv)
88            print('  Parameters:')
89            print('    data=%s' % data)
90            print('    salt=%s' % salt)
91            print('    iterations=%d' % iterations)
92            print()
93            failed.append(1)
94
95    # From RFC 6070
96    check('password', 'salt', 1, 20,
97          '0c60c80f961f0e71f3a9b524af6012062fe037a6')
98    check('password', 'salt', 2, 20,
99          'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957')
100    check('password', 'salt', 4096, 20,
101          '4b007901b765489abead49d926f721d065a429c1')
102    check('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt',
103          4096, 25, '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038')
104    check('pass\x00word', 'sa\x00lt', 4096, 16,
105          '56fa6aa75548099dcc37d7f03425e0c3')
106    # This one is from the RFC but it just takes for ages
107    ##check('password', 'salt', 16777216, 20,
108    ##      'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')
109
110    # From Crypt-PBKDF2
111    check('password', 'ATHENA.MIT.EDUraeburn', 1, 16,
112          'cdedb5281bb2f801565a1122b2563515')
113    check('password', 'ATHENA.MIT.EDUraeburn', 1, 32,
114          'cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837')
115    check('password', 'ATHENA.MIT.EDUraeburn', 2, 16,
116          '01dbee7f4a9e243e988b62c73cda935d')
117    check('password', 'ATHENA.MIT.EDUraeburn', 2, 32,
118          '01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86')
119    check('password', 'ATHENA.MIT.EDUraeburn', 1200, 32,
120          '5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13')
121    check('X' * 64, 'pass phrase equals block size', 1200, 32,
122          '139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1')
123    check('X' * 65, 'pass phrase exceeds block size', 1200, 32,
124          '9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a')
125
126    raise SystemExit(bool(failed))
127
128
129if __name__ == '__main__':
130    test()
Note: See TracBrowser for help on using the repository browser.