def raw(cls, secret, encoding=None): """encode password using LANMAN hash algorithm. :type secret: unicode or utf-8 encoded bytes :arg secret: secret to hash :type encoding: str :arg encoding: optional encoding to use for unicode inputs. this defaults to ``cp437``, which is the common case for most situations. :returns: returns string of raw bytes """ if not encoding: encoding = cls.default_encoding # some nice empircal data re: different encodings is at... # http://www.openwall.com/lists/john-dev/2011/08/01/2 # http://www.freerainbowtables.com/phpBB3/viewtopic.php?t=387&p=12163 from passlib.crypto.des import des_encrypt_block MAGIC = cls._magic if isinstance(secret, unicode): # perform uppercasing while we're still unicode, # to give a better shot at getting non-ascii chars right. # (though some codepages do NOT upper-case the same as unicode). secret = secret.upper().encode(encoding) elif isinstance(secret, bytes): # FIXME: just trusting ascii upper will work? # and if not, how to do codepage specific case conversion? # we could decode first using , # but *that* might not always be right. secret = secret.upper() else: raise TypeError("secret must be unicode or bytes") secret = right_pad_string(secret, 14) return des_encrypt_block(secret[0:7], MAGIC) + \ des_encrypt_block(secret[7:14], MAGIC)