mirror of
https://github.com/python/cpython.git
synced 2025-11-25 12:44:13 +00:00
[3.14] gh-134696: align OpenSSL and HACL*-based hash functions constructors AC signatures (GH-134713) (#134961)
OpenSSL and HACL*-based hash functions constructors now support both `data` and `string` parameters. Previously these constructor functions inconsistently supported sometimes `data` and sometimes `string`, while the documentation expected `data` to be given in all cases. (cherry picked from commitc6e63d9d35) (cherry picked from commit379d0bc956)
This commit is contained in:
parent
5d07d16d45
commit
777fd4979c
16 changed files with 937 additions and 502 deletions
|
|
@ -12,6 +12,7 @@ import io
|
|||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import sysconfig
|
||||
import tempfile
|
||||
|
|
@ -141,11 +142,10 @@ class HashLibTestCase(unittest.TestCase):
|
|||
# of hashlib.new given the algorithm name.
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
constructors.add(getattr(hashlib, algorithm))
|
||||
def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs):
|
||||
if data is None:
|
||||
return hashlib.new(_alg, **kwargs)
|
||||
return hashlib.new(_alg, data, **kwargs)
|
||||
constructors.add(_test_algorithm_via_hashlib_new)
|
||||
def c(*args, __algorithm_name=algorithm, **kwargs):
|
||||
return hashlib.new(__algorithm_name, *args, **kwargs)
|
||||
c.__name__ = f'do_test_algorithm_via_hashlib_new_{algorithm}'
|
||||
constructors.add(c)
|
||||
|
||||
_hashlib = self._conditional_import_module('_hashlib')
|
||||
self._hashlib = _hashlib
|
||||
|
|
@ -250,6 +250,75 @@ class HashLibTestCase(unittest.TestCase):
|
|||
self._hashlib.new("md5", usedforsecurity=False)
|
||||
self._hashlib.openssl_md5(usedforsecurity=False)
|
||||
|
||||
@unittest.skipIf(get_fips_mode(), "skip in FIPS mode")
|
||||
def test_clinic_signature(self):
|
||||
for constructor in self.hash_constructors:
|
||||
with self.subTest(constructor.__name__):
|
||||
constructor(b'')
|
||||
constructor(data=b'')
|
||||
constructor(string=b'') # should be deprecated in the future
|
||||
|
||||
digest_name = constructor(b'').name
|
||||
with self.subTest(digest_name):
|
||||
hashlib.new(digest_name, b'')
|
||||
hashlib.new(digest_name, data=b'')
|
||||
hashlib.new(digest_name, string=b'')
|
||||
if self._hashlib:
|
||||
self._hashlib.new(digest_name, b'')
|
||||
self._hashlib.new(digest_name, data=b'')
|
||||
self._hashlib.new(digest_name, string=b'')
|
||||
|
||||
@unittest.skipIf(get_fips_mode(), "skip in FIPS mode")
|
||||
def test_clinic_signature_errors(self):
|
||||
nomsg = b''
|
||||
mymsg = b'msg'
|
||||
conflicting_call = re.escape(
|
||||
"'data' and 'string' are mutually exclusive "
|
||||
"and support for 'string' keyword parameter "
|
||||
"is slated for removal in a future version."
|
||||
)
|
||||
duplicated_param = re.escape("given by name ('data') and position")
|
||||
unexpected_param = re.escape("got an unexpected keyword argument '_'")
|
||||
for args, kwds, errmsg in [
|
||||
# Reject duplicated arguments before unknown keyword arguments.
|
||||
((nomsg,), dict(data=nomsg, _=nomsg), duplicated_param),
|
||||
((mymsg,), dict(data=nomsg, _=nomsg), duplicated_param),
|
||||
# Reject duplicated arguments before conflicting ones.
|
||||
*itertools.product(
|
||||
[[nomsg], [mymsg]],
|
||||
[dict(data=nomsg), dict(data=nomsg, string=nomsg)],
|
||||
[duplicated_param]
|
||||
),
|
||||
# Reject unknown keyword arguments before conflicting ones.
|
||||
*itertools.product(
|
||||
[()],
|
||||
[
|
||||
dict(_=None),
|
||||
dict(data=nomsg, _=None),
|
||||
dict(string=nomsg, _=None),
|
||||
dict(string=nomsg, data=nomsg, _=None),
|
||||
],
|
||||
[unexpected_param]
|
||||
),
|
||||
((nomsg,), dict(_=None), unexpected_param),
|
||||
((mymsg,), dict(_=None), unexpected_param),
|
||||
# Reject conflicting arguments.
|
||||
[(nomsg,), dict(string=nomsg), conflicting_call],
|
||||
[(mymsg,), dict(string=nomsg), conflicting_call],
|
||||
[(), dict(data=nomsg, string=nomsg), conflicting_call],
|
||||
]:
|
||||
for constructor in self.hash_constructors:
|
||||
digest_name = constructor(b'').name
|
||||
with self.subTest(constructor.__name__, args=args, kwds=kwds):
|
||||
with self.assertRaisesRegex(TypeError, errmsg):
|
||||
constructor(*args, **kwds)
|
||||
with self.subTest(digest_name, args=args, kwds=kwds):
|
||||
with self.assertRaisesRegex(TypeError, errmsg):
|
||||
hashlib.new(digest_name, *args, **kwds)
|
||||
if self._hashlib:
|
||||
with self.assertRaisesRegex(TypeError, errmsg):
|
||||
self._hashlib.new(digest_name, *args, **kwds)
|
||||
|
||||
def test_unknown_hash(self):
|
||||
self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam')
|
||||
self.assertRaises(TypeError, hashlib.new, 1)
|
||||
|
|
@ -719,8 +788,6 @@ class HashLibTestCase(unittest.TestCase):
|
|||
self.assertRaises(ValueError, constructor, node_offset=-1)
|
||||
self.assertRaises(OverflowError, constructor, node_offset=max_offset+1)
|
||||
|
||||
self.assertRaises(TypeError, constructor, data=b'')
|
||||
self.assertRaises(TypeError, constructor, string=b'')
|
||||
self.assertRaises(TypeError, constructor, '')
|
||||
|
||||
constructor(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue