Home  >  Q&A  >  body text

如何找到Python的hashlib的实现(见截图)?

1 在hashlib.py中貌似找不到md5()这些东西
2 hashlib.py也没有import什么东西


怪我咯怪我咯2742 days ago1023

reply all(1)I'll reply

  • ringa_lee

    ringa_lee2017-04-17 17:37:01

    Hashlib has digital calculations similar to Crypto. If it is done purely in python, the speed will be very slow and cannot meet the requirements. Therefore, this specific implementation is placed in _hashlib.pyd. For Python2.7, the path is located in C: Python27DLLs_hashlib.pyd, this dynamic library implemented in C

    import hashlib
    print help(hashlib.md5)
    
    import _hashlib
    print help(_hashlib.openssl_md5)
    
    
    # 生成的MD5值一样
    S = "this is a demo for md5"
    assert hashlib.md5(S).hexdigest() == _hashlib.openssl_md5(S).hexdigest()
    

    The loading process is:

    try:
        import _hashlib
        new = __hash_new
        __get_hash = __get_openssl_constructor
        algorithms_available = algorithms_available.union(
            _hashlib.openssl_md_meth_names)
    except ImportError:
        new = __py_new
        __get_hash = __get_builtin_constructor
    
    for __func_name in __always_supported:
        # try them all, some may not work due to the OpenSSL
        # version not supporting that algorithm.
        try:
            globals()[__func_name] = __get_hash(__func_name)
        except ValueError:
            import logging
            logging.exception('code for hash %s was not found.', __func_name)
    
    
    try:
        # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
        from _hashlib import pbkdf2_hmac
    except ImportError:
        import binascii
        import struct
    
        _trans_5C = b"".join(chr(x ^ 0x5C) for x in range(256))
        _trans_36 = b"".join(chr(x ^ 0x36) for x in range(256))
    
        def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
            """Password based key derivation function 2 (PKCS #5 v2.0)
    
            This Python implementations based on the hmac module about as fast
            as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
            for long passwords.
            """
            if not isinstance(hash_name, str):
                raise TypeError(hash_name)
    
            if not isinstance(password, (bytes, bytearray)):
                password = bytes(buffer(password))
            if not isinstance(salt, (bytes, bytearray)):
                salt = bytes(buffer(salt))
    
            # Fast inline HMAC implementation
            inner = new(hash_name)
            outer = new(hash_name)
            blocksize = getattr(inner, 'block_size', 64)
            if len(password) > blocksize:
                password = new(hash_name, password).digest()
            password = password + b'\x00' * (blocksize - len(password))
            inner.update(password.translate(_trans_36))
            outer.update(password.translate(_trans_5C))
    
            def prf(msg, inner=inner, outer=outer):
                # PBKDF2_HMAC uses the password as key. We can re-use the same
                # digest objects and just update copies to skip initialization.
                icpy = inner.copy()
                ocpy = outer.copy()
                icpy.update(msg)
                ocpy.update(icpy.digest())
                return ocpy.digest()
    
            if iterations < 1:
                raise ValueError(iterations)
            if dklen is None:
                dklen = outer.digest_size
            if dklen < 1:
                raise ValueError(dklen)
    
            hex_format_string = "%%0%ix" % (new(hash_name).digest_size * 2)
    
            dkey = b''
            loop = 1
            while len(dkey) < dklen:
                prev = prf(salt + struct.pack(b'>I', loop))
                rkey = int(binascii.hexlify(prev), 16)
                for i in xrange(iterations - 1):
                    prev = prf(prev)
                    rkey ^= int(binascii.hexlify(prev), 16)
                loop += 1
                dkey += binascii.unhexlify(hex_format_string % rkey)
    
            return dkey[:dklen]
    
    # Cleanup locals()
    del __always_supported, __func_name, __get_hash
    del __py_new, __hash_new, __get_openssl_constructor
    

    reply
    0
  • Cancelreply