You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
6.4 KiB
189 lines
6.4 KiB
|
|
# HG changeset patch |
|
# User Benjamin Peterson <benjamin@python.org> |
|
# Date 1409233289 14400 |
|
# Node ID 3f73c44b1fd1d442d6841493328e9756fb5e7ef5 |
|
# Parent 97081a80f487841d81aeed55d398a1dba1faca00 |
|
PEP 466: backport hashlib algorithm constants (closes #21307) |
|
|
|
diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst |
|
--- a/Doc/library/hashlib.rst |
|
+++ b/Doc/library/hashlib.rst |
|
@@ -88,6 +88,24 @@ This module provides the following const |
|
|
|
.. versionadded:: 2.7 |
|
|
|
+.. data:: algorithms_guaranteed |
|
+ |
|
+ A set containing the names of the hash algorithms guaranteed to be supported |
|
+ by this module on all platforms. |
|
+ |
|
+ .. versionadded:: 2.7.9 |
|
+ |
|
+.. data:: algorithms_available |
|
+ |
|
+ A set containing the names of the hash algorithms that are available in the |
|
+ running Python interpreter. These names will be recognized when passed to |
|
+ :func:`new`. :attr:`algorithms_guaranteed` will always be a subset. The |
|
+ same algorithm may appear multiple times in this set under different names |
|
+ (thanks to OpenSSL). |
|
+ |
|
+ .. versionadded:: 2.7.9 |
|
+ |
|
+ |
|
The following values are provided as constant attributes of the hash objects |
|
returned by the constructors: |
|
|
|
diff -up Python-2.7.5/Lib/hashlib.py.hash Python-2.7.5/Lib/hashlib.py |
|
--- Python-2.7.5/Lib/hashlib.py.hash 2015-03-04 17:05:57.496598686 +0100 |
|
+++ Python-2.7.5/Lib/hashlib.py 2015-03-04 17:11:34.872739103 +0100 |
|
@@ -18,8 +18,9 @@ than using new(): |
|
|
|
md5(), sha1(), sha224(), sha256(), sha384(), and sha512() |
|
|
|
-More algorithms may be available on your platform but the above are |
|
-guaranteed to exist. |
|
+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. |
|
@@ -75,9 +76,14 @@ More condensed: |
|
# always available algorithm is added. |
|
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') |
|
|
|
+algorithms_guaranteed = set(__always_supported) |
|
+algorithms_available = set(__always_supported) |
|
+ |
|
algorithms = __always_supported |
|
|
|
-__all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac') |
|
+__all__ = __always_supported + ('new', 'algorithms_guaranteed', |
|
+ 'algorithms_available', 'algorithms', |
|
+ 'pbkdf2_hmac') |
|
|
|
|
|
def __get_openssl_constructor(name): |
|
@@ -110,6 +116,8 @@ try: |
|
import _hashlib |
|
new = __hash_new |
|
__get_hash = __get_openssl_constructor |
|
+ algorithms_available = algorithms_available.union( |
|
+ _hashlib.openssl_md_meth_names) |
|
except ImportError: |
|
# We don't build the legacy modules |
|
raise |
|
diff -up Python-2.7.5/Modules/_hashopenssl.c.hash Python-2.7.5/Modules/_hashopenssl.c |
|
--- Python-2.7.5/Modules/_hashopenssl.c.hash 2015-03-04 17:06:18.246791837 +0100 |
|
+++ Python-2.7.5/Modules/_hashopenssl.c 2015-03-04 17:16:17.696369000 +0100 |
|
@@ -784,6 +784,61 @@ pbkdf2_hmac(PyObject *self, PyObject *ar |
|
|
|
#endif |
|
|
|
+/* State for our callback function so that it can accumulate a result. */ |
|
+typedef struct _internal_name_mapper_state { |
|
+ PyObject *set; |
|
+ int error; |
|
+} _InternalNameMapperState; |
|
+ |
|
+ |
|
+/* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */ |
|
+static void |
|
+_openssl_hash_name_mapper(const OBJ_NAME *openssl_obj_name, void *arg) |
|
+{ |
|
+ _InternalNameMapperState *state = (_InternalNameMapperState *)arg; |
|
+ PyObject *py_name; |
|
+ |
|
+ assert(state != NULL); |
|
+ if (openssl_obj_name == NULL) |
|
+ return; |
|
+ /* Ignore aliased names, they pollute the list and OpenSSL appears to |
|
+ * have a its own definition of alias as the resulting list still |
|
+ * contains duplicate and alternate names for several algorithms. */ |
|
+ if (openssl_obj_name->alias) |
|
+ return; |
|
+ |
|
+ py_name = PyString_FromString(openssl_obj_name->name); |
|
+ if (py_name == NULL) { |
|
+ state->error = 1; |
|
+ } else { |
|
+ if (PySet_Add(state->set, py_name) != 0) { |
|
+ state->error = 1; |
|
+ } |
|
+ Py_DECREF(py_name); |
|
+ } |
|
+} |
|
+ |
|
+ |
|
+/* Ask OpenSSL for a list of supported ciphers, filling in a Python set. */ |
|
+static PyObject* |
|
+generate_hash_name_list(void) |
|
+{ |
|
+ _InternalNameMapperState state; |
|
+ state.set = PyFrozenSet_New(NULL); |
|
+ if (state.set == NULL) |
|
+ return NULL; |
|
+ state.error = 0; |
|
+ |
|
+ OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, &_openssl_hash_name_mapper, &state); |
|
+ |
|
+ if (state.error) { |
|
+ Py_DECREF(state.set); |
|
+ return NULL; |
|
+ } |
|
+ return state.set; |
|
+} |
|
+ |
|
+ |
|
/* |
|
* This macro and function generates a family of constructor function |
|
* definitions for specific hash algorithms. These constructors are much |
|
@@ -924,11 +979,11 @@ static struct PyMethodDef EVP_functions[ |
|
PyMODINIT_FUNC |
|
init_hashlib(void) |
|
{ |
|
- PyObject *m; |
|
+ PyObject *m, *openssl_md_meth_names; |
|
|
|
SSL_load_error_strings(); |
|
SSL_library_init(); |
|
- OpenSSL_add_all_digests(); |
|
+ ERR_load_crypto_strings(); |
|
|
|
Py_TYPE(&EVPtype) = &PyType_Type; |
|
if (PyType_Ready(&EVPtype) < 0) |
|
@@ -938,6 +993,14 @@ init_hashlib(void) |
|
if (m == NULL) |
|
return; |
|
|
|
+ openssl_md_meth_names = generate_hash_name_list(); |
|
+ if (openssl_md_meth_names == NULL) { |
|
+ return; |
|
+ } |
|
+ if (PyModule_AddObject(m, "openssl_md_meth_names", openssl_md_meth_names)) { |
|
+ return; |
|
+ } |
|
+ |
|
#if HASH_OBJ_CONSTRUCTOR |
|
Py_INCREF(&EVPtype); |
|
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype); |
|
diff -up Python-2.7.5/Lib/test/test_hashlib.py.hash Python-2.7.5/Lib/test/test_hashlib.py |
|
--- Python-2.7.5/Lib/test/test_hashlib.py.hash 2015-03-04 18:04:57.823553474 +0100 |
|
+++ Python-2.7.5/Lib/test/test_hashlib.py 2015-03-04 18:06:39.395499123 +0100 |
|
@@ -107,6 +107,15 @@ class HashLibTestCase(unittest.TestCase) |
|
tuple([_algo for _algo in self.supported_hash_names if |
|
_algo.islower()])) |
|
|
|
+ def test_algorithms_guaranteed(self): |
|
+ self.assertEqual(hashlib.algorithms_guaranteed, |
|
+ set(_algo for _algo in self.supported_hash_names |
|
+ if _algo.islower())) |
|
+ |
|
+ def test_algorithms_available(self): |
|
+ self.assertTrue(set(hashlib.algorithms_guaranteed). |
|
+ issubset(hashlib.algorithms_available)) |
|
+ |
|
def test_unknown_hash(self): |
|
self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') |
|
self.assertRaises(TypeError, hashlib.new, 1)
|
|
|