Skip to content

Commit a1f35b3

Browse files
committed
issue2551251 - migrate pbkdf2 passwords if more rounds configured
migrate/re-encrypt PBKDF2 password if stored password used a smaller number of rounds than set in password_pbkdf2_default_rounds. Also increase fallback number of rounds (when not set in config) to 2,000,000.
1 parent ff021ca commit a1f35b3

File tree

4 files changed

+21
-3
lines changed

4 files changed

+21
-3
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ Fixed:
7474
make sure that an 'X-Content-Type-Options: nosniff' header is sent.
7575
- issue2551252 - default number of rounds for PKDF2 password increased
7676
to 2,000,000.
77+
- issue2551251 - migrate/re-encrypt PBKDF2 password if stored
78+
password used a smaller number of rounds than set in
79+
password_pbkdf2_default_rounds.
7780

7881
Features:
7982

roundup/cgi/actions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,8 @@ def verifyPassword(self, userid, givenpw):
13991399
db = self.db
14001400
stored = db.user.get(userid, 'password')
14011401
if givenpw == stored:
1402-
if db.config.WEB_MIGRATE_PASSWORDS and stored.needs_migration():
1402+
if (db.config.WEB_MIGRATE_PASSWORDS and
1403+
stored.needs_migration(config=db.config)):
14031404
newpw = password.Password(givenpw, config=db.config)
14041405
db.user.set(userid, password=newpw)
14051406
db.commit()

roundup/password.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def encodePassword(plaintext, scheme, other=None, config=None):
190190
if config:
191191
rounds = config.PASSWORD_PBKDF2_DEFAULT_ROUNDS
192192
else:
193-
rounds = 10000
193+
rounds = 2000000
194194
if rounds < 1000:
195195
raise PasswordValueError("invalid PBKDF2 hash (rounds too low)")
196196
raw_digest = pbkdf2(plaintext, raw_salt, rounds, 20)
@@ -325,7 +325,7 @@ def __init__(self, plaintext=None, scheme=None, encrypted=None,
325325
def __repr__(self):
326326
return self.__str__()
327327

328-
def needs_migration(self):
328+
def needs_migration(self, config):
329329
""" Password has insecure scheme or other insecure parameters
330330
and needs migration to new password scheme
331331
"""
@@ -334,6 +334,10 @@ def needs_migration(self):
334334
rounds, salt, raw_salt, digest = pbkdf2_unpack(self.password)
335335
if rounds < 1000:
336336
return True
337+
if (self.scheme == "PBKDF2"):
338+
new_rounds = config.PASSWORD_PBKDF2_DEFAULT_ROUNDS
339+
if rounds < int(new_rounds):
340+
return True
337341
return False
338342

339343
def unpack(self, encrypted, scheme=None, strict=False, config=None):

test/test_security.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,4 +422,14 @@ def test_password(self):
422422
roundup.password.test_missing_crypt()
423423
roundup.password.crypt = orig_crypt
424424

425+
def test_pbkdf2_migrate_rounds(self):
426+
self.db.config.PASSWORD_PBKDF2_DEFAULT_ROUNDS = 10000
427+
428+
p = roundup.password.Password('sekrit', 'PBKDF2',
429+
config=self.db.config)
430+
431+
self.db.config.PASSWORD_PBKDF2_DEFAULT_ROUNDS = 2000000
432+
433+
self.assertEqual(p.needs_migration(config=self.db.config), True)
434+
425435
# vim: set filetype=python sts=4 sw=4 et si :

0 commit comments

Comments
 (0)