def test_10_wrapped_attributes(self): d1 = uh.PrefixWrapper('d1', 'ldap_md5', '{XXX}', '{MD5}') self.assertEqual(d1.name, 'd1') self.assertIs(d1.setting_kwds, ldap_md5.setting_kwds) self.assertFalse('max_rounds' in dir(d1)) d2 = uh.PrefixWrapper('d2', 'sha256_crypt', '{XXX}') self.assertIs(d2.setting_kwds, sha256_crypt.setting_kwds) self.assertTrue('max_rounds' in dir(d2))
def test_12_ident(self): h = uh.PrefixWrapper('h2', 'ldap_md5', '{XXX}') self.assertEqual(h.ident, u('{XXX}{MD5}')) self.assertIs(h.ident_values, None) h = uh.PrefixWrapper('h2', 'des_crypt', '{XXX}') self.assertIs(h.ident, None) self.assertIs(h.ident_values, None) h = uh.PrefixWrapper('h1', 'ldap_md5', '{XXX}', '{MD5}') self.assertIs(h.ident, None) self.assertIs(h.ident_values, None) h = uh.PrefixWrapper('h3', 'ldap_md5', '{XXX}', ident='{X') self.assertEqual(h.ident, u('{X')) self.assertIs(h.ident_values, None) h = uh.PrefixWrapper('h3', 'ldap_md5', '{XXX}', ident='{XXX}A') self.assertRaises(ValueError, uh.PrefixWrapper, 'h3', 'ldap_md5', '{XXX}', ident='{XY') self.assertRaises(ValueError, uh.PrefixWrapper, 'h3', 'ldap_md5', '{XXX}', ident='{XXXX') h = uh.PrefixWrapper('h4', 'phpass', '{XXX}') self.assertIs(h.ident, None) self.assertEqual(h.ident_values, (u('{XXX}$P$'), u('{XXX}$H$'))) h = uh.PrefixWrapper('h5', 'des_crypt', '{XXX}', ident=True) self.assertEqual(h.ident, u('{XXX}')) self.assertIs(h.ident_values, None) self.assertRaises(ValueError, uh.PrefixWrapper, 'h6', 'des_crypt', ident=True) with self.assertWarningList('orig_prefix.*may not work correctly'): h = uh.PrefixWrapper('h7', 'phpass', orig_prefix='$', prefix='?') self.assertEqual(h.ident_values, None) self.assertEqual(h.ident, None) return
def _init_ldap_crypt_handlers(): g = globals() for wname in unix_crypt_schemes: name = 'ldap_' + wname g[name] = uh.PrefixWrapper(name, wname, prefix=u('{CRYPT}'), lazy=True) del g
def test_01_active_loading(self): d1 = uh.PrefixWrapper('d1', 'ldap_md5', '{XXX}', '{MD5}') self.assertEqual(d1._wrapped_name, 'ldap_md5') self.assertIs(d1._wrapped_handler, ldap_md5) self.assertIs(d1.wrapped, ldap_md5) with dummy_handler_in_registry('ldap_md5') as (dummy): self.assertIs(d1.wrapped, ldap_md5)
def test_02_explicit(self): d1 = uh.PrefixWrapper('d1', ldap_md5, '{XXX}', '{MD5}') self.assertEqual(d1._wrapped_name, None) self.assertIs(d1._wrapped_handler, ldap_md5) self.assertIs(d1.wrapped, ldap_md5) with dummy_handler_in_registry('ldap_md5') as (dummy): self.assertIs(d1.wrapped, ldap_md5) return
def test_00_lazy_loading(self): d1 = uh.PrefixWrapper('d1', 'ldap_md5', '{XXX}', '{MD5}', lazy=True) self.assertEqual(d1._wrapped_name, 'ldap_md5') self.assertIs(d1._wrapped_handler, None) self.assertIs(d1.wrapped, ldap_md5) self.assertIs(d1._wrapped_handler, ldap_md5) with dummy_handler_in_registry('ldap_md5') as (dummy): self.assertIs(d1.wrapped, ldap_md5) return
def test_11_wrapped_methods(self): d1 = uh.PrefixWrapper('d1', 'ldap_md5', '{XXX}', '{MD5}') dph = '{XXX}X03MO1qnZdYdgyfeuILPmQ==' lph = '{MD5}X03MO1qnZdYdgyfeuILPmQ==' self.assertEqual(d1.genconfig(), '{XXX}1B2M2Y8AsgTpgAmY7PhCfg==') self.assertRaises(TypeError, d1.genhash, 'password', None) self.assertEqual(d1.genhash('password', dph), dph) self.assertRaises(ValueError, d1.genhash, 'password', lph) self.assertEqual(d1.hash('password'), dph) self.assertTrue(d1.identify(dph)) self.assertFalse(d1.identify(lph)) self.assertRaises(ValueError, d1.verify, 'password', lph) self.assertTrue(d1.verify('password', dph)) return
def test_14_bad_hash(self): h = uh.PrefixWrapper('h2', 'md5_crypt', orig_prefix='$6$') self.assertRaises(ValueError, h.hash, 'test')
def test_13_repr(self): h = uh.PrefixWrapper('h2', 'md5_crypt', '{XXX}', orig_prefix='$1$') self.assertRegex(repr(h), '(?x)^PrefixWrapper\\(\n [\'"]h2[\'"],\\s+\n [\'"]md5_crypt[\'"],\\s+\n prefix=u?["\']{XXX}[\'"],\\s+\n orig_prefix=u?["\']\\$1\\$[\'"]\n \\)$')
import logging log = logging.getLogger(__name__) import otp.ai.passlib.utils.handlers as uh from otp.ai.passlib.utils.compat import u __all__ = ['roundup_plaintext', 'ldap_hex_md5', 'ldap_hex_sha1'] roundup_plaintext = uh.PrefixWrapper('roundup_plaintext', 'plaintext', prefix=u('{plaintext}'), lazy=True) ldap_hex_md5 = uh.PrefixWrapper('ldap_hex_md5', 'hex_md5', u('{MD5}'), lazy=True) ldap_hex_sha1 = uh.PrefixWrapper('ldap_hex_sha1', 'hex_sha1', u('{SHA}'), lazy=True)
@classmethod def raw(cls, secret): secret = to_unicode(secret, 'utf-8', param='secret') return md4(secret.encode('utf-16-le')).digest() @classmethod def raw_nthash(cls, secret, hex=False): warn('nthash.raw_nthash() is deprecated, and will be removed in Passlib 1.8, please use nthash.raw() instead', DeprecationWarning) ret = nthash.raw(secret) if hex: return hexlify(ret).decode('ascii') return ret bsd_nthash = uh.PrefixWrapper('bsd_nthash', nthash, prefix='$3$$', ident='$3$$', doc="The class support FreeBSD's representation of NTHASH\n (which is compatible with the :ref:`modular-crypt-format`),\n and follows the :ref:`password-hash-api`.\n\n It has no salt and a single fixed round.\n\n The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods accept no optional keywords.\n ") class msdcc(uh.HasUserContext, uh.StaticHandler): name = 'msdcc' checksum_chars = uh.HEX_CHARS checksum_size = 32 @classmethod def _norm_hash(cls, hash): return hash.lower() def _calc_checksum(self, secret): return hexlify(self.raw(secret, self.user)).decode('ascii') @classmethod def raw(cls, secret, user):
return str_to_uascii(sha1(self.salt.encode('ascii') + secret).hexdigest()) class django_salted_md5(DjangoSaltedHash): name = 'django_salted_md5' django_name = 'md5' ident = u('md5$') checksum_size = 32 def _calc_checksum(self, secret): if isinstance(secret, unicode): secret = secret.encode('utf-8') return str_to_uascii(md5(self.salt.encode('ascii') + secret).hexdigest()) django_bcrypt = uh.PrefixWrapper('django_bcrypt', bcrypt, prefix=u('bcrypt$'), ident=u('bcrypt$'), doc='This class implements Django 1.4\'s BCrypt wrapper, and follows the :ref:`password-hash-api`.\n\n This is identical to :class:`!bcrypt` itself, but with\n the Django-specific prefix ``"bcrypt$"`` prepended.\n\n See :doc:`/lib/passlib.hash.bcrypt` for more details,\n the usage and behavior is identical.\n\n This should be compatible with the hashes generated by\n Django 1.4\'s :class:`!BCryptPasswordHasher` class.\n\n .. versionadded:: 1.6\n ') django_bcrypt.django_name = 'bcrypt' django_bcrypt._using_clone_attrs += ('django_name', ) class django_bcrypt_sha256(_wrapped_bcrypt): name = 'django_bcrypt_sha256' django_name = 'bcrypt_sha256' _digest = sha256 django_prefix = u('bcrypt_sha256$') @classmethod def identify(cls, hash): hash = uh.to_unicode_for_identify(hash) if not hash: return False return hash.startswith(cls.django_prefix)
default_rounds=rounds, checksum_size=digest_size, encoded_checksum_size=(digest_size * 4 + 2) // 3, __doc__= 'This class implements a generic ``PBKDF2-HMAC-%(digest)s``-based password hash, and follows the :ref:`password-hash-api`.\n\n It supports a variable-length salt, and a variable number of rounds.\n\n The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:\n\n :type salt: bytes\n :param salt:\n Optional salt bytes.\n If specified, the length must be between 0-1024 bytes.\n If not specified, a %(dsc)d byte salt will be autogenerated (this is recommended).\n\n :type salt_size: int\n :param salt_size:\n Optional number of bytes to use when autogenerating new salts.\n Defaults to %(dsc)d bytes, but can be any value between 0 and 1024.\n\n :type rounds: int\n :param rounds:\n Optional number of rounds to use.\n Defaults to %(dr)d, but must be within ``range(1,1<<32)``.\n\n :type relaxed: bool\n :param relaxed:\n By default, providing an invalid value for one of the other\n keywords will result in a :exc:`ValueError`. If ``relaxed=True``,\n and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`\n will be issued instead. Correctable errors include ``rounds``\n that are too small or too large, and ``salt`` strings that are too long.\n\n .. versionadded:: 1.6\n ' % dict(digest=hash_name.upper(), dsc=base.default_salt_size, dr=rounds))) pbkdf2_sha1 = create_pbkdf2_hash('sha1', 20, 131000, ident=u('$pbkdf2$')) pbkdf2_sha256 = create_pbkdf2_hash('sha256', 32, 29000) pbkdf2_sha512 = create_pbkdf2_hash('sha512', 64, 25000) ldap_pbkdf2_sha1 = uh.PrefixWrapper('ldap_pbkdf2_sha1', pbkdf2_sha1, '{PBKDF2}', '$pbkdf2$', ident=True) ldap_pbkdf2_sha256 = uh.PrefixWrapper('ldap_pbkdf2_sha256', pbkdf2_sha256, '{PBKDF2-SHA256}', '$pbkdf2-sha256$', ident=True) ldap_pbkdf2_sha512 = uh.PrefixWrapper('ldap_pbkdf2_sha512', pbkdf2_sha512, '{PBKDF2-SHA512}', '$pbkdf2-sha512$', ident=True) CTA_ALTCHARS = '-_'