mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
bpo-32433: Optimized HMAC digest (#5023)
The hmac module now has hmac.digest(), which provides an optimized HMAC digest for short messages. hmac.digest() is up to three times faster than hmac.HMAC().digest(). Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
parent
a49ac99029
commit
2f050c7e1b
7 changed files with 204 additions and 3 deletions
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
/* EVP is the preferred interface to hashing in OpenSSL */
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
/* We use the object interface to discover what hashes OpenSSL supports. */
|
||||
#include <openssl/objects.h>
|
||||
#include "openssl/err.h"
|
||||
|
|
@ -528,8 +529,6 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
|
|||
return ret_obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10000000 && !defined(OPENSSL_NO_HMAC) \
|
||||
&& !defined(OPENSSL_NO_SHA))
|
||||
|
||||
|
|
@ -849,6 +848,61 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Fast HMAC for hmac.digest()
|
||||
*/
|
||||
|
||||
/*[clinic input]
|
||||
_hashlib.hmac_digest
|
||||
|
||||
key: Py_buffer
|
||||
msg: Py_buffer
|
||||
digest: str
|
||||
|
||||
Single-shot HMAC
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_hashlib_hmac_digest_impl(PyObject *module, Py_buffer *key, Py_buffer *msg,
|
||||
const char *digest)
|
||||
/*[clinic end generated code: output=75630e684cdd8762 input=10e964917921e2f2]*/
|
||||
{
|
||||
unsigned char md[EVP_MAX_MD_SIZE] = {0};
|
||||
unsigned int md_len = 0;
|
||||
unsigned char *result;
|
||||
const EVP_MD *evp;
|
||||
|
||||
evp = EVP_get_digestbyname(digest);
|
||||
if (evp == NULL) {
|
||||
PyErr_SetString(PyExc_ValueError, "unsupported hash type");
|
||||
return NULL;
|
||||
}
|
||||
if (key->len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"key is too long.");
|
||||
return NULL;
|
||||
}
|
||||
if (msg->len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"msg is too long.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
result = HMAC(
|
||||
evp,
|
||||
(const void*)key->buf, (int)key->len,
|
||||
(const unsigned char*)msg->buf, (int)msg->len,
|
||||
md, &md_len
|
||||
);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (result == NULL) {
|
||||
_setException(PyExc_ValueError);
|
||||
return NULL;
|
||||
}
|
||||
return PyBytes_FromStringAndSize((const char*)md, md_len);
|
||||
}
|
||||
|
||||
/* State for our callback function so that it can accumulate a result. */
|
||||
typedef struct _internal_name_mapper_state {
|
||||
PyObject *set;
|
||||
|
|
@ -982,6 +1036,7 @@ static struct PyMethodDef EVP_functions[] = {
|
|||
pbkdf2_hmac__doc__},
|
||||
#endif
|
||||
_HASHLIB_SCRYPT_METHODDEF
|
||||
_HASHLIB_HMAC_DIGEST_METHODDEF
|
||||
CONSTRUCTOR_METH_DEF(md5),
|
||||
CONSTRUCTOR_METH_DEF(sha1),
|
||||
CONSTRUCTOR_METH_DEF(sha224),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue