第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

什么是 _md5.md5,為什么 hashlib.md5 這么慢?

什么是 _md5.md5,為什么 hashlib.md5 這么慢?

炎炎設(shè)計(jì) 2022-07-12 09:34:49
當(dāng)對(duì)緩慢的 stdlib實(shí)現(xiàn)_md5感到沮喪時(shí),發(fā)現(xiàn)此未記錄。hashlib.md5在 Macbook 上:>>> timeit hashlib.md5(b"hello world")597 ns ± 17.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> timeit _md5.md5(b"hello world")224 ns ± 3.18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> _md5<module '_md5' from '/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload/_md5.cpython-37m-darwin.so'>在 Windows 機(jī)器上:>>> timeit hashlib.md5(b"stonk overflow")328 ns ± 21.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> timeit _md5.md5(b"stonk overflow")110 ns ± 12.5 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)>>> _md5<module '_md5' (built-in)>在 Linux 機(jī)器上:>>> timeit hashlib.md5(b"https://adventofcode.com/2016/day/5")259 ns ± 1.33 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)>>> timeit _md5.md5(b"https://adventofcode.com/2016/day/5")102 ns ± 0.0576 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)>>> _md5<module '_md5' from '/usr/local/lib/python3.8/lib-dynload/_md5.cpython-38-x86_64-linux-gnu.so'>對(duì)于散列短消息,它的速度更快。對(duì)于長(zhǎng)消息,類似的性能。為什么它隱藏在下劃線擴(kuò)展模塊中,為什么在 hashlib 中默認(rèn)不使用這種更快的實(shí)現(xiàn)? 什么是_md5模塊,為什么它沒有公共 API?
查看完整描述

3 回答

?
千巷貓影

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超7個(gè)贊

在Python 2. 5之前,哈希和摘要在它們自己的模塊中實(shí)現(xiàn)(例如[Python 2.Docs ]: md5 - MD5 message digest algorithm)。
v2.5開始,[Python 2.6.Docs]: hashlib -添加了安全哈希和消息摘要。其目的是:

  1. 提供對(duì)哈希/摘要的統(tǒng)一訪問方法(通過它們的名稱)

  2. 切換(默認(rèn)情況下)到外部密碼學(xué)提供程序(這似乎是委托給該領(lǐng)域的某個(gè)專門實(shí)體的合乎邏輯的步驟,因?yàn)榫S護(hù)所有這些算法可能是一種矯枉過正)。那時(shí)OpenSSL是最好的選擇:足夠成熟、知名和兼容(有一堆類似的Java提供者,但那些都沒什么用)

作為#2的副作用。,Python實(shí)現(xiàn)對(duì)公共API隱藏(重命名為:_md5_sha1、_sha256、_sha512,后添加:_blake2、_sha3),因?yàn)槿哂嗤ǔ?huì)造成混淆。
但是,另一個(gè)副作用是_hashlib.so對(duì)OpenSSLlibcrypto*.so的依賴(這是Nix(至少Lnx)特定的,在Win上,靜態(tài)libeay32.lib鏈接在_hashlib.pyd,還有_ssl.pyd(我認(rèn)為是蹩腳的),直到v3。7 +,其中OpenSSL .dllPython安裝的一部分)。
可能在90+%的機(jī)器上一切都很順利,因?yàn)槟J(rèn)安裝了OpenSSL,但是對(duì)于那些沒有安裝的機(jī)器,很多事情可能會(huì)被破壞,因?yàn)槔?em>hashlib是由許多模塊導(dǎo)入的(一個(gè)這樣的例子是隨機(jī)的它本身被許多其他人導(dǎo)入),因此與密碼學(xué)完全無關(guān)的瑣碎代碼(至少不是第一眼看到的)將停止工作. 這就是保留舊實(shí)現(xiàn)的原因(但同樣,它們只是后備,因?yàn)?em>OpenSSL版本/應(yīng)該得到更好的維護(hù))。

[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q059955854]> ~/sopr.sh

*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***


[064bit-prompt]> python3 -c "import sys, hashlib as hl, _md5, ssl;print(\"{0:}\n{1:}\n{2:}\n{3:}\".format(sys.version, _md5, hl._hashlib, ssl.OPENSSL_VERSION))"

3.5.2 (default, Oct  8 2019, 13:06:37)

[GCC 5.4.0 20160609]

<module '_md5' (built-in)>

<module '_hashlib' from '/usr/lib/python3.5/lib-dynload/_hashlib.cpython-35m-x86_64-linux-gnu.so'>

OpenSSL 1.0.2g  1 Mar 2016

[064bit-prompt]>

[064bit-prompt]> ldd /usr/lib/python3.5/lib-dynload/_hashlib.cpython-35m-x86_64-linux-gnu.so

        linux-vdso.so.1 =>  (0x00007fffa7d0b000)

        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f50d9e4d000)

        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f50d9a83000)

        libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f50d963e000)

        /lib64/ld-linux-x86-64.so.2 (0x00007f50da271000)

        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f50d943a000)

[064bit-prompt]>

[064bit-prompt]> openssl version -a

OpenSSL 1.0.2g  1 Mar 2016

built on: reproducible build, date unspecified

platform: debian-amd64

options:  bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)

compiler: cc -I. -I.. -I../include  -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM

OPENSSLDIR: "/usr/lib/ssl"

[064bit-prompt]>

[064bit-prompt]> python3 -c "import _md5, hashlib as hl;print(_md5.md5(b\"A\").hexdigest(), hl.md5(b\"A\").hexdigest())"

7fc56270e7a70fa81a5935b72eacbe29 7fc56270e7a70fa81a5935b72eacbe29

根據(jù)[Python 3.Docs]:hashlib。算法保證:


包含哈希算法名稱的集合,保證在所有平臺(tái)上都受此模塊支持。請(qǐng)注意,盡管一些上游供應(yīng)商提供了一個(gè)奇怪的“FIPS 兼容”Python 構(gòu)建,但排除了它,但“md5”仍在此列表中。


下面是一個(gè)自定義Python 2.7安裝的示例(我很久以前構(gòu)建的,值得一提的是它動(dòng)態(tài)鏈接到OpenSSL .dll):


e:\Work\Dev\StackOverflow\q059955854>sopr.bat

*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***


[prompt]> "F:\Install\pc064\HPE\OPSWpython\2.7.10__00\python.exe" -c "import sys, ssl;print(\"{0:}\n{1:}\".format(sys.version, ssl.OPENSSL_VERSION))"

2.7.10 (default, Mar  8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]

OpenSSL 1.0.2j-fips  26 Sep 2016


[prompt]> "F:\Install\pc064\HPE\OPSWpython\2.7.10__00\python.exe" -c "import hashlib as hl;print(hl.md5(\"A\").hexdigest())"

7fc56270e7a70fa81a5935b72eacbe29


[prompt]> "F:\Install\pc064\HPE\OPSWpython\2.7.10__00\python.exe" -c "import ssl;ssl.FIPS_mode_set(True);import hashlib as hl;print(hl.md5(\"A\").hexdigest())"

Traceback (most recent call last):

  File "<string>", line 1, in <module>

ValueError: error:060A80A3:digital envelope routines:FIPS_DIGESTINIT:disabled for fips

至于速度問題我只能推測(cè):


Python實(shí)現(xiàn)(顯然)是專門為Python編寫的,這意味著它對(duì)于Python比通用版本“更優(yōu)化”(是的,這在語法上是不正確的) ,并且還駐留在python*.so(或python可執(zhí)行文件本身)中

OpenSSL實(shí)現(xiàn)駐留在libcrypto*.so中,它被包裝器_hashlib.so訪問,它在Python類型 ( PyObject* ) 和OpenSSL類型( EVP_MD_CTX* )之間進(jìn)行來回轉(zhuǎn)換

考慮到上述情況,前者(稍微)更快是有道理的(至少對(duì)于小消息,其中開銷(函數(shù)調(diào)用和其他Python底層操作)與散列本身相比占總時(shí)間的很大一部分)。還有其他因素需要考慮(例如,是否使用了OpenSSL匯編器加速)。




更新#0

以下是我自己的一些基準(zhǔn)。


code00.py:


#!/usr/bin/env python


import sys

from hashlib import md5 as md5_openssl

from _md5 import md5 as md5_builtin

import timeit



def main(*argv):

    base_text = b"A"

    number = 1000000

    print("timeit attempts number: {0:d}".format(number))

    #x = []

    #y = {}

    for count in range(0, 16):

        factor = 2 ** count

        text = base_text * factor

        globals_dict = {"text": text}

        #x.append(factor)

        print("\nUsing a {0:8d} (2 ** {1:2d}) bytes message".format(len(text), count))

        for func in [

            md5_openssl,

            md5_builtin,

        ]:

            globals_dict["md5"] = func


            t = timeit.timeit(stmt="md5(text)", globals=globals_dict, number=number)

            print("    {0:12s} took: {1:11.6f} seconds".format(func.__name__, t))

            #y.setdefault(func.__name__, []).append(t)

    #print(x, y)



if __name__ == "__main__":

    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))

    main(*sys.argv[1:])

    print("\nDone.")

輸出:


Win 10 pc064(在戴爾 Precision 5510筆記本電腦上運(yùn)行):


[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py

Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32


timeit attempts number: 1000000


Using a        1 (2 **  0) bytes message

    openssl_md5  took:    0.449134 seconds

    md5          took:    0.120021 seconds


Using a        2 (2 **  1) bytes message

    openssl_md5  took:    0.460399 seconds

    md5          took:    0.118555 seconds


Using a        4 (2 **  2) bytes message

    openssl_md5  took:    0.451850 seconds

    md5          took:    0.121166 seconds


Using a        8 (2 **  3) bytes message

    openssl_md5  took:    0.438398 seconds

    md5          took:    0.118127 seconds


Using a       16 (2 **  4) bytes message

    openssl_md5  took:    0.454653 seconds

    md5          took:    0.122818 seconds


Using a       32 (2 **  5) bytes message

    openssl_md5  took:    0.450776 seconds

    md5          took:    0.118594 seconds


Using a       64 (2 **  6) bytes message

    openssl_md5  took:    0.555761 seconds

    md5          took:    0.278812 seconds


Using a      128 (2 **  7) bytes message

    openssl_md5  took:    0.681296 seconds

    md5          took:    0.455921 seconds


Using a      256 (2 **  8) bytes message

    openssl_md5  took:    0.895952 seconds

    md5          took:    0.807457 seconds


Using a      512 (2 **  9) bytes message

    openssl_md5  took:    1.401584 seconds

    md5          took:    1.499279 seconds


Using a     1024 (2 ** 10) bytes message

    openssl_md5  took:    2.360966 seconds

    md5          took:    2.878650 seconds


Using a     2048 (2 ** 11) bytes message

    openssl_md5  took:    4.383245 seconds

    md5          took:    5.655477 seconds


Using a     4096 (2 ** 12) bytes message

    openssl_md5  took:    8.264774 seconds

    md5          took:   10.920909 seconds


Using a     8192 (2 ** 13) bytes message

    openssl_md5  took:   15.521947 seconds

    md5          took:   21.895179 seconds


Using a    16384 (2 ** 14) bytes message

    openssl_md5  took:   29.947287 seconds

    md5          took:   43.198639 seconds


Using a    32768 (2 ** 15) bytes message

    openssl_md5  took:   59.123447 seconds

    md5          took:   86.453821 seconds


Done.

Ubtu 16 pc064(在上述機(jī)器上的VirtualBox中運(yùn)行的VM ):


[064bit-prompt]> python3 code00.py

Python 3.5.2 (default, Oct  8 2019, 13:06:37) [GCC 5.4.0 20160609] 64bit on linux


timeit attempts number: 1000000


Using a        1 (2 **  0) bytes message

    openssl_md5  took:    0.246166 seconds

    md5          took:    0.130589 seconds


Using a        2 (2 **  1) bytes message

    openssl_md5  took:    0.251019 seconds

    md5          took:    0.127750 seconds


Using a        4 (2 **  2) bytes message

    openssl_md5  took:    0.257018 seconds

    md5          took:    0.123116 seconds


Using a        8 (2 **  3) bytes message

    openssl_md5  took:    0.245399 seconds

    md5          took:    0.128267 seconds


Using a       16 (2 **  4) bytes message

    openssl_md5  took:    0.251832 seconds

    md5          took:    0.136373 seconds


Using a       32 (2 **  5) bytes message

    openssl_md5  took:    0.248410 seconds

    md5          took:    0.140708 seconds


Using a       64 (2 **  6) bytes message

    openssl_md5  took:    0.361016 seconds

    md5          took:    0.267021 seconds


Using a      128 (2 **  7) bytes message

    openssl_md5  took:    0.478735 seconds

    md5          took:    0.413986 seconds


Using a      256 (2 **  8) bytes message

    openssl_md5  took:    0.707602 seconds

    md5          took:    0.695042 seconds


Using a      512 (2 **  9) bytes message

    openssl_md5  took:    1.216832 seconds

    md5          took:    1.268570 seconds


Using a     1024 (2 ** 10) bytes message

    openssl_md5  took:    2.122014 seconds

    md5          took:    2.429623 seconds


Using a     2048 (2 ** 11) bytes message

    openssl_md5  took:    4.158188 seconds

    md5          took:    4.847686 seconds


Using a     4096 (2 ** 12) bytes message

    openssl_md5  took:    7.839173 seconds

    md5          took:    9.242224 seconds


Using a     8192 (2 ** 13) bytes message

    openssl_md5  took:   15.282232 seconds

    md5          took:   18.368874 seconds


Using a    16384 (2 ** 14) bytes message

    openssl_md5  took:   30.681912 seconds

    md5          took:   36.755073 seconds


Using a    32768 (2 ** 15) bytes message

    openssl_md5  took:   60.230543 seconds

    md5          took:   73.237356 seconds


Done.

結(jié)果似乎與你的完全不同。就我而言:


從 [~ 512B .. ~ 1KiB ] 大小的消息開始,OpenSSL實(shí)現(xiàn)似乎比內(nèi)置的執(zhí)行得更好

我知道聲明模式的結(jié)果太少,但似乎兩種實(shí)現(xiàn)似乎與消息大小成線性比例(就時(shí)間而言)(但內(nèi)置斜率似乎有點(diǎn)陡峭 - 這意味著它會(huì)表現(xiàn)更差從長(zhǎng)遠(yuǎn)來看)

總而言之,如果您的所有消息都很小,并且內(nèi)置實(shí)現(xiàn)最適合您,那么請(qǐng)使用它。


查看完整回答
反對(duì) 回復(fù) 2022-07-12
?
慕斯王

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超2個(gè)贊

Python 公共模塊將方法委托給隱藏模塊是很常見的。


例如,該collections.abc模塊的完整代碼為:


from _collections_abc import *

from _collections_abc import __all__

的函數(shù)hashlib是動(dòng)態(tài)創(chuàng)建的:


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)

的定義always_supported是:


__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',

                      'blake2b', 'blake2s',

                      'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',

                      'shake_128', 'shake_256')

get_hash或者:___get_openssl_constructor ___get_builtin_constructor


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

__get_builtin_constructor是(再次)隱藏_hashlib模塊的后備:


def __get_openssl_constructor(name):

    if name in __block_openssl_constructor:

        # Prefer our blake2 and sha3 implementation.

        return __get_builtin_constructor(name)

    try:

        f = getattr(_hashlib, 'openssl_' + name)

        # Allow the C module to raise ValueError.  The function will be

        # defined but the hash not actually available thanks to OpenSSL.

        f()

        # Use the C function directly (very fast)

        return f

    except (AttributeError, ValueError):

        return __get_builtin_constructor(name)

在上面的hashlib代碼中,你有這個(gè):


def __get_builtin_constructor(name):

    cache = __builtin_constructor_cache

    ...

    elif name in {'MD5', 'md5'}:

        import _md5

        cache['MD5'] = cache['md5'] = _md5.md5

But md5is not in __block_openssl_constructor,因此該_hashlib/openssl版本優(yōu)于該_md5/builtin版本:


REPL 中的確認(rèn):


>>> hashlib.md5

<built-in function openssl_md5>

>>> _md5.md5

<built-in function md5>

這些函數(shù)是 MD5 算法的不同實(shí)現(xiàn),它們openssl_md5調(diào)用動(dòng)態(tài)系統(tǒng)庫。這就是為什么你有一些性能變化。第一個(gè)版本在https://github.com/python/cpython/blob/master/Modules/_hashopenssl.c中定義,另一個(gè)在https://github.com/python/cpython/blob/master/Modules/md5module .c,如果你想檢查差異。


那為什么_md5.md5定義了函數(shù)但從未使用過?我想這個(gè)想法是確保某些算法始終可用,即使openssl不存在:


此模塊中始終存在的哈希算法的構(gòu)造函數(shù)是 sha1()、sha224()、sha256()、sha384()、sha512()、blake2b() 和 blake2s()。(https://docs.python.org/3/library/hashlib.html)


查看完整回答
反對(duì) 回復(fù) 2022-07-12
?
MMMHUHU

TA貢獻(xiàn)1834條經(jīng)驗(yàn) 獲得超8個(gè)贊

我在 bugs.python.org 上環(huán)顧四周并閱讀 cpython git 提交歷史的理論:

cpython 在 2005 年切換到 openssl md5,因?yàn)樗葍?nèi)置實(shí)現(xiàn)更快。他們?cè)?2007 年添加了一個(gè)新的內(nèi)置實(shí)現(xiàn),它比 openssl 更快,但從未切換回來。這兩項(xiàng)更改均由 Gregory P. Smith 完成。

這是我的證據(jù)。

  • 2005 年,Greg 創(chuàng)建了 bpo 問題“sha 和 md5 模塊應(yīng)盡可能使用 OpenSSL”。此提交中所做的更改。

  • 2007 年,Greg 在此提交中添加了新的快速 md5 模塊。

  • Python 3.8 中的_md5實(shí)現(xiàn)似乎基本相同(我正在查看提交 ea316fd21527)

我認(rèn)為 cpython 維護(hù)者可能會(huì)愿意切換回_md5它可用的時(shí)間,因?yàn)?openssl 實(shí)現(xiàn)更快不再是真的(過去 13 年可能是不真實(shí)的)。


查看完整回答
反對(duì) 回復(fù) 2022-07-12
  • 3 回答
  • 0 關(guān)注
  • 81 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)