Merge remote-tracking branch 'remotes/lotusecho/trac_711_test_speed'
[mediagoblin.git] / mediagoblin / plugins / basic_auth / tools.py
CommitLineData
5b6923ab
RE
1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16import bcrypt
14efa7bd 17import random
5b6923ab 18
5b6923ab
RE
19
20def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None):
21 """
22 Check to see if this password matches.
23
24 Args:
25 - raw_pass: user submitted password to check for authenticity.
26 - stored_hash: The hash of the raw password (and possibly extra
27 salt) to check against
28 - extra_salt: (optional) If this password is with stored with a
29 non-database extra salt (probably in the config file) for extra
30 security, factor this into the check.
31
32 Returns:
33 True or False depending on success.
34 """
35 if extra_salt:
36 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
37
38 hashed_pass = bcrypt.hashpw(raw_pass.encode('utf-8'), stored_hash)
39
40 # Reduce risk of timing attacks by hashing again with a random
41 # number (thx to zooko on this advice, which I hopefully
42 # incorporated right.)
43 #
44 # See also:
45 rand_salt = bcrypt.gensalt(5)
46 randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt)
47 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
48
49 return randplus_stored_hash == randplus_hashed_pass
50
51
52def bcrypt_gen_password_hash(raw_pass, extra_salt=None):
53 """
54 Generate a salt for this new password.
55
56 Args:
57 - raw_pass: user submitted password
58 - extra_salt: (optional) If this password is with stored with a
59 non-database extra salt
60 """
61 if extra_salt:
62 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
63
64 return unicode(
65 bcrypt.hashpw(raw_pass.encode('utf-8'), bcrypt.gensalt()))
66
67
14efa7bd
RE
68def fake_login_attempt():
69 """
70 Pretend we're trying to login.
71
72 Nothing actually happens here, we're just trying to take up some
73 time, approximately the same amount of time as
74 bcrypt_check_password, so as to avoid figuring out what users are
75 on the system by intentionally faking logins a bunch of times.
76 """
77 rand_salt = bcrypt.gensalt(5)
78
79 hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt)
80
81 randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt)
82 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
83
84 randplus_stored_hash == randplus_hashed_pass