Skip to content

warn for hmac and hexlify #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Lib/hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"""

import warnings as _warnings
import sys


from operator import _compare_digest as compare_digest

Expand Down Expand Up @@ -41,6 +43,10 @@ def __init__(self, key, msg = None, digestmod = None):
return

if digestmod is None:
if sys.py3kwarning:
_warnings.warnpy3k_with_fix('the digestmod paramemer is required in 3.x',
'generate a digest with hashlib module',
DeprecationWarning, stacklevel=4)
import hashlib
digestmod = hashlib.md5

Expand Down
7 changes: 5 additions & 2 deletions Lib/test/test_binascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@ def test_hex(self):
self.assertRaises(TypeError, binascii.a2b_hex, t[:-1] + 'q')

# Verify the treatment of Unicode strings
if test_support.have_unicode:
self.assertEqual(binascii.hexlify(unicode('a', 'ascii')), '61')
with test_support.check_py3k_warnings(("The hexlify() module expects bytes in 3.x; use the 'b' prefix on the string",
DeprecationWarning)):
if test_support.have_unicode:
self.assertEqual(binascii.hexlify(unicode('a', 'ascii')), '61')
self.assertEqual(binascii.b2a_hex(unicode('a', 'ascii')), '61')

def test_qp(self):
type2test = self.type2test
Expand Down
33 changes: 19 additions & 14 deletions Lib/test/test_hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,37 @@ def test_md5_vectors(self):
# Test the HMAC module against test vectors from the RFC.

def md5test(key, data, digest):
h = hmac.HMAC(key, data)
h = hmac.HMAC(key, data, digestmod=hashlib.sha1)
self.assertEqual(h.hexdigest().upper(), digest.upper())

md5test(chr(0x0b) * 16,
"Hi There",
"9294727A3638BB1C13F48EF8158BFC9D")
"675B0B3A1B4DDF4E124872DA6C2F632BFED957E9")

md5test("Jefe",
"what do ya want for nothing?",
"750c783e6ab0b503eaa86e310a5db738")
"EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79")

md5test(chr(0xAA)*16,
chr(0xDD)*50,
"56be34521d144c88dbb8c733f0e8b3f6")
"D730594D167E35D5956FD8003D0DB3D3F46DC7BB")

md5test("".join([chr(i) for i in range(1, 26)]),
chr(0xCD) * 50,
"697eaf0aca3a3aea3a75164746ffaa79")
"4C9007F4026250C6BC8414F9BF50C86C2D7235DA")

md5test(chr(0x0C) * 16,
"Test With Truncation",
"56461ef2342edc00f9bab995690efd4c")
"37268B7E21E84DA5720C53C4BA03AD1104039FA7")

md5test(chr(0xAA) * 80,
"Test Using Larger Than Block-Size Key - Hash Key First",
"6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd")
"AA4AE5E15272D00E95705637CE8A3B55ED402112")

md5test(chr(0xAA) * 80,
("Test Using Larger Than Block-Size Key "
"and Larger Than One Block-Size Data"),
"6f630fad67cda0ee1fb1f562db3aa53e")
"E8E99D0F45237D786D6BBAA7965C7808BBFF1A91")

def test_sha_vectors(self):
def shatest(key, data, digest):
Expand Down Expand Up @@ -232,14 +232,14 @@ def test_normal(self):
# Standard constructor call.
failed = 0
try:
h = hmac.HMAC("key")
h = hmac.HMAC("key", digestmod=hashlib.sha1)
except:
self.fail("Standard constructor call raised exception.")

def test_withtext(self):
# Constructor call with text.
try:
h = hmac.HMAC("key", "hash this!")
h = hmac.HMAC("key", "hash this!", digestmod=hashlib.sha1)
except:
self.fail("Constructor call with text argument raised exception.")

Expand All @@ -250,6 +250,11 @@ def test_withmodule(self):
except:
self.fail("Constructor call with hashlib.sha1 raised exception.")

def test_3k_no_digest(self):
with test_support.check_py3k_warnings(("the digestmod paramemer is required in 3.x; generate a digest with hashlib module",
DeprecationWarning)):
h = hmac.HMAC("key", "", hashlib.sha1)

class SanityTestCase(unittest.TestCase):

def test_default_is_md5(self):
Expand All @@ -262,7 +267,7 @@ def test_exercise_all_methods(self):
# Exercising all methods once.
# This must not raise any exceptions
try:
h = hmac.HMAC("my secret key")
h = hmac.HMAC("my secret key", digestmod=hashlib.sha1)
h.update("compute the hash of this text!")
dig = h.digest()
dig = h.hexdigest()
Expand All @@ -274,7 +279,7 @@ class CopyTestCase(unittest.TestCase):

def test_attributes(self):
# Testing if attributes are of same type.
h1 = hmac.HMAC("key")
h1 = hmac.HMAC("key", digestmod=hashlib.sha1)
h2 = h1.copy()
self.assertTrue(h1.digest_cons == h2.digest_cons,
"digest constructors don't match.")
Expand All @@ -285,7 +290,7 @@ def test_attributes(self):

def test_realcopy(self):
# Testing if the copy method created a real copy.
h1 = hmac.HMAC("key")
h1 = hmac.HMAC("key", digestmod=hashlib.sha1)
h2 = h1.copy()
# Using id() in case somebody has overridden __cmp__.
self.assertTrue(id(h1) != id(h2), "No real copy of the HMAC instance.")
Expand All @@ -296,7 +301,7 @@ def test_realcopy(self):

def test_equality(self):
# Testing if the copy has the same digests.
h1 = hmac.HMAC("key")
h1 = hmac.HMAC("key", digestmod=hashlib.sha1)
h1.update("some random text")
h2 = h1.copy()
self.assertTrue(h1.digest() == h2.digest(),
Expand Down
50 changes: 50 additions & 0 deletions Lib/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ def warnpy3k(message, category=None, stacklevel=1):
category = DeprecationWarning
warn(message, category, stacklevel+1)

def warnpy3k_with_fix(message, category=None, stacklevel=1):
"""Issue a deprecation warning for Python 3.x related changes and a fix.

Warnings are omitted unless Python is started with the -3 option.
"""
if sys.py3kwarning:
if category is None:
category = DeprecationWarning
warn_with_fix(message, fix, category, stacklevel+1)

def _show_warning(message, category, filename, lineno, file=None, line=None):
"""Hook to write a warning to a file; replace if you like."""
if file is None:
Expand Down Expand Up @@ -343,6 +353,46 @@ def warn_explicit(message, category, filename, lineno,
# Print message and context
showwarning(message, category, filename, lineno)

def warn_with_fix(message, fix, category=None, stacklevel=1):
"""Issue a warning, or maybe ignore it or raise an exception."""
# Check if message is already a Warning object
if isinstance(message, Warning):
category = message.__class__
# Check category argument
if category is None:
category = UserWarning
assert issubclass(category, Warning)
# Get context information
try:
caller = sys._getframe(stacklevel)
except ValueError:
globals = sys.__dict__
lineno = 1
else:
globals = caller.f_globals
lineno = caller.f_lineno
if '__name__' in globals:
module = globals['__name__']
else:
module = "<string>"
filename = globals.get('__file__')
if filename:
fnl = filename.lower()
if fnl.endswith((".pyc", ".pyo")):
filename = filename[:-1]
else:
if module == "__main__":
try:
filename = sys.argv[0]
except AttributeError:
# embedded interpreters don't have sys.argv, see bug #839151
filename = '__main__'
if not filename:
filename = module
registry = globals.setdefault("__warningregistry__", {})
warn_explicit_with_fix(message, fix, category, filename, lineno, module, registry,
globals)

def warn_explicit_with_fix(message, fix, category, filename, lineno,
module=None, registry=None, module_globals=None):
lineno = int(lineno)
Expand Down
5 changes: 5 additions & 0 deletions Modules/binascii.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,11 @@ binascii_hexlify(PyObject *self, PyObject *args)
argbuf = parg.buf;
arglen = parg.len;

if (PyUnicode_Check(args))
if (PyErr_WarnPy3k_WithFix("The hexlify() module expects bytes in 3.x",
"use the 'b' prefix on the string", 1) < 0)
return NULL;

assert(arglen >= 0);
if (arglen > PY_SSIZE_T_MAX / 2) {
PyBuffer_Release(&parg);
Expand Down