Merge branch 'master' of http://git.gitorious.org/mediagoblin/mediagoblin
[mediagoblin.git] / mediagoblin / auth / lib.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
6755f50e
CAW
2# Copyright (C) 2011 Free Software Foundation, Inc
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/>.
16
17import os
c15c9843 18import random
6755f50e 19
51479a1d
CAW
20import bcrypt
21
6755f50e
CAW
22
23def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None):
24 """
25 Check to see if this password matches.
26
27 Args:
28 - raw_pass: user submitted password to check for authenticity.
29 - stored_hash: The hash of the raw password (and possibly extra
30 salt) to check against
31 - extra_salt: (optional) If this password is with stored with a
32 non-database extra salt (probably in the config file) for extra
33 security, factor this into the check.
34
35 Returns:
36 True or False depending on success.
37 """
38 if extra_salt:
39 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
40
41 hashed_pass = bcrypt.hashpw(raw_pass, stored_hash)
42
43 # Reduce risk of timing attacks by hashing again with a random
44 # number (thx to zooko on this advice, which I hopefully
45 # incorporated right.)
46 #
47 # See also:
48 rand_salt = bcrypt.gensalt(5)
49 randplus_stored_hash = bcrypt.hashpw(stored_hash, rand_salt)
50 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
51
52 return randplus_stored_hash == randplus_hashed_pass
53
54
55def bcrypt_gen_password_hash(raw_pass, extra_salt=None):
56 """
57 Generate a salt for this new password.
58
59 Args:
60 - raw_pass: user submitted password
61 - extra_salt: (optional) If this password is with stored with a
62 non-database extra salt
63 """
64 if extra_salt:
65 raw_pass = u"%s:%s" % (extra_salt, raw_pass)
66
e0bc23d3 67 return unicode(bcrypt.hashpw(raw_pass, bcrypt.gensalt()))
c15c9843
CAW
68
69
70def fake_login_attempt():
71 """
72 Pretend we're trying to login.
73
74 Nothing actually happens here, we're just trying to take up some
51479a1d
CAW
75 time, approximately the same amount of time as
76 bcrypt_check_password, so as to avoid figuring out what users are
77 on the system by intentionally faking logins a bunch of times.
c15c9843
CAW
78 """
79 rand_salt = bcrypt.gensalt(5)
80
81 hashed_pass = bcrypt.hashpw(str(random.random()), rand_salt)
82
83 randplus_stored_hash = bcrypt.hashpw(str(random.random()), rand_salt)
84 randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
85
86 randplus_stored_hash == randplus_hashed_pass