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'))
|
return '%s:%s' % (_hash, salt.decode('hex'))
|
||||||
else:
|
else:
|
||||||
return _hash
|
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.SSHA1PasswordHasher',
|
||||||
'authentic2.hashers.SMD5PasswordHasher',
|
'authentic2.hashers.SMD5PasswordHasher',
|
||||||
'authentic2.hashers.SHA1OLDAPPasswordHasher',
|
'authentic2.hashers.SHA1OLDAPPasswordHasher',
|
||||||
'authentic2.hashers.MD5OLDAPPasswordHasher'
|
'authentic2.hashers.MD5OLDAPPasswordHasher',
|
||||||
|
'authentic2.hashers.PloneSHA1PasswordHasher',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Admin tools
|
# Admin tools
|
||||||
|
|
|
@ -30,3 +30,10 @@ def test_joomla_hasher():
|
||||||
|
|
||||||
assert hashers.JoomlaPasswordHasher().verify(pwd, dj_encoded)
|
assert hashers.JoomlaPasswordHasher().verify(pwd, dj_encoded)
|
||||||
assert hashers.JoomlaPasswordHasher.to_joomla(dj_encoded) == 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