forked from Rust-related/RustPython
Merge pull request #4835 from Masorubka1/test_hashlib.py
Update test_hashlib.py from Cpython v3.11.2 & refactor hashlib
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -950,6 +950,15 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.53"
|
||||
@@ -2137,6 +2146,7 @@ dependencies = [
|
||||
"foreign-types-shared",
|
||||
"gethostname",
|
||||
"hex",
|
||||
"hmac",
|
||||
"itertools",
|
||||
"libc",
|
||||
"libsqlite3-sys",
|
||||
|
||||
316
Lib/hashlib.py
vendored
Normal file
316
Lib/hashlib.py
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
#. Copyright (C) 2005-2010 Gregory P. Smith (greg@krypto.org)
|
||||
# Licensed to PSF under a Contributor Agreement.
|
||||
#
|
||||
|
||||
__doc__ = """hashlib module - A common interface to many hash functions.
|
||||
|
||||
new(name, data=b'', **kwargs) - returns a new hash object implementing the
|
||||
given hash function; initializing the hash
|
||||
using the given binary data.
|
||||
|
||||
Named constructor functions are also available, these are faster
|
||||
than using new(name):
|
||||
|
||||
md5(), sha1(), sha224(), sha256(), sha384(), sha512(), blake2b(), blake2s(),
|
||||
sha3_224, sha3_256, sha3_384, sha3_512, shake_128, and shake_256.
|
||||
|
||||
More algorithms may be available on your platform but the above are guaranteed
|
||||
to exist. See the algorithms_guaranteed and algorithms_available attributes
|
||||
to find out what algorithm names can be passed to new().
|
||||
|
||||
NOTE: If you want the adler32 or crc32 hash functions they are available in
|
||||
the zlib module.
|
||||
|
||||
Choose your hash function wisely. Some have known collision weaknesses.
|
||||
sha384 and sha512 will be slow on 32 bit platforms.
|
||||
|
||||
Hash objects have these methods:
|
||||
- update(data): Update the hash object with the bytes in data. Repeated calls
|
||||
are equivalent to a single call with the concatenation of all
|
||||
the arguments.
|
||||
- digest(): Return the digest of the bytes passed to the update() method
|
||||
so far as a bytes object.
|
||||
- hexdigest(): Like digest() except the digest is returned as a string
|
||||
of double length, containing only hexadecimal digits.
|
||||
- copy(): Return a copy (clone) of the hash object. This can be used to
|
||||
efficiently compute the digests of datas that share a common
|
||||
initial substring.
|
||||
|
||||
For example, to obtain the digest of the byte string 'Nobody inspects the
|
||||
spammish repetition':
|
||||
|
||||
>>> import hashlib
|
||||
>>> m = hashlib.md5()
|
||||
>>> m.update(b"Nobody inspects")
|
||||
>>> m.update(b" the spammish repetition")
|
||||
>>> m.digest()
|
||||
b'\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9'
|
||||
|
||||
More condensed:
|
||||
|
||||
>>> hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest()
|
||||
'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
|
||||
|
||||
"""
|
||||
|
||||
# This tuple and __get_builtin_constructor() must be modified if a new
|
||||
# always available algorithm is added.
|
||||
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
|
||||
'blake2b', 'blake2s',
|
||||
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
||||
'shake_128', 'shake_256')
|
||||
|
||||
|
||||
algorithms_guaranteed = set(__always_supported)
|
||||
algorithms_available = set(__always_supported)
|
||||
|
||||
__all__ = __always_supported + ('new', 'algorithms_guaranteed',
|
||||
'algorithms_available', 'pbkdf2_hmac', 'file_digest')
|
||||
|
||||
|
||||
__builtin_constructor_cache = {}
|
||||
|
||||
# Prefer our blake2 implementation
|
||||
# OpenSSL 1.1.0 comes with a limited implementation of blake2b/s. The OpenSSL
|
||||
# implementations neither support keyed blake2 (blake2 MAC) nor advanced
|
||||
# features like salt, personalization, or tree hashing. OpenSSL hash-only
|
||||
# variants are available as 'blake2b512' and 'blake2s256', though.
|
||||
__block_openssl_constructor = {
|
||||
'blake2b', 'blake2s',
|
||||
}
|
||||
|
||||
def __get_builtin_constructor(name):
|
||||
cache = __builtin_constructor_cache
|
||||
constructor = cache.get(name)
|
||||
if constructor is not None:
|
||||
return constructor
|
||||
try:
|
||||
if name in {'SHA1', 'sha1'}:
|
||||
import _sha1
|
||||
cache['SHA1'] = cache['sha1'] = _sha1.sha1
|
||||
elif name in {'MD5', 'md5'}:
|
||||
import _md5
|
||||
cache['MD5'] = cache['md5'] = _md5.md5
|
||||
elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}:
|
||||
import _sha256
|
||||
cache['SHA224'] = cache['sha224'] = _sha256.sha224
|
||||
cache['SHA256'] = cache['sha256'] = _sha256.sha256
|
||||
elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}:
|
||||
import _sha512
|
||||
cache['SHA384'] = cache['sha384'] = _sha512.sha384
|
||||
cache['SHA512'] = cache['sha512'] = _sha512.sha512
|
||||
elif name in {'blake2b', 'blake2s'}:
|
||||
import _blake2
|
||||
cache['blake2b'] = _blake2.blake2b
|
||||
cache['blake2s'] = _blake2.blake2s
|
||||
elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
|
||||
import _sha3
|
||||
cache['sha3_224'] = _sha3.sha3_224
|
||||
cache['sha3_256'] = _sha3.sha3_256
|
||||
cache['sha3_384'] = _sha3.sha3_384
|
||||
cache['sha3_512'] = _sha3.sha3_512
|
||||
elif name in {'shake_128', 'shake_256'}:
|
||||
import _sha3
|
||||
cache['shake_128'] = _sha3.shake_128
|
||||
cache['shake_256'] = _sha3.shake_256
|
||||
except ImportError:
|
||||
pass # no extension module, this hash is unsupported.'''
|
||||
|
||||
constructor = cache.get(name)
|
||||
if constructor is not None:
|
||||
return constructor
|
||||
|
||||
raise ValueError('unsupported hash type ' + name)
|
||||
|
||||
|
||||
def __get_openssl_constructor(name):
|
||||
if name in __block_openssl_constructor:
|
||||
# Prefer our builtin blake2 implementation.
|
||||
return __get_builtin_constructor(name)
|
||||
try:
|
||||
# MD5, SHA1, and SHA2 are in all supported OpenSSL versions
|
||||
# SHA3/shake are available in OpenSSL 1.1.1+
|
||||
f = getattr(_hashlib, 'openssl_' + name)
|
||||
# Allow the C module to raise ValueError. The function will be
|
||||
# defined but the hash not actually available. Don't fall back to
|
||||
# builtin if the current security policy blocks a digest, bpo#40695.
|
||||
f(usedforsecurity=False)
|
||||
# Use the C function directly (very fast)
|
||||
return f
|
||||
except (AttributeError, ValueError):
|
||||
return __get_builtin_constructor(name)
|
||||
|
||||
|
||||
def __py_new(name, data=b'', **kwargs):
|
||||
"""new(name, data=b'', **kwargs) - Return a new hashing object using the
|
||||
named algorithm; optionally initialized with data (which must be
|
||||
a bytes-like object).
|
||||
"""
|
||||
return __get_builtin_constructor(name)(data, **kwargs)
|
||||
|
||||
|
||||
def __hash_new(name, data=b'', **kwargs):
|
||||
"""new(name, data=b'') - Return a new hashing object using the named algorithm;
|
||||
optionally initialized with data (which must be a bytes-like object).
|
||||
"""
|
||||
if name in __block_openssl_constructor:
|
||||
# Prefer our builtin blake2 implementation.
|
||||
return __get_builtin_constructor(name)(data, **kwargs)
|
||||
try:
|
||||
return _hashlib.new(name, data, **kwargs)
|
||||
except ValueError:
|
||||
# If the _hashlib module (OpenSSL) doesn't support the named
|
||||
# hash, try using our builtin implementations.
|
||||
# This allows for SHA224/256 and SHA384/512 support even though
|
||||
# the OpenSSL library prior to 0.9.8 doesn't provide them.
|
||||
return __get_builtin_constructor(name)(data)
|
||||
|
||||
|
||||
try:
|
||||
import _hashlib
|
||||
new = __hash_new
|
||||
__get_hash = __get_openssl_constructor
|
||||
# TODO: RUSTPYTHON set in _hashlib instance PyFrozenSet algorithms_available
|
||||
'''algorithms_available = algorithms_available.union(
|
||||
_hashlib.openssl_md_meth_names)'''
|
||||
except ImportError:
|
||||
_hashlib = None
|
||||
new = __py_new
|
||||
__get_hash = __get_builtin_constructor
|
||||
|
||||
try:
|
||||
# OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
|
||||
from _hashlib import pbkdf2_hmac
|
||||
except ImportError:
|
||||
from warnings import warn as _warn
|
||||
_trans_5C = bytes((x ^ 0x5C) for x in range(256))
|
||||
_trans_36 = bytes((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.
|
||||
"""
|
||||
_warn(
|
||||
"Python implementation of pbkdf2_hmac() is deprecated.",
|
||||
category=DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
if not isinstance(hash_name, str):
|
||||
raise TypeError(hash_name)
|
||||
|
||||
if not isinstance(password, (bytes, bytearray)):
|
||||
password = bytes(memoryview(password))
|
||||
if not isinstance(salt, (bytes, bytearray)):
|
||||
salt = bytes(memoryview(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)
|
||||
|
||||
dkey = b''
|
||||
loop = 1
|
||||
from_bytes = int.from_bytes
|
||||
while len(dkey) < dklen:
|
||||
prev = prf(salt + loop.to_bytes(4))
|
||||
# endianness doesn't matter here as long to / from use the same
|
||||
rkey = from_bytes(prev)
|
||||
for i in range(iterations - 1):
|
||||
prev = prf(prev)
|
||||
# rkey = rkey ^ prev
|
||||
rkey ^= from_bytes(prev)
|
||||
loop += 1
|
||||
dkey += rkey.to_bytes(inner.digest_size)
|
||||
|
||||
return dkey[:dklen]
|
||||
|
||||
try:
|
||||
# OpenSSL's scrypt requires OpenSSL 1.1+
|
||||
from _hashlib import scrypt
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def file_digest(fileobj, digest, /, *, _bufsize=2**18):
|
||||
"""Hash the contents of a file-like object. Returns a digest object.
|
||||
|
||||
*fileobj* must be a file-like object opened for reading in binary mode.
|
||||
It accepts file objects from open(), io.BytesIO(), and SocketIO objects.
|
||||
The function may bypass Python's I/O and use the file descriptor *fileno*
|
||||
directly.
|
||||
|
||||
*digest* must either be a hash algorithm name as a *str*, a hash
|
||||
constructor, or a callable that returns a hash object.
|
||||
"""
|
||||
# On Linux we could use AF_ALG sockets and sendfile() to archive zero-copy
|
||||
# hashing with hardware acceleration.
|
||||
if isinstance(digest, str):
|
||||
digestobj = new(digest)
|
||||
else:
|
||||
digestobj = digest()
|
||||
|
||||
if hasattr(fileobj, "getbuffer"):
|
||||
# io.BytesIO object, use zero-copy buffer
|
||||
digestobj.update(fileobj.getbuffer())
|
||||
return digestobj
|
||||
|
||||
# Only binary files implement readinto().
|
||||
if not (
|
||||
hasattr(fileobj, "readinto")
|
||||
and hasattr(fileobj, "readable")
|
||||
and fileobj.readable()
|
||||
):
|
||||
raise ValueError(
|
||||
f"'{fileobj!r}' is not a file-like object in binary reading mode."
|
||||
)
|
||||
|
||||
# binary file, socket.SocketIO object
|
||||
# Note: socket I/O uses different syscalls than file I/O.
|
||||
buf = bytearray(_bufsize) # Reusable buffer to reduce allocations.
|
||||
view = memoryview(buf)
|
||||
while True:
|
||||
size = fileobj.readinto(buf)
|
||||
if size == 0:
|
||||
break # EOF
|
||||
digestobj.update(view[:size])
|
||||
|
||||
return digestobj
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# Cleanup locals()
|
||||
del __always_supported, __func_name, __get_hash
|
||||
del __py_new, __hash_new, __get_openssl_constructor
|
||||
4
Lib/test/test_enum.py
vendored
4
Lib/test/test_enum.py
vendored
@@ -2889,9 +2889,7 @@ class TestIntFlag(unittest.TestCase):
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipIf(sys.platform == "win32", "TODO: RUSTPYTHON, inconsistent test result on Windows due to threading")
|
||||
@unittest.skip("TODO: RUSTPYTHON, inconsistent test result due to threading")
|
||||
@threading_helper.reap_threads
|
||||
def test_unique_composite(self):
|
||||
# override __eq__ to be identity only
|
||||
|
||||
84
Lib/test/test_hashlib.py
vendored
84
Lib/test/test_hashlib.py
vendored
@@ -10,6 +10,7 @@ import array
|
||||
from binascii import unhexlify
|
||||
import hashlib
|
||||
import importlib
|
||||
import io
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
@@ -20,6 +21,7 @@ import warnings
|
||||
from test import support
|
||||
from test.support import _4G, bigmemtest
|
||||
from test.support.import_helper import import_fresh_module
|
||||
from test.support import os_helper
|
||||
from test.support import threading_helper
|
||||
from test.support import warnings_helper
|
||||
from http.client import HTTPException
|
||||
@@ -102,8 +104,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
'sha384', 'SHA384', 'sha512', 'SHA512',
|
||||
'blake2b', 'blake2s',
|
||||
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
||||
'shake_128', 'shake_256'
|
||||
)
|
||||
'shake_128', 'shake_256')
|
||||
|
||||
shakes = {'shake_128', 'shake_256'}
|
||||
|
||||
@@ -214,15 +215,11 @@ class HashLibTestCase(unittest.TestCase):
|
||||
else:
|
||||
c.hexdigest()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_algorithms_guaranteed(self):
|
||||
self.assertEqual(hashlib.algorithms_guaranteed,
|
||||
set(_algo for _algo in self.supported_hash_names
|
||||
if _algo.islower()))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_algorithms_available(self):
|
||||
self.assertTrue(set(hashlib.algorithms_guaranteed).
|
||||
issubset(hashlib.algorithms_available))
|
||||
@@ -262,8 +259,6 @@ class HashLibTestCase(unittest.TestCase):
|
||||
def test_new_upper_to_lower(self):
|
||||
self.assertEqual(hashlib.new("SHA256").name, "sha256")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_get_builtin_constructor(self):
|
||||
get_builtin_constructor = getattr(hashlib,
|
||||
'__get_builtin_constructor')
|
||||
@@ -384,6 +379,39 @@ class HashLibTestCase(unittest.TestCase):
|
||||
if not shake:
|
||||
self.assertEqual(len(digest), m.digest_size)
|
||||
|
||||
if not shake and kwargs.get("key") is None:
|
||||
# skip shake and blake2 extended parameter tests
|
||||
self.check_file_digest(name, data, hexdigest)
|
||||
|
||||
def check_file_digest(self, name, data, hexdigest):
|
||||
hexdigest = hexdigest.lower()
|
||||
try:
|
||||
hashlib.new(name)
|
||||
except ValueError:
|
||||
# skip, algorithm is blocked by security policy.
|
||||
return
|
||||
digests = [name]
|
||||
digests.extend(self.constructors_to_test[name])
|
||||
|
||||
with open(os_helper.TESTFN, "wb") as f:
|
||||
f.write(data)
|
||||
|
||||
try:
|
||||
for digest in digests:
|
||||
buf = io.BytesIO(data)
|
||||
buf.seek(0)
|
||||
'''self.assertEqual(
|
||||
dir(hashlib), None
|
||||
)'''
|
||||
self.assertEqual(
|
||||
hashlib.file_digest(buf, digest).hexdigest(), hexdigest
|
||||
)
|
||||
with open(os_helper.TESTFN, "rb") as f:
|
||||
digestobj = hashlib.file_digest(f, digest)
|
||||
self.assertEqual(digestobj.hexdigest(), hexdigest)
|
||||
finally:
|
||||
os.unlink(os_helper.TESTFN)
|
||||
|
||||
def check_no_unicode(self, algorithm_name):
|
||||
# Unicode objects are not allowed as input.
|
||||
constructors = self.constructors_to_test[algorithm_name]
|
||||
@@ -475,6 +503,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.check_sha3('shake_128', 256, 1344, b'\x1f')
|
||||
self.check_sha3('shake_256', 512, 1088, b'\x1f')
|
||||
|
||||
# TODO: RUSTPYTHON implement all blake2 params
|
||||
@unittest.expectedFailure
|
||||
@requires_blake2
|
||||
def test_blocksize_name_blake2(self):
|
||||
self.check_blocksize_name('blake2b', 128, 64)
|
||||
@@ -718,6 +748,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
outer.update(keyed.digest())
|
||||
return outer.hexdigest()
|
||||
|
||||
# TODO: RUSTPYTHON add to constructor const value
|
||||
@unittest.expectedFailure
|
||||
@requires_blake2
|
||||
def test_blake2b(self):
|
||||
self.check_blake2(hashlib.blake2b, 16, 16, 64, 64, (1<<64)-1)
|
||||
@@ -739,6 +771,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"+
|
||||
"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")
|
||||
|
||||
# TODO: RUSTPYTHON implement all blake2 fields
|
||||
@unittest.expectedFailure
|
||||
@requires_blake2
|
||||
def test_case_blake2b_all_parameters(self):
|
||||
# This checks that all the parameters work in general, and also that
|
||||
@@ -763,6 +797,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
key = bytes.fromhex(key)
|
||||
self.check('blake2b', msg, md, key=key)
|
||||
|
||||
# TODO: RUSTPYTHON add to constructor const value
|
||||
@unittest.expectedFailure
|
||||
@requires_blake2
|
||||
def test_blake2s(self):
|
||||
self.check_blake2(hashlib.blake2s, 8, 8, 32, 32, (1<<48)-1)
|
||||
@@ -782,6 +818,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.check('blake2s', b"abc",
|
||||
"508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982")
|
||||
|
||||
# TODO: RUSTPYTHON implement all blake2 fields
|
||||
@unittest.expectedFailure
|
||||
@requires_blake2
|
||||
def test_case_blake2s_all_parameters(self):
|
||||
# This checks that all the parameters work in general, and also that
|
||||
@@ -898,6 +936,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
)
|
||||
|
||||
@threading_helper.reap_threads
|
||||
@threading_helper.requires_working_threading()
|
||||
def test_threaded_hashing(self):
|
||||
# Updating the same hash object from several threads at once
|
||||
# using data chunk sizes containing the same byte sequences.
|
||||
@@ -1136,12 +1175,37 @@ class KDFTests(unittest.TestCase):
|
||||
hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1,
|
||||
dklen=dklen)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_normalized_name(self):
|
||||
self.assertNotIn("blake2b512", hashlib.algorithms_available)
|
||||
self.assertNotIn("sha3-512", hashlib.algorithms_available)
|
||||
|
||||
def test_file_digest(self):
|
||||
data = b'a' * 65536
|
||||
d1 = hashlib.sha256()
|
||||
self.addCleanup(os.unlink, os_helper.TESTFN)
|
||||
with open(os_helper.TESTFN, "wb") as f:
|
||||
for _ in range(10):
|
||||
d1.update(data)
|
||||
f.write(data)
|
||||
|
||||
with open(os_helper.TESTFN, "rb") as f:
|
||||
d2 = hashlib.file_digest(f, hashlib.sha256)
|
||||
|
||||
self.assertEqual(d1.hexdigest(), d2.hexdigest())
|
||||
self.assertEqual(d1.name, d2.name)
|
||||
self.assertIs(type(d1), type(d2))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
hashlib.file_digest(None, "sha256")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
with open(os_helper.TESTFN, "r") as f:
|
||||
hashlib.file_digest(f, "sha256")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
with open(os_helper.TESTFN, "wb") as f:
|
||||
hashlib.file_digest(f, "sha256")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
42
Lib/test/test_hmac.py
vendored
42
Lib/test/test_hmac.py
vendored
@@ -39,6 +39,8 @@ def ignore_warning(func):
|
||||
|
||||
class TestVectorsTestCase(unittest.TestCase):
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def assert_hmac_internals(
|
||||
self, h, digest, hashname, digest_size, block_size
|
||||
):
|
||||
@@ -48,6 +50,8 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||
self.assertEqual(h.digest_size, digest_size)
|
||||
self.assertEqual(h.block_size, block_size)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def assert_hmac(
|
||||
self, key, data, digest, hashfunc, hashname, digest_size, block_size
|
||||
):
|
||||
@@ -122,6 +126,8 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||
h, digest, hashname, digest_size, block_size
|
||||
)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('md5', openssl=True)
|
||||
def test_md5_vectors(self):
|
||||
# Test the HMAC module against test vectors from the RFC.
|
||||
@@ -164,6 +170,8 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||
b"and Larger Than One Block-Size Data"),
|
||||
"6f630fad67cda0ee1fb1f562db3aa53e")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha1', openssl=True)
|
||||
def test_sha_vectors(self):
|
||||
def shatest(key, data, digest):
|
||||
@@ -323,18 +331,26 @@ class TestVectorsTestCase(unittest.TestCase):
|
||||
'134676fb6de0446065c97440fa8c6a58',
|
||||
})
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha224', openssl=True)
|
||||
def test_sha224_rfc4231(self):
|
||||
self._rfc4231_test_cases(hashlib.sha224, 'sha224', 28, 64)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256', openssl=True)
|
||||
def test_sha256_rfc4231(self):
|
||||
self._rfc4231_test_cases(hashlib.sha256, 'sha256', 32, 64)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha384', openssl=True)
|
||||
def test_sha384_rfc4231(self):
|
||||
self._rfc4231_test_cases(hashlib.sha384, 'sha384', 48, 128)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha512', openssl=True)
|
||||
def test_sha512_rfc4231(self):
|
||||
self._rfc4231_test_cases(hashlib.sha512, 'sha512', 64, 128)
|
||||
@@ -380,6 +396,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
"6c845b47f52b3b47f6590c502db7825aad757bf4fadc8fa972f7cd2e76a5bdeb"
|
||||
)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_normal(self):
|
||||
# Standard constructor call.
|
||||
@@ -402,6 +420,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
h = hmac.new("key", digestmod='sha256')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_withtext(self):
|
||||
# Constructor call with text.
|
||||
@@ -411,6 +431,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
self.fail("Constructor call with text argument raised exception.")
|
||||
self.assertEqual(h.hexdigest(), self.expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_with_bytearray(self):
|
||||
try:
|
||||
@@ -420,6 +442,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
self.fail("Constructor call with bytearray arguments raised exception.")
|
||||
self.assertEqual(h.hexdigest(), self.expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_with_memoryview_msg(self):
|
||||
try:
|
||||
@@ -428,6 +452,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
self.fail("Constructor call with memoryview msg raised exception.")
|
||||
self.assertEqual(h.hexdigest(), self.expected)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_withmodule(self):
|
||||
# Constructor call with text and digest module.
|
||||
@@ -436,6 +462,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
except Exception:
|
||||
self.fail("Constructor call with hashlib.sha256 raised exception.")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipUnless(C_HMAC is not None, 'need _hashlib')
|
||||
def test_internal_types(self):
|
||||
# internal types like _hashlib.C_HMAC are not constructable
|
||||
@@ -443,6 +471,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
with self.assertRaisesRegex(TypeError, "immutable type"):
|
||||
C_HMAC.value = None
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipUnless(sha256_module is not None, 'need _sha256')
|
||||
def test_with_sha256_module(self):
|
||||
h = hmac.HMAC(b"key", b"hash this!", digestmod=sha256_module.sha256)
|
||||
@@ -455,6 +485,8 @@ class ConstructorTestCase(unittest.TestCase):
|
||||
|
||||
class SanityTestCase(unittest.TestCase):
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_exercise_all_methods(self):
|
||||
# Exercising all methods once.
|
||||
@@ -496,6 +528,8 @@ class CopyTestCase(unittest.TestCase):
|
||||
"No real copy of the attribute 'outer'.")
|
||||
self.assertIs(h1._hmac, None)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipIf(_hashopenssl is None, "test requires _hashopenssl")
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_realcopy_hmac(self):
|
||||
@@ -504,6 +538,8 @@ class CopyTestCase(unittest.TestCase):
|
||||
h2 = h1.copy()
|
||||
self.assertTrue(id(h1._hmac) != id(h2._hmac))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_equality(self):
|
||||
# Testing if the copy has the same digests.
|
||||
@@ -515,6 +551,8 @@ class CopyTestCase(unittest.TestCase):
|
||||
self.assertEqual(h1.hexdigest(), h2.hexdigest(),
|
||||
"Hexdigest of copy doesn't match original hexdigest.")
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@hashlib_helper.requires_hashdigest('sha256')
|
||||
def test_equality_new(self):
|
||||
# Testing if the copy has the same digests with hmac.new().
|
||||
@@ -532,6 +570,8 @@ class CopyTestCase(unittest.TestCase):
|
||||
|
||||
class CompareDigestTestCase(unittest.TestCase):
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_hmac_compare_digest(self):
|
||||
self._test_compare_digest(hmac.compare_digest)
|
||||
if openssl_compare_digest is not None:
|
||||
@@ -542,6 +582,8 @@ class CompareDigestTestCase(unittest.TestCase):
|
||||
def test_operator_compare_digest(self):
|
||||
self._test_compare_digest(operator_compare_digest)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipIf(openssl_compare_digest is None, "test requires _hashlib")
|
||||
def test_openssl_compare_digest(self):
|
||||
self._test_compare_digest(openssl_compare_digest)
|
||||
|
||||
@@ -55,6 +55,7 @@ sha-1 = "0.10.0"
|
||||
sha2 = "0.10.2"
|
||||
sha3 = "0.10.1"
|
||||
blake2 = "0.10.4"
|
||||
hmac = "0.12.1"
|
||||
|
||||
## unicode stuff
|
||||
unicode_names2 = { workspace = true }
|
||||
|
||||
19
stdlib/src/blake2.rs
Normal file
19
stdlib/src/blake2.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
// spell-checker:ignore usedforsecurity HASHXOF
|
||||
|
||||
pub(crate) use _blake2::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _blake2 {
|
||||
use crate::hashlib::_hashlib::{local_blake2b, local_blake2s, BlakeHashArgs};
|
||||
use crate::vm::{PyPayload, PyResult, VirtualMachine};
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2b(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_blake2b(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2s(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_blake2s(args).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
// spell-checker:ignore usedforsecurity HASHXOF
|
||||
|
||||
pub(crate) use hashlib::make_module;
|
||||
pub(crate) use _hashlib::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod hashlib {
|
||||
pub mod _hashlib {
|
||||
use crate::common::lock::PyRwLock;
|
||||
use crate::vm::{
|
||||
builtins::{PyBytes, PyStrRef, PyTypeRef},
|
||||
function::{ArgBytesLike, FuncArgs, OptionalArg},
|
||||
convert::ToPyObject,
|
||||
function::{ArgBytesLike, ArgStrOrBytesLike, FuncArgs, OptionalArg},
|
||||
protocol::PyBuffer,
|
||||
PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
};
|
||||
use blake2::{Blake2b512, Blake2s256};
|
||||
@@ -19,24 +21,22 @@ mod hashlib {
|
||||
use sha2::{Sha224, Sha256, Sha384, Sha512};
|
||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
|
||||
|
||||
#[derive(FromArgs, Traverse)]
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[allow(unused)]
|
||||
struct NewHashArgs {
|
||||
#[pyarg(positional)]
|
||||
name: PyStrRef,
|
||||
#[pyarg(any, optional)]
|
||||
data: OptionalArg<ArgBytesLike>,
|
||||
#[pytraverse(skip)]
|
||||
#[pyarg(named, default = "true")]
|
||||
usedforsecurity: bool,
|
||||
}
|
||||
|
||||
#[derive(FromArgs, Traverse)]
|
||||
#[derive(FromArgs)]
|
||||
#[allow(unused)]
|
||||
struct BlakeHashArgs {
|
||||
pub struct BlakeHashArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
data: OptionalArg<ArgBytesLike>,
|
||||
#[pytraverse(skip)]
|
||||
pub data: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = "true")]
|
||||
usedforsecurity: bool,
|
||||
}
|
||||
@@ -50,12 +50,11 @@ mod hashlib {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs, Traverse)]
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[allow(unused)]
|
||||
struct HashArgs {
|
||||
pub struct HashArgs {
|
||||
#[pyarg(any, optional)]
|
||||
string: OptionalArg<ArgBytesLike>,
|
||||
#[pytraverse(skip)]
|
||||
pub string: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = "true")]
|
||||
usedforsecurity: bool,
|
||||
}
|
||||
@@ -84,11 +83,11 @@ mod hashlib {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "hashlib", name = "HASH")]
|
||||
#[pyclass(module = "_hashlib", name = "HASH")]
|
||||
#[derive(PyPayload)]
|
||||
struct PyHasher {
|
||||
name: String,
|
||||
ctx: PyRwLock<HashWrapper>,
|
||||
pub struct PyHasher {
|
||||
pub name: String,
|
||||
pub ctx: PyRwLock<HashWrapper>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PyHasher {
|
||||
@@ -108,7 +107,7 @@ mod hashlib {
|
||||
|
||||
#[pyslot]
|
||||
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("cannot create 'hashlib.HASH' instances".into()))
|
||||
Err(vm.new_type_error("cannot create '_hashlib.HASH' instances".into()))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
@@ -148,9 +147,9 @@ mod hashlib {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "hashlib", name = "HASHXOF")]
|
||||
#[pyclass(module = "_hashlib", name = "HASHXOF")]
|
||||
#[derive(PyPayload)]
|
||||
struct PyHasherXof {
|
||||
pub struct PyHasherXof {
|
||||
name: String,
|
||||
ctx: PyRwLock<HashXofWrapper>,
|
||||
}
|
||||
@@ -172,7 +171,7 @@ mod hashlib {
|
||||
|
||||
#[pyslot]
|
||||
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("cannot create 'hashlib.HASHXOF' instances".into()))
|
||||
Err(vm.new_type_error("cannot create '_hashlib.HASHXOF' instances".into()))
|
||||
}
|
||||
|
||||
#[pygetset]
|
||||
@@ -214,108 +213,147 @@ mod hashlib {
|
||||
#[pyfunction(name = "new")]
|
||||
fn hashlib_new(args: NewHashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
match args.name.as_str().to_lowercase().as_str() {
|
||||
"md5" => Ok(md5(args.into()).into_pyobject(vm)),
|
||||
"sha1" => Ok(sha1(args.into()).into_pyobject(vm)),
|
||||
"sha224" => Ok(sha224(args.into()).into_pyobject(vm)),
|
||||
"sha256" => Ok(sha256(args.into()).into_pyobject(vm)),
|
||||
"sha384" => Ok(sha384(args.into()).into_pyobject(vm)),
|
||||
"sha512" => Ok(sha512(args.into()).into_pyobject(vm)),
|
||||
"sha3_224" => Ok(sha3_224(args.into()).into_pyobject(vm)),
|
||||
"sha3_256" => Ok(sha3_256(args.into()).into_pyobject(vm)),
|
||||
"sha3_384" => Ok(sha3_384(args.into()).into_pyobject(vm)),
|
||||
"sha3_512" => Ok(sha3_512(args.into()).into_pyobject(vm)),
|
||||
"shake_128" => Ok(shake_128(args.into()).into_pyobject(vm)),
|
||||
"shake_256" => Ok(shake_256(args.into()).into_pyobject(vm)),
|
||||
"blake2b" => Ok(blake2b(args.into()).into_pyobject(vm)),
|
||||
"blake2s" => Ok(blake2s(args.into()).into_pyobject(vm)),
|
||||
"md5" => Ok(local_md5(args.into()).into_pyobject(vm)),
|
||||
"sha1" => Ok(local_sha1(args.into()).into_pyobject(vm)),
|
||||
"sha224" => Ok(local_sha224(args.into()).into_pyobject(vm)),
|
||||
"sha256" => Ok(local_sha256(args.into()).into_pyobject(vm)),
|
||||
"sha384" => Ok(local_sha384(args.into()).into_pyobject(vm)),
|
||||
"sha512" => Ok(local_sha512(args.into()).into_pyobject(vm)),
|
||||
"sha3_224" => Ok(local_sha3_224(args.into()).into_pyobject(vm)),
|
||||
"sha3_256" => Ok(local_sha3_256(args.into()).into_pyobject(vm)),
|
||||
"sha3_384" => Ok(local_sha3_384(args.into()).into_pyobject(vm)),
|
||||
"sha3_512" => Ok(local_sha3_512(args.into()).into_pyobject(vm)),
|
||||
"shake_128" => Ok(local_shake_128(args.into()).into_pyobject(vm)),
|
||||
"shake_256" => Ok(local_shake_256(args.into()).into_pyobject(vm)),
|
||||
"blake2b" => Ok(local_blake2b(args.into()).into_pyobject(vm)),
|
||||
"blake2s" => Ok(local_blake2s(args.into()).into_pyobject(vm)),
|
||||
other => Err(vm.new_value_error(format!("Unknown hashing algorithm: {other}"))),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn md5(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_md5")]
|
||||
pub fn local_md5(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("md5", HashWrapper::new::<Md5>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha1(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha1")]
|
||||
pub fn local_sha1(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha1", HashWrapper::new::<Sha1>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha224(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha224")]
|
||||
pub fn local_sha224(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha224", HashWrapper::new::<Sha224>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha256(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha256")]
|
||||
pub fn local_sha256(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha256", HashWrapper::new::<Sha256>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha384(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha384")]
|
||||
pub fn local_sha384(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha384", HashWrapper::new::<Sha384>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha512(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha512")]
|
||||
pub fn local_sha512(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha512", HashWrapper::new::<Sha512>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_224(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha3_224")]
|
||||
pub fn local_sha3_224(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_224", HashWrapper::new::<Sha3_224>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_256(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha3_256")]
|
||||
pub fn local_sha3_256(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_256", HashWrapper::new::<Sha3_256>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_384(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha3_384")]
|
||||
pub fn local_sha3_384(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_384", HashWrapper::new::<Sha3_384>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_512(args: HashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_sha3_512")]
|
||||
pub fn local_sha3_512(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_512", HashWrapper::new::<Sha3_512>(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_128(args: HashArgs) -> PyHasherXof {
|
||||
#[pyfunction(name = "openssl_shake_128")]
|
||||
pub fn local_shake_128(args: HashArgs) -> PyHasherXof {
|
||||
PyHasherXof::new("shake_128", HashXofWrapper::new_shake_128(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_256(args: HashArgs) -> PyHasherXof {
|
||||
#[pyfunction(name = "openssl_shake_256")]
|
||||
pub fn local_shake_256(args: HashArgs) -> PyHasherXof {
|
||||
PyHasherXof::new("shake_256", HashXofWrapper::new_shake_256(args.string))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2b(args: BlakeHashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_blake2b")]
|
||||
pub fn local_blake2b(args: BlakeHashArgs) -> PyHasher {
|
||||
PyHasher::new("blake2b", HashWrapper::new::<Blake2b512>(args.data))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2s(args: BlakeHashArgs) -> PyHasher {
|
||||
#[pyfunction(name = "openssl_blake2s")]
|
||||
pub fn local_blake2s(args: BlakeHashArgs) -> PyHasher {
|
||||
PyHasher::new("blake2s", HashWrapper::new::<Blake2s256>(args.data))
|
||||
}
|
||||
|
||||
trait ThreadSafeDynDigest: DynClone + DynDigest + Sync + Send {}
|
||||
#[pyfunction]
|
||||
fn compare_digest(
|
||||
a: ArgStrOrBytesLike,
|
||||
b: ArgStrOrBytesLike,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyObjectRef> {
|
||||
fn is_str(arg: &ArgStrOrBytesLike) -> bool {
|
||||
matches!(arg, ArgStrOrBytesLike::Str(_))
|
||||
}
|
||||
|
||||
if is_str(&a) != is_str(&b) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"a bytes-like object is required, not '{}'",
|
||||
b.as_object().class().name()
|
||||
)));
|
||||
}
|
||||
|
||||
let a_hash = a.borrow_bytes().to_vec();
|
||||
let b_hash = b.borrow_bytes().to_vec();
|
||||
|
||||
Ok((a_hash == b_hash).to_pyobject(vm))
|
||||
}
|
||||
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[allow(unused)]
|
||||
pub struct NewHMACHashArgs {
|
||||
#[pyarg(positional)]
|
||||
name: PyBuffer,
|
||||
#[pyarg(any, optional)]
|
||||
data: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = "true")]
|
||||
digestmod: bool, // TODO: RUSTPYTHON support functions & name functions
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn hmac_new(_args: NewHMACHashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
Err(vm.new_type_error("cannot create 'hmac' instances".into())) // TODO: RUSTPYTHON support hmac
|
||||
}
|
||||
|
||||
pub trait ThreadSafeDynDigest: DynClone + DynDigest + Sync + Send {}
|
||||
impl<T> ThreadSafeDynDigest for T where T: DynClone + DynDigest + Sync + Send {}
|
||||
|
||||
clone_trait_object!(ThreadSafeDynDigest);
|
||||
|
||||
/// Generic wrapper patching around the hashing libraries.
|
||||
#[derive(Clone)]
|
||||
struct HashWrapper {
|
||||
pub struct HashWrapper {
|
||||
block_size: usize,
|
||||
inner: Box<dyn ThreadSafeDynDigest>,
|
||||
}
|
||||
|
||||
impl HashWrapper {
|
||||
fn new<D>(data: OptionalArg<ArgBytesLike>) -> Self
|
||||
pub fn new<D>(data: OptionalArg<ArgBytesLike>) -> Self
|
||||
where
|
||||
D: ThreadSafeDynDigest + BlockSizeUser + Default + 'static,
|
||||
{
|
||||
@@ -348,13 +386,13 @@ mod hashlib {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum HashXofWrapper {
|
||||
pub enum HashXofWrapper {
|
||||
Shake128(Shake128),
|
||||
Shake256(Shake256),
|
||||
}
|
||||
|
||||
impl HashXofWrapper {
|
||||
fn new_shake_128(data: OptionalArg<ArgBytesLike>) -> Self {
|
||||
pub fn new_shake_128(data: OptionalArg<ArgBytesLike>) -> Self {
|
||||
let mut h = HashXofWrapper::Shake128(Shake128::default());
|
||||
if let OptionalArg::Present(d) = data {
|
||||
d.with_ref(|bytes| h.update(bytes));
|
||||
@@ -362,7 +400,7 @@ mod hashlib {
|
||||
h
|
||||
}
|
||||
|
||||
fn new_shake_256(data: OptionalArg<ArgBytesLike>) -> Self {
|
||||
pub fn new_shake_256(data: OptionalArg<ArgBytesLike>) -> Self {
|
||||
let mut h = HashXofWrapper::Shake256(Shake256::default());
|
||||
if let OptionalArg::Present(d) = data {
|
||||
d.with_ref(|bytes| h.update(bytes));
|
||||
|
||||
@@ -13,7 +13,14 @@ mod contextvars;
|
||||
mod csv;
|
||||
mod dis;
|
||||
mod gc;
|
||||
|
||||
mod blake2;
|
||||
mod hashlib;
|
||||
mod md5;
|
||||
mod sha1;
|
||||
mod sha256;
|
||||
mod sha3;
|
||||
|
||||
mod json;
|
||||
#[cfg(not(any(target_os = "ios", target_os = "android", target_arch = "wasm32")))]
|
||||
mod locale;
|
||||
@@ -100,7 +107,13 @@ pub fn get_module_inits() -> impl Iterator<Item = (Cow<'static, str>, StdlibInit
|
||||
"_csv" => csv::make_module,
|
||||
"_dis" => dis::make_module,
|
||||
"gc" => gc::make_module,
|
||||
"hashlib" => hashlib::make_module,
|
||||
"_hashlib" => hashlib::make_module,
|
||||
"_sha1" => sha1::make_module,
|
||||
"_sha3" => sha3::make_module,
|
||||
"_sha256" => sha256::make_module,
|
||||
// "_sha512" => sha512::make_module, // TODO: RUSPYTHON fix strange fail on vm: 'static type has not been initialized'
|
||||
"_md5" => md5::make_module,
|
||||
"_blake2" => blake2::make_module,
|
||||
"_json" => json::make_module,
|
||||
"math" => math::make_module,
|
||||
"pyexpat" => pyexpat::make_module,
|
||||
|
||||
12
stdlib/src/md5.rs
Normal file
12
stdlib/src/md5.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
pub(crate) use _md5::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _md5 {
|
||||
use crate::hashlib::_hashlib::{local_md5, HashArgs};
|
||||
use crate::vm::{PyPayload, PyResult, VirtualMachine};
|
||||
|
||||
#[pyfunction]
|
||||
fn md5(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_md5(args).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
12
stdlib/src/sha1.rs
Normal file
12
stdlib/src/sha1.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
pub(crate) use _sha1::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _sha1 {
|
||||
use crate::hashlib::_hashlib::{local_sha1, HashArgs};
|
||||
use crate::vm::{PyPayload, PyResult, VirtualMachine};
|
||||
|
||||
#[pyfunction]
|
||||
fn sha1(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha1(args).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
17
stdlib/src/sha256.rs
Normal file
17
stdlib/src/sha256.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
pub(crate) use _sha256::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _sha256 {
|
||||
use crate::hashlib::_hashlib::{local_sha224, local_sha256, HashArgs};
|
||||
use crate::vm::{PyPayload, PyResult, VirtualMachine};
|
||||
|
||||
#[pyfunction]
|
||||
fn sha224(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha224(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha256(args).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
40
stdlib/src/sha3.rs
Normal file
40
stdlib/src/sha3.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
pub(crate) use _sha3::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _sha3 {
|
||||
use crate::hashlib::_hashlib::{
|
||||
local_sha3_224, local_sha3_256, local_sha3_384, local_sha3_512, local_shake_128,
|
||||
local_shake_256, HashArgs,
|
||||
};
|
||||
use crate::vm::{PyPayload, PyResult, VirtualMachine};
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_224(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_224(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_256(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_384(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_384(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_512(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_512(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_128(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_shake_128(args).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_shake_256(args).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
20
stdlib/src/sha512.rs
Normal file
20
stdlib/src/sha512.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
// spell-checker:ignore usedforsecurity HASHXOF
|
||||
|
||||
pub(crate) use _sha512::make_module;
|
||||
|
||||
#[pymodule]
|
||||
mod _sha512 {
|
||||
use crate::hashlib::_hashlib::{HashArgs, HashWrapper, PyHasher};
|
||||
use crate::vm::{PyObjectRef, PyPayload, PyResult, VirtualMachine};
|
||||
use sha2::{Sha384, Sha512};
|
||||
|
||||
#[pyfunction(name = "sha384")]
|
||||
fn sha384(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
Ok(PyHasher::new("sha384", HashWrapper::new::<Sha384>(args.string)).into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "sha512")]
|
||||
fn sha512(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
Ok(PyHasher::new("sha512", HashWrapper::new::<Sha512>(args.string)).into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user