Skip to content

Commit ec0f3b4

Browse files
authored
Merge pull request #7120 from youknowone/hashlib
Update hashlib from v3.14.3 and align _hashlib to CPython
2 parents 16c7439 + 12db02e commit ec0f3b4

File tree

18 files changed

+590
-262
lines changed

18 files changed

+590
-262
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/hashlib.py

Lines changed: 22 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
- hexdigest(): Like digest() except the digest is returned as a string
3434
of double length, containing only hexadecimal digits.
3535
- copy(): Return a copy (clone) of the hash object. This can be used to
36-
efficiently compute the digests of datas that share a common
36+
efficiently compute the digests of data that share a common
3737
initial substring.
3838
3939
For example, to obtain the digest of the byte string 'Nobody inspects the
@@ -65,7 +65,7 @@
6565
algorithms_available = set(__always_supported)
6666

6767
__all__ = __always_supported + ('new', 'algorithms_guaranteed',
68-
'algorithms_available', 'pbkdf2_hmac', 'file_digest')
68+
'algorithms_available', 'file_digest')
6969

7070

7171
__builtin_constructor_cache = {}
@@ -92,13 +92,13 @@ def __get_builtin_constructor(name):
9292
import _md5
9393
cache['MD5'] = cache['md5'] = _md5.md5
9494
elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}:
95-
import _sha256
96-
cache['SHA224'] = cache['sha224'] = _sha256.sha224
97-
cache['SHA256'] = cache['sha256'] = _sha256.sha256
95+
import _sha2
96+
cache['SHA224'] = cache['sha224'] = _sha2.sha224
97+
cache['SHA256'] = cache['sha256'] = _sha2.sha256
9898
elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}:
99-
import _sha512
100-
cache['SHA384'] = cache['sha384'] = _sha512.sha384
101-
cache['SHA512'] = cache['sha512'] = _sha512.sha512
99+
import _sha2
100+
cache['SHA384'] = cache['sha384'] = _sha2.sha384
101+
cache['SHA512'] = cache['sha512'] = _sha2.sha512
102102
elif name in {'blake2b', 'blake2s'}:
103103
import _blake2
104104
cache['blake2b'] = _blake2.blake2b
@@ -141,38 +141,37 @@ def __get_openssl_constructor(name):
141141
return __get_builtin_constructor(name)
142142

143143

144-
def __py_new(name, data=b'', **kwargs):
144+
def __py_new(name, *args, **kwargs):
145145
"""new(name, data=b'', **kwargs) - Return a new hashing object using the
146146
named algorithm; optionally initialized with data (which must be
147147
a bytes-like object).
148148
"""
149-
return __get_builtin_constructor(name)(data, **kwargs)
149+
return __get_builtin_constructor(name)(*args, **kwargs)
150150

151151

152-
def __hash_new(name, data=b'', **kwargs):
152+
def __hash_new(name, *args, **kwargs):
153153
"""new(name, data=b'') - Return a new hashing object using the named algorithm;
154154
optionally initialized with data (which must be a bytes-like object).
155155
"""
156156
if name in __block_openssl_constructor:
157157
# Prefer our builtin blake2 implementation.
158-
return __get_builtin_constructor(name)(data, **kwargs)
158+
return __get_builtin_constructor(name)(*args, **kwargs)
159159
try:
160-
return _hashlib.new(name, data, **kwargs)
160+
return _hashlib.new(name, *args, **kwargs)
161161
except ValueError:
162162
# If the _hashlib module (OpenSSL) doesn't support the named
163163
# hash, try using our builtin implementations.
164164
# This allows for SHA224/256 and SHA384/512 support even though
165165
# the OpenSSL library prior to 0.9.8 doesn't provide them.
166-
return __get_builtin_constructor(name)(data)
166+
return __get_builtin_constructor(name)(*args, **kwargs)
167167

168168

169169
try:
170170
import _hashlib
171171
new = __hash_new
172172
__get_hash = __get_openssl_constructor
173-
# TODO: RUSTPYTHON set in _hashlib instance PyFrozenSet algorithms_available
174-
'''algorithms_available = algorithms_available.union(
175-
_hashlib.openssl_md_meth_names)'''
173+
algorithms_available = algorithms_available.union(
174+
_hashlib.openssl_md_meth_names)
176175
except ImportError:
177176
_hashlib = None
178177
new = __py_new
@@ -181,76 +180,14 @@ def __hash_new(name, data=b'', **kwargs):
181180
try:
182181
# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
183182
from _hashlib import pbkdf2_hmac
183+
__all__ += ('pbkdf2_hmac',)
184184
except ImportError:
185-
from warnings import warn as _warn
186-
_trans_5C = bytes((x ^ 0x5C) for x in range(256))
187-
_trans_36 = bytes((x ^ 0x36) for x in range(256))
188-
189-
def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
190-
"""Password based key derivation function 2 (PKCS #5 v2.0)
191-
192-
This Python implementations based on the hmac module about as fast
193-
as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
194-
for long passwords.
195-
"""
196-
_warn(
197-
"Python implementation of pbkdf2_hmac() is deprecated.",
198-
category=DeprecationWarning,
199-
stacklevel=2
200-
)
201-
if not isinstance(hash_name, str):
202-
raise TypeError(hash_name)
203-
204-
if not isinstance(password, (bytes, bytearray)):
205-
password = bytes(memoryview(password))
206-
if not isinstance(salt, (bytes, bytearray)):
207-
salt = bytes(memoryview(salt))
208-
209-
# Fast inline HMAC implementation
210-
inner = new(hash_name)
211-
outer = new(hash_name)
212-
blocksize = getattr(inner, 'block_size', 64)
213-
if len(password) > blocksize:
214-
password = new(hash_name, password).digest()
215-
password = password + b'\x00' * (blocksize - len(password))
216-
inner.update(password.translate(_trans_36))
217-
outer.update(password.translate(_trans_5C))
218-
219-
def prf(msg, inner=inner, outer=outer):
220-
# PBKDF2_HMAC uses the password as key. We can re-use the same
221-
# digest objects and just update copies to skip initialization.
222-
icpy = inner.copy()
223-
ocpy = outer.copy()
224-
icpy.update(msg)
225-
ocpy.update(icpy.digest())
226-
return ocpy.digest()
227-
228-
if iterations < 1:
229-
raise ValueError(iterations)
230-
if dklen is None:
231-
dklen = outer.digest_size
232-
if dklen < 1:
233-
raise ValueError(dklen)
234-
235-
dkey = b''
236-
loop = 1
237-
from_bytes = int.from_bytes
238-
while len(dkey) < dklen:
239-
prev = prf(salt + loop.to_bytes(4))
240-
# endianness doesn't matter here as long to / from use the same
241-
rkey = from_bytes(prev)
242-
for i in range(iterations - 1):
243-
prev = prf(prev)
244-
# rkey = rkey ^ prev
245-
rkey ^= from_bytes(prev)
246-
loop += 1
247-
dkey += rkey.to_bytes(inner.digest_size)
248-
249-
return dkey[:dklen]
185+
pass
186+
250187

251188
try:
252189
# OpenSSL's scrypt requires OpenSSL 1.1+
253-
from _hashlib import scrypt
190+
from _hashlib import scrypt # noqa: F401
254191
except ImportError:
255192
pass
256193

@@ -294,6 +231,8 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
294231
view = memoryview(buf)
295232
while True:
296233
size = fileobj.readinto(buf)
234+
if size is None:
235+
raise BlockingIOError("I/O operation would block.")
297236
if size == 0:
298237
break # EOF
299238
digestobj.update(view[:size])

0 commit comments

Comments
 (0)