misc: add support for passwords hashed by Plone (#29430)
This commit is contained in:
parent
5cb0cb54c3
commit
3fe0a9f826
|
@ -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)),
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue