# Standard modules
import logging
+import re
# Third party modules
_ = XLATOR.gettext
ngettext = XLATOR.ngettext
-__version__ = '0.3.4'
+__version__ = '0.4.0'
# =============================================================================
'ldap_pbkdf2_sha512': 'PBKDF2_SHA512',
}
+ crypt_ids = {
+ '^1$': 'CRYPT-MD5',
+ '^2.*': 'CRYPT-BRYPT',
+ '^3$': 'CRYPT-NTHASH',
+ '^5$': 'CRYPT-SHA256',
+ '^6$': 'CRYPT-SHA512',
+ '^7$': 'CRYPT-SCRYPT',
+ '^8$': 'CRYPT-PBKDF2',
+ '^gy$': 'CRYPT-GOSTYESCRYPT',
+ '^md5$': 'CRYPT-SOLARIS-MD5',
+ '^sha1$': 'CRYPT-PBKDF1-SHA1',
+ '^y$': 'CRYPT-YESCRYPT',
+ }
+
+ crypt_id_re = {}
+ re_hash_method = re.compile(r'^\{([^\}]+)\}')
+ re_crypt_id = re.compile(r'^\$([^\$]+)\$')
+
schema_description = {
'ldap_des_crypt': _('The ancient and notorious 3 DES crypt method.'),
'ldap_md5': _('Pure {} hashing method.').format('MD5'),
cls.passlib_context = passlib.context.CryptContext(**context_opts)
+ cls.crypt_id_re = {}
+ for crypt_id in cls.crypt_ids.keys():
+ cls.crypt_id_re[crypt_id] = re.compile(crypt_id, re.IGNORECASE)
+
# -------------------------------------------------------------------------
def __init__(
self, appname=None, verbose=0, version=__version__, base_dir=None,
LOG.debug('The quality of the new password seems to be sufficient.')
return True
+ # -------------------------------------------------------------------------
+ def get_hashing_schema(self, pwd_hash):
+ """Get the used hashing method of the given password hash."""
+ if self.verbose > 2:
+ LOG.debug('Password hash: {!r}'.format(pwd_hash))
+ pwd_hash = pwd_hash.strip()
+ if not pwd_hash:
+ return 'EMPTY'
+
+ m = self.re_hash_method.match(pwd_hash)
+ if not m:
+ return 'CLEAR'
+ method = m.group(1).upper()
+ if self.verbose > 2:
+ LOG.debug('Found raw method: {!r}'.format(method))
+ if method != 'CRYPT':
+ return method
+
+ bare_hash = self.re_hash_method.sub('', pwd_hash)
+ if self.verbose > 2:
+ LOG.debug('Bare hash: {!r}'.format(bare_hash))
+ m = self.re_crypt_id.match(bare_hash)
+ if not m:
+ return 'CRYPT'
+
+ crypt_id = m.group(1)
+
+ for pattern in self.crypt_id_re.keys():
+ re_id = self.crypt_id_re[pattern]
+ if re_id.match(crypt_id):
+ return self.crypt_ids[pattern]
+
+ return 'CRYPT (unknown {!r})'.format(crypt_id)
+
# =============================================================================
if __name__ == '__main__':