mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-27 07:02:26 +00:00
Custom password hasher for SSHA
This commit is contained in:
parent
50945f0dfa
commit
2b4227c5fb
1 changed files with 68 additions and 8 deletions
|
@ -2,29 +2,89 @@
|
|||
# Module d'authentification
|
||||
# David Sinquin, Gabriel Détraz, Goulven Kermarec
|
||||
|
||||
import hashlib, binascii
|
||||
|
||||
import hashlib
|
||||
import binascii
|
||||
import os
|
||||
from base64 import urlsafe_b64encode as encode
|
||||
from base64 import urlsafe_b64decode as decode
|
||||
from base64 import encodestring
|
||||
from base64 import decodestring
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.contrib.auth import hashers
|
||||
|
||||
|
||||
ALGO_NAME = "{SSHA}"
|
||||
ALGO_LEN = len(ALGO_NAME + "$")
|
||||
DIGEST_LEN = 20
|
||||
|
||||
|
||||
def makeSecret(password):
|
||||
salt = os.urandom(4)
|
||||
h = hashlib.sha1(password.encode())
|
||||
h.update(salt)
|
||||
return "{SSHA}" + encode(h.digest() + salt).decode()
|
||||
return ALGO_NAME + "$" + encodestring(h.digest() + salt).decode()[:-1]
|
||||
|
||||
|
||||
def hashNT(password):
|
||||
hash = hashlib.new('md4', password.encode()).digest()
|
||||
return binascii.hexlify(hash)
|
||||
|
||||
|
||||
def checkPassword(challenge_password, password):
|
||||
challenge_bytes = decode(challenge_password[6:])
|
||||
digest = challenge_bytes[:20]
|
||||
salt = challenge_bytes[20:]
|
||||
challenge_bytes = decodestring(challenge_password[ALGO_LEN:].encode())
|
||||
digest = challenge_bytes[:DIGEST_LEN]
|
||||
salt = challenge_bytes[DIGEST_LEN:]
|
||||
hr = hashlib.sha1(password.encode())
|
||||
hr.update(salt)
|
||||
valid_password = True
|
||||
# La comparaison est volontairement en temps constant (pour éviter les timing-attacks)
|
||||
# La comparaison est volontairement en temps constant
|
||||
# (pour éviter les timing-attacks)
|
||||
for i, j in zip(digest, hr.digest()):
|
||||
valid_password &= i == j
|
||||
return valid_password
|
||||
|
||||
|
||||
class SSHAPasswordHasher(hashers.BasePasswordHasher):
|
||||
"""
|
||||
SSHA password hashing to allow for LDAP auth compatibility
|
||||
"""
|
||||
|
||||
algorithm = ALGO_NAME
|
||||
|
||||
def encode(self, password, salt, iterations=None):
|
||||
"""
|
||||
Hash and salt the given password using SSHA algorithm
|
||||
|
||||
salt is overridden
|
||||
"""
|
||||
assert password is not None
|
||||
return makeSecret(password)
|
||||
|
||||
def verify(self, password, encoded):
|
||||
"""
|
||||
Check password against encoded using SSHA algorithm
|
||||
"""
|
||||
assert encoded.startswith(self.algorithm)
|
||||
return checkPassword(encoded, password)
|
||||
|
||||
def safe_summary(self, encoded):
|
||||
"""
|
||||
Provides a safe summary ofthe password
|
||||
"""
|
||||
assert encoded.startswith(self.algorithm)
|
||||
hash = encoded[ALGO_LEN:]
|
||||
hash = binascii.hexlify(decodestring(hash.encode())).decode()
|
||||
return OrderedDict([
|
||||
('algorithm', self.algorithm),
|
||||
('iterations', 0),
|
||||
('salt', hashers.mask_hash(hash[2*DIGEST_LEN:], show=2)),
|
||||
('hash', hashers.mask_hash(hash[:2*DIGEST_LEN])),
|
||||
])
|
||||
|
||||
def harden_runtime(self, password, encoded):
|
||||
"""
|
||||
Method implemented to shut up BasePasswordHasher warning
|
||||
|
||||
As we are not using multiple iterations the method is pretty useless
|
||||
"""
|
||||
pass
|
||||
|
|
Loading…
Reference in a new issue