misc: add support for passwords hashed by Plone (#29430)

This commit is contained in:
Frédéric Péters 2019-01-03 16:25:31 +01:00
parent 5cb0cb54c3
commit 3fe0a9f826
3 changed files with 55 additions and 1 deletions

View File

@ -235,3 +235,49 @@ class JoomlaPasswordHasher(CommonPasswordHasher):
return '%s:%s' % (_hash, salt.decode('hex'))
else:
return _hash
class PloneSHA1PasswordHasher(hashers.SHA1PasswordHasher):
# from https://www.fourdigits.nl/blog/converting-plone-data-to-django/
"""
The SHA1 password hashing algorithm used by Plone.
Plone uses `password + salt`, Django has `salt + password`.
"""
algorithm = "plonesha1"
_prefix = '{SSHA}'
def encode(self, password, salt):
"""Encode a plain text password into a plonesha1 style hash."""
assert password is not None
assert salt
password = force_bytes(password)
salt = force_bytes(salt)
hashed = base64.b64encode(hashlib.sha1(password + salt).digest() + salt)
return "%s$%s%s" % (self.algorithm, self._prefix, hashed)
def verify(self, password, encoded):
"""Verify the given password against the encoded string."""
algorithm, data = encoded.split('$', 1)
assert algorithm == self.algorithm
# throw away the prefix
if data.startswith(self._prefix):
data = data[len(self._prefix):]
# extract salt from encoded data
intermediate = base64.b64decode(data)
salt = intermediate[20:].strip()
password_encoded = self.encode(password, salt)
return constant_time_compare(password_encoded, encoded)
def safe_summary(self, encoded):
algorithm, hash = encoded.split('$', 1)
assert algorithm == self.algorithm
return OrderedDict([
(_('algorithm'), algorithm),
(_('hash'), hashers.mask_hash(hash)),
])

View File

@ -191,7 +191,8 @@ PASSWORD_HASHERS = list(global_settings.PASSWORD_HASHERS) + [
'authentic2.hashers.SSHA1PasswordHasher',
'authentic2.hashers.SMD5PasswordHasher',
'authentic2.hashers.SHA1OLDAPPasswordHasher',
'authentic2.hashers.MD5OLDAPPasswordHasher'
'authentic2.hashers.MD5OLDAPPasswordHasher',
'authentic2.hashers.PloneSHA1PasswordHasher',
]
# Admin tools

View File

@ -30,3 +30,10 @@ def test_joomla_hasher():
assert hashers.JoomlaPasswordHasher().verify(pwd, dj_encoded)
assert hashers.JoomlaPasswordHasher.to_joomla(dj_encoded) == encoded
def test_plone_hasher():
hasher = hashers.PloneSHA1PasswordHasher()
assert hasher.verify(
'Azerty!123',
'plonesha1${SSHA}vS4g4MtzJyAjvhyW7vsrgjpJ6lDCU+Y42a6p')