def password_matches_crypt(self, password): crypt_password = self.crypt() if crypt_password is None: return False # try MD5 fields = crypt_password.split('$') if len(fields) > 3: salt = fields[2] crypted = _crypt(password, '$1$' + salt + '$') if crypt_password == crypted: return True # try crypt (for legacy users) crypted = _crypt(password, crypt_password[:2]) if crypt_password == crypted: return True return False
def password_matches_crypt(self, password): crypt_password = self.crypt() if crypt_password is None: return False # try MD5 fields = crypt_password.split('$') if len(fields) > 3: salt = fields[2] crypted = _crypt(password, '$1$'+salt+'$') if crypt_password == crypted: return True # try crypt (for legacy users) crypted = _crypt(password, crypt_password[:2]) if crypt_password == crypted: return True return False
def crypted(username, password, word, sulfur=None, calculate=1, file=_SHADOW_FILE): if sulfur is None: sulfur = sulfur_for(username, password, calculate, file) return _crypt(word, sulfur)
def safe_crypt(secret, hash): if isinstance(secret, unicode): secret = secret.encode("utf-8") if _NULL in secret: raise ValueError("null character in secret") if isinstance(hash, unicode): hash = hash.encode("ascii") result = _crypt(secret, hash) if not result: return None result = result.decode("ascii") if result[0] in _invalid_prefixes: return None return result
def crypt(password, method_id=None, salt=None): # type: (str, Optional[str], Optional[str]) -> str """ Return crypt hash. :param password: password string. :param method_id: optional hash type, MD5, SHA256/SHA-256, SHA512/SHA-512. :param salt: salt for randomize the hashing. :returns: the hashed password string. """ hashing_method = configRegistry.get('password/hashing/method', 'sha-512').upper() if salt is None: salt = '' valid = [ '.', '/', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] urandom = open("/dev/urandom", "rb") for i in range( 0, 16 ): # up to 16 bytes of salt are evaluated by crypt(3), overhead is ignored o = ord(urandom.read(1)) while not o < 256 // len(valid) * len( valid ): # make sure not to skew the distribution when using modulo o = ord(urandom.read(1)) salt = salt + valid[(o % len(valid))] urandom.close() if method_id is None: method_id = { 'MD5': '1', 'SHA256': '5', 'SHA-256': '5', 'SHA512': '6', 'SHA-512': '6', }.get(hashing_method, '6') from crypt import crypt as _crypt return _crypt(password, '$%s$%s$' % ( method_id, salt, ))
def safe_crypt(secret, hash): if crypt_accepts_bytes: # PyPy3 -- all bytes accepted, but unicode encoded to ASCII, # so handling that ourselves. if isinstance(secret, unicode): secret = secret.encode("utf-8") if _BNULL in secret: raise ValueError("null character in secret") if isinstance(hash, unicode): hash = hash.encode("ascii") else: # CPython3's crypt() doesn't take bytes, only unicode; unicode which is then # encoding using utf-8 before passing to the C-level crypt(). # so we have to decode the secret. if isinstance(secret, bytes): orig = secret try: secret = secret.decode("utf-8") except UnicodeDecodeError: return None # sanity check it encodes back to original byte string, # otherwise when crypt() does it's encoding, it'll hash the wrong bytes! assert secret.encode("utf-8") == orig, \ "utf-8 spec says this can't happen!" if _NULL in secret: raise ValueError("null character in secret") if isinstance(hash, bytes): hash = hash.decode("ascii") try: with _safe_crypt_lock: result = _crypt(secret, hash) except OSError: # new in py39 -- per https://bugs.python.org/issue39289, # crypt() now throws OSError for various things, mainly unknown hash formats # translating that to None for now (may revise safe_crypt behavior in future) return None # NOTE: per issue 113, crypt() may return bytes in some odd cases. # assuming it should still return an ASCII hash though, # or there's a bigger issue at hand. if isinstance(result, bytes): result = result.decode("ascii") if not result or result[0] in _invalid_prefixes: return None return result
def crypt(word, salt): """ 代理原生crypt """ hash_method = get_hash(salt) if hash_method is None: if _crypt is None: raise TypeError("not crypt module!") else: hash_str = _crypt(word, salt) hash_str = hash_str[hash_str.rindex("$") + 1:] else: hash_obj = hash_method() hash_obj.update((salt + word + salt).encode()) pwd = hash_obj.digest() hash_str = encode_bytes(pwd).decode() if salt[-1] == "$": return salt + hash_str return "%s$%s" % (salt, hash_str)
def safe_crypt(secret, hash): if isinstance(secret, bytes): # Python 3's crypt() only accepts unicode, which is then # encoding using utf-8 before passing to the C-level crypt(). # so we have to decode the secret. orig = secret try: secret = secret.decode("utf-8") except UnicodeDecodeError: return None assert secret.encode("utf-8") == orig, \ "utf-8 spec says this can't happen!" if _NULL in secret: raise ValueError("null character in secret") if isinstance(hash, bytes): hash = hash.decode("ascii") result = _crypt(secret, hash) if not result or result[0] in _invalid_prefixes: return None return result
# some crypt() variants will return various constant strings when # an invalid/unrecognized config string is passed in; instead of # returning NULL / None. examples include ":", ":0", "*0", etc. # safe_crypt() returns None for any string starting with one of the # chars in this string... _invalid_prefixes = u("*:!") if PY3: # * pypy3 (as of v7.3.1) has a crypt which accepts bytes, or ASCII-only unicode. # * whereas CPython3 (as of v3.9) has a crypt which doesn't take bytes, # but accepts ANY unicode (which it always encodes to UTF8). crypt_accepts_bytes = True try: _crypt(b"\xEE", "xx") except TypeError: # CPython will throw TypeError crypt_accepts_bytes = False except: # no pragma # don't care about other errors this might throw, # just want to see if we get past initial type-coercion step. pass def safe_crypt(secret, hash): if crypt_accepts_bytes: # PyPy3 -- all bytes accepted, but unicode encoded to ASCII, # so handling that ourselves. if isinstance(secret, unicode): secret = secret.encode("utf-8") if _BNULL in secret:
def password_matches_crypt(self, password): crypt_password = self.crypt() return _crypt(password, crypt_password[:2]) == crypt_password
def csiked_password(password): return _crypt(password, "en")
for a, b, c in ((0, 6, 12), (1, 7, 13), (2, 8, 14), (3, 9, 15), (4, 10, 5)): v = ord(final[a]) << 16 | ord(final[b]) << 8 | ord(final[c]) for i in range(4): rearranged += itoa64[v & 0x3f]; v >>= 6 v = ord(final[11]) for i in range(2): rearranged += itoa64[v & 0x3f]; v >>= 6 return magic + salt + '$' + rearranged _plus_to_dot = string.maketrans('+', '.') def md5salt(): return '$1$' + urandom(6).encode('base64').translate(_plus_to_dot).rstrip() word = "joefoo1234" magicsalt = "$1$kBmmDTGr" magic, salt = magicsalt[1:].split('$')[:2] magic = '$' + magic + '$' hashword = _md5crypt(word, magic + salt) md5crypt = _md5crypt try: from crypt import crypt as _crypt except ImportError: pass else: if _crypt(word, hashword) == '$1$kBmmDTGr$FngxLa03zfySCR3dZTdXS1': md5crypt = _crypt