| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,37 +70,44 @@ | |||
| 70 | 70 | ||
| 71 | 71 | __builtin_constructor_cache = {} | |
| 72 | 72 | ||
| 73 | + __block_openssl_constructor = { | ||
| 74 | + 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', | ||
| 75 | + 'shake_128', 'shake_256', | ||
| 76 | + 'blake2b', 'blake2s', | ||
| 77 | + } | ||
| 78 | + | ||
| 73 | 79 | def __get_builtin_constructor(name): | |
| 74 | 80 | cache = __builtin_constructor_cache | |
| 75 | 81 | constructor = cache.get(name) | |
| 76 | 82 | if constructor is not None: | |
| 77 | 83 | return constructor | |
| 78 | 84 | try: | |
| 79 | - if name in ('SHA1', 'sha1'): | ||
| 85 | + if name in {'SHA1', 'sha1'}: | ||
| 80 | 86 | import _sha1 | |
| 81 | 87 | cache['SHA1'] = cache['sha1'] = _sha1.sha1 | |
| 82 | - elif name in ('MD5', 'md5'): | ||
| 88 | + elif name in {'MD5', 'md5'}: | ||
| 83 | 89 | import _md5 | |
| 84 | 90 | cache['MD5'] = cache['md5'] = _md5.md5 | |
| 85 | - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): | ||
| 91 | + elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}: | ||
| 86 | 92 | import _sha256 | |
| 87 | 93 | cache['SHA224'] = cache['sha224'] = _sha256.sha224 | |
| 88 | 94 | cache['SHA256'] = cache['sha256'] = _sha256.sha256 | |
| 89 | - elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): | ||
| 95 | + elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}: | ||
| 90 | 96 | import _sha512 | |
| 91 | 97 | cache['SHA384'] = cache['sha384'] = _sha512.sha384 | |
| 92 | 98 | cache['SHA512'] = cache['sha512'] = _sha512.sha512 | |
| 93 | - elif name in ('blake2b', 'blake2s'): | ||
| 99 | + elif name in {'blake2b', 'blake2s'}: | ||
| 94 | 100 | import _blake2 | |
| 95 | 101 | cache['blake2b'] = _blake2.blake2b | |
| 96 | 102 | cache['blake2s'] = _blake2.blake2s | |
| 97 | - elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', | ||
| 98 | - 'shake_128', 'shake_256'}: | ||
| 103 | + elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}: | ||
| 99 | 104 | import _sha3 | |
| 100 | 105 | cache['sha3_224'] = _sha3.sha3_224 | |
| 101 | 106 | cache['sha3_256'] = _sha3.sha3_256 | |
| 102 | 107 | cache['sha3_384'] = _sha3.sha3_384 | |
| 103 | 108 | cache['sha3_512'] = _sha3.sha3_512 | |
| 109 | + elif name in {'shake_128', 'shake_256'}: | ||
| 110 | + import _sha3 | ||
| 104 | 111 | cache['shake_128'] = _sha3.shake_128 | |
| 105 | 112 | cache['shake_256'] = _sha3.shake_256 | |
| 106 | 113 | except ImportError: | |
@@ -114,8 +121,8 @@ def __get_builtin_constructor(name): | |||
| 114 | 121 | ||
| 115 | 122 | ||
| 116 | 123 | def __get_openssl_constructor(name): | |
| 117 | - if name in {'blake2b', 'blake2s'}: | ||
| 118 | - # Prefer our blake2 implementation. | ||
| 124 | + if name in __block_openssl_constructor: | ||
| 125 | + # Prefer our blake2 and sha3 implementation. | ||
| 119 | 126 | return __get_builtin_constructor(name) | |
| 120 | 127 | try: | |
| 121 | 128 | f = getattr(_hashlib, 'openssl_' + name) | |
@@ -140,8 +147,8 @@ def __hash_new(name, data=b'', **kwargs): | |||
| 140 | 147 | """new(name, data=b'') - Return a new hashing object using the named algorithm; | |
| 141 | 148 | optionally initialized with data (which must be a bytes-like object). | |
| 142 | 149 | """ | |
| 143 | - if name in {'blake2b', 'blake2s'}: | ||
| 144 | - # Prefer our blake2 implementation. | ||
| 150 | + if name in __block_openssl_constructor: | ||
| 151 | + # Prefer our blake2 and sha3 implementation | ||
| 145 | 152 | # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s. | |
| 146 | 153 | # It does neither support keyed blake2 nor advanced features like | |
| 147 | 154 | # salt, personal, tree hashing or SSE. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,6 +26,11 @@ | |||
| 26 | 26 | c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib']) | |
| 27 | 27 | py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib']) | |
| 28 | 28 | ||
| 29 | + try: | ||
| 30 | + from _hashlib import HASH | ||
| 31 | + except ImportError: | ||
| 32 | + HASH = None | ||
| 33 | + | ||
| 29 | 34 | try: | |
| 30 | 35 | import _blake2 | |
| 31 | 36 | except ImportError: | |
@@ -386,6 +391,9 @@ def check_sha3(self, name, capacity, rate, suffix): | |||
| 386 | 391 | constructors = self.constructors_to_test[name] | |
| 387 | 392 | for hash_object_constructor in constructors: | |
| 388 | 393 | m = hash_object_constructor() | |
| 394 | + if HASH is not None and isinstance(m, HASH): | ||
| 395 | + # _hashopenssl's variant does not have extra SHA3 attributes | ||
| 396 | + continue | ||
| 389 | 397 | self.assertEqual(capacity + rate, 1600) | |
| 390 | 398 | self.assertEqual(m._capacity_bits, capacity) | |
| 391 | 399 | self.assertEqual(m._rate_bits, rate) | |
@@ -985,6 +993,10 @@ def test_scrypt(self): | |||
| 985 | 993 | hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1, | |
| 986 | 994 | dklen=dklen) | |
| 987 | 995 | ||
| 996 | + def test_normalized_name(self): | ||
| 997 | + self.assertNotIn("blake2b512", hashlib.algorithms_available) | ||
| 998 | + self.assertNotIn("sha3-512", hashlib.algorithms_available) | ||
| 999 | + | ||
| 988 | 1000 | ||
| 989 | 1001 | if __name__ == "__main__": | |
| 990 | 1002 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + Names of hashing algorithms frome OpenSSL are now normalized to follow | ||
| 2 | + Python's naming conventions. For example OpenSSL uses sha3-512 instead of | ||
| 3 | + sha3_512 or blake2b512 instead of blake2b. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,6 +34,14 @@ | |||
| 34 | 34 | ||
| 35 | 35 | #define MUNCH_SIZE INT_MAX | |
| 36 | 36 | ||
| 37 | + #if defined(NID_sha3_224) && defined(EVP_MD_FLAG_XOF) | ||
| 38 | + #define PY_OPENSSL_HAS_SHA3 1 | ||
| 39 | + #endif | ||
| 40 | + | ||
| 41 | + #ifdef NID_blake2b512 | ||
| 42 | + #define PY_OPENSSL_HAS_BLAKE2 1 | ||
| 43 | + #endif | ||
| 44 | + | ||
| 37 | 45 | typedef struct { | |
| 38 | 46 | PyObject_HEAD | |
| 39 | 47 | EVP_MD_CTX *ctx; /* OpenSSL message digest context */ | |
@@ -82,6 +90,135 @@ _setException(PyObject *exc) | |||
| 82 | 90 | } | |
| 83 | 91 | /* LCOV_EXCL_STOP */ | |
| 84 | 92 | ||
| 93 | + static PyObject* | ||
| 94 | + py_digest_name(const EVP_MD *md) | ||
| 95 | + { | ||
| 96 | + int nid = EVP_MD_nid(md); | ||
| 97 | + const char *name = NULL; | ||
| 98 | + | ||
| 99 | + /* Hard-coded names for well-known hashing algorithms. | ||
| 100 | + * OpenSSL uses slightly different names algorithms like SHA3. | ||
| 101 | + */ | ||
| 102 | + switch (nid) { | ||
| 103 | + case NID_md5: | ||
| 104 | + name = "md5"; | ||
| 105 | + break; | ||
| 106 | + case NID_sha1: | ||
| 107 | + name = "sha1"; | ||
| 108 | + break; | ||
| 109 | + case NID_sha224: | ||
| 110 | + name ="sha224"; | ||
| 111 | + break; | ||
| 112 | + case NID_sha256: | ||
| 113 | + name ="sha256"; | ||
| 114 | + break; | ||
| 115 | + case NID_sha384: | ||
| 116 | + name ="sha384"; | ||
| 117 | + break; | ||
| 118 | + case NID_sha512: | ||
| 119 | + name ="sha512"; | ||
| 120 | + break; | ||
| 121 | + #ifdef NID_sha512_224 | ||
| 122 | + case NID_sha512_224: | ||
| 123 | + name ="sha512_224"; | ||
| 124 | + break; | ||
| 125 | + case NID_sha512_256: | ||
| 126 | + name ="sha512_256"; | ||
| 127 | + break; | ||
| 128 | + #endif | ||
| 129 | + #ifdef PY_OPENSSL_HAS_SHA3 | ||
| 130 | + case NID_sha3_224: | ||
| 131 | + name ="sha3_224"; | ||
| 132 | + break; | ||
| 133 | + case NID_sha3_256: | ||
| 134 | + name ="sha3_256"; | ||
| 135 | + break; | ||
| 136 | + case NID_sha3_384: | ||
| 137 | + name ="sha3_384"; | ||
| 138 | + break; | ||
| 139 | + case NID_sha3_512: | ||
| 140 | + name ="sha3_512"; | ||
| 141 | + break; | ||
| 142 | + case NID_shake128: | ||
| 143 | + name ="shake_128"; | ||
| 144 | + break; | ||
| 145 | + case NID_shake256: | ||
| 146 | + name ="shake_256"; | ||
| 147 | + break; | ||
| 148 | + #endif | ||
| 149 | + #ifdef PY_OPENSSL_HAS_BLAKE2 | ||
| 150 | + case NID_blake2s256: | ||
| 151 | + name ="blake2s"; | ||
| 152 | + break; | ||
| 153 | + case NID_blake2b512: | ||
| 154 | + name ="blake2b"; | ||
| 155 | + break; | ||
| 156 | + #endif | ||
| 157 | + default: | ||
| 158 | + /* Ignore aliased names and only use long, lowercase name. The aliases | ||
| 159 | + * pollute the list and OpenSSL appears to have its own definition of | ||
| 160 | + * alias as the resulting list still contains duplicate and alternate | ||
| 161 | + * names for several algorithms. | ||
| 162 | + */ | ||
| 163 | + name = OBJ_nid2ln(nid); | ||
| 164 | + if (name == NULL) | ||
| 165 | + name = OBJ_nid2sn(nid); | ||
| 166 | + break; | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + return PyUnicode_FromString(name); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + static const EVP_MD* | ||
| 173 | + py_digest_by_name(const char *name) | ||
| 174 | + { | ||
| 175 | + const EVP_MD *digest = EVP_get_digestbyname(name); | ||
| 176 | + | ||
| 177 | + /* OpenSSL uses dash instead of underscore in names of some algorithms | ||
| 178 | + * like SHA3 and SHAKE. Detect different spellings. */ | ||
| 179 | + if (digest == NULL) { | ||
| 180 | + #ifdef NID_sha512_224 | ||
| 181 | + if (!strcmp(name, "sha512_224") || !strcmp(name, "SHA512_224")) { | ||
| 182 | + digest = EVP_sha512_224(); | ||
| 183 | + } | ||
| 184 | + else if (!strcmp(name, "sha512_256") || !strcmp(name, "SHA512_256")) { | ||
| 185 | + digest = EVP_sha512_256(); | ||
| 186 | + } | ||
| 187 | + #endif | ||
| 188 | + #ifdef PY_OPENSSL_HAS_SHA3 | ||
| 189 | + /* could be sha3_ or shake_, Python never defined upper case */ | ||
| 190 | + else if (!strcmp(name, "sha3_224")) { | ||
| 191 | + digest = EVP_sha3_224(); | ||
| 192 | + } | ||
| 193 | + else if (!strcmp(name, "sha3_256")) { | ||
| 194 | + digest = EVP_sha3_256(); | ||
| 195 | + } | ||
| 196 | + else if (!strcmp(name, "sha3_384")) { | ||
| 197 | + digest = EVP_sha3_384(); | ||
| 198 | + } | ||
| 199 | + else if (!strcmp(name, "sha3_512")) { | ||
| 200 | + digest = EVP_sha3_512(); | ||
| 201 | + } | ||
| 202 | + else if (!strcmp(name, "shake_128")) { | ||
| 203 | + digest = EVP_shake128(); | ||
| 204 | + } | ||
| 205 | + else if (!strcmp(name, "shake_256")) { | ||
| 206 | + digest = EVP_shake256(); | ||
| 207 | + } | ||
| 208 | + #endif | ||
| 209 | + #ifdef PY_OPENSSL_HAS_BLAKE2 | ||
| 210 | + else if (!strcmp(name, "blake2s256")) { | ||
| 211 | + digest = EVP_blake2s256(); | ||
| 212 | + } | ||
| 213 | + else if (!strcmp(name, "blake2b512")) { | ||
| 214 | + digest = EVP_blake2b512(); | ||
| 215 | + } | ||
| 216 | + #endif | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + return digest; | ||
| 220 | + } | ||
| 221 | + | ||
| 85 | 222 | static EVPobject * | |
| 86 | 223 | newEVPobject(void) | |
| 87 | 224 | { | |
@@ -304,16 +441,7 @@ EVP_get_digest_size(EVPobject *self, void *closure) | |||
| 304 | 441 | static PyObject * | |
| 305 | 442 | EVP_get_name(EVPobject *self, void *closure) | |
| 306 | 443 | { | |
| 307 | - const char *name = EVP_MD_name(EVP_MD_CTX_md(self->ctx)); | ||
| 308 | - PyObject *name_obj, *name_lower; | ||
| 309 | - | ||
| 310 | - name_obj = PyUnicode_FromString(name); | ||
| 311 | - if (!name_obj) { | ||
| 312 | - return NULL; | ||
| 313 | - } | ||
| 314 | - name_lower = PyObject_CallMethod(name_obj, "lower", NULL); | ||
| 315 | - Py_DECREF(name_obj); | ||
| 316 | - return name_lower; | ||
| 444 | + return py_digest_name(EVP_MD_CTX_md(self->ctx)); | ||
| 317 | 445 | } | |
| 318 | 446 | ||
| 319 | 447 | static PyGetSetDef EVP_getseters[] = { | |
@@ -337,7 +465,7 @@ static PyObject * | |||
| 337 | 465 | EVP_repr(EVPobject *self) | |
| 338 | 466 | { | |
| 339 | 467 | PyObject *name_obj, *repr; | |
| 340 | - name_obj = EVP_get_name(self, NULL); | ||
| 468 | + name_obj = py_digest_name(EVP_MD_CTX_md(self->ctx)); | ||
| 341 | 469 | if (!name_obj) { | |
| 342 | 470 | return NULL; | |
| 343 | 471 | } | |
@@ -403,6 +531,7 @@ static PyTypeObject EVPtype = { | |||
| 403 | 531 | 0, /* tp_dictoffset */ | |
| 404 | 532 | }; | |
| 405 | 533 | ||
| 534 | + \ | ||
| 406 | 535 | static PyObject * | |
| 407 | 536 | EVPnew(const EVP_MD *digest, | |
| 408 | 537 | const unsigned char *cp, Py_ssize_t len, int usedforsecurity) | |
@@ -485,7 +614,7 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj, | |||
| 485 | 614 | if (data_obj) | |
| 486 | 615 | GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); | |
| 487 | 616 | ||
| 488 | - digest = EVP_get_digestbyname(name); | ||
| 617 | + digest = py_digest_by_name(name); | ||
| 489 | 618 | ||
| 490 | 619 | ret_obj = EVPnew(digest, | |
| 491 | 620 | (unsigned char*)view.buf, view.len, | |
@@ -922,21 +1051,17 @@ typedef struct _internal_name_mapper_state { | |||
| 922 | 1051 | ||
| 923 | 1052 | /* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */ | |
| 924 | 1053 | static void | |
| 925 | - _openssl_hash_name_mapper(const OBJ_NAME *openssl_obj_name, void *arg) | ||
| 1054 | + _openssl_hash_name_mapper(const EVP_MD *md, const char *from, | ||
| 1055 | + const char *to, void *arg) | ||
| 926 | 1056 | { | |
| 927 | 1057 | _InternalNameMapperState *state = (_InternalNameMapperState *)arg; | |
| 928 | 1058 | PyObject *py_name; | |
| 929 | 1059 | ||
| 930 | 1060 | assert(state != NULL); | |
| 931 | - if (openssl_obj_name == NULL) | ||
| 932 | - return; | ||
| 933 | - /* Ignore aliased names, they pollute the list and OpenSSL appears to | ||
| 934 | - * have its own definition of alias as the resulting list still | ||
| 935 | - * contains duplicate and alternate names for several algorithms. */ | ||
| 936 | - if (openssl_obj_name->alias) | ||
| 1061 | + if (md == NULL) | ||
| 937 | 1062 | return; | |
| 938 | 1063 | ||
| 939 | - py_name = PyUnicode_FromString(openssl_obj_name->name); | ||
| 1064 | + py_name = py_digest_name(md); | ||
| 940 | 1065 | if (py_name == NULL) { | |
| 941 | 1066 | state->error = 1; | |
| 942 | 1067 | } else { | |
@@ -958,7 +1083,7 @@ generate_hash_name_list(void) | |||
| 958 | 1083 | return NULL; | |
| 959 | 1084 | state.error = 0; | |
| 960 | 1085 | ||
| 961 | - OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, &_openssl_hash_name_mapper, &state); | ||
| 1086 | + EVP_MD_do_all(&_openssl_hash_name_mapper, &state); | ||
| 962 | 1087 | ||
| 963 | 1088 | if (state.error) { | |
| 964 | 1089 | Py_DECREF(state.set); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments