Skip to main content

Modules/_hashlibmodule.c

cpython 3.14 @ ab2d84fe1023/Modules/_hashlibmodule.c

The C backend for hashlib. The pure-Python Lib/hashlib.py imports this module as _hashlib and re-exports its objects under the familiar names (hashlib.md5, hashlib.sha256, etc.).

The central type is EVPobject, which wraps an OpenSSL EVP_MD_CTX pointer. Each EVPobject instance represents an in-progress hash computation: you push data in with update, and retrieve the digest with digest or hexdigest. The state is mutable and not thread-safe — callers are responsible for locking if the same object is shared across threads.

The module also exposes _hashlib.new(name, data=b"", *, usedforsecurity=True) to construct a hash object by name, and _hashlib.openssl_md_meth_names as a frozenset of all algorithm names that the linked OpenSSL library supports.

When OpenSSL is unavailable (rare, usually embedded builds), CPython falls back to Modules/_blake2/ and Modules/sha*module.c pure-C implementations, but that fallback path is not in this file.

Map

LinesSymbolRolegopy
1-80includes, _hashlibstate, _hashlib_HASHXOF, EVP_MD_CTX typedefsPer-interpreter state struct and OpenSSL type aliases.module/hashlib/module.go:state
80-280EVPobject, EVPobject_new, EVPobject_dealloc, EVPobject_traverseHash-state object wrapping EVP_MD_CTX *. Holds name, ctx, lock.module/hashlib/module.go:EVPObject
280-450EVP_hash, _hashlib_HASH_update_implupdate(data) — hashes more data; releases GIL for large inputs.module/hashlib/module.go:Update
450-620_hashlib_HASH_digest_impl, _hashlib_HASH_hexdigest_impl, _hashlib_HASH_copy_impldigest(), hexdigest(), and copy(). All finalize into a scratch copy so the original state is unchanged.module/hashlib/module.go:Digest
620-820_hashlib_new_impl, EVP_new, py_digest_name_hashlib.new(name) — looks up the algorithm by name via EVP_get_digestbyname, allocates and returns an EVPobject.module/hashlib/module.go:New
820-1050_hashlib_openssl_md_meth_names, _hashlib_get_fips_mode, _hashlib_compare_digestModule-level utilities: algorithm name enumeration, FIPS mode query, and constant-time compare.module/hashlib/module.go:AlgorithmsAvailable
1050-1200_hashlibmodule, _hashlib_exec, PyInit__hashlibModule definition and entry point. Registers EVPobject type and module-level functions.module/hashlib/module.go:Module

Reading

EVPobject layout (lines 80 to 280)

cpython 3.14 @ ab2d84fe1023/Modules/_hashlibmodule.c#L80-280

typedef struct {
PyObject_HEAD
PyObject *name; /* algorithm name as a str, e.g. "sha256" */
EVP_MD_CTX *ctx; /* OpenSSL digest context — the live state */
PyThread_type_lock lock; /* NULL unless the object has been shared */
#ifdef PY_OPENSSL_HAS_SHAKE
int use_mutex;
#endif
} EVPobject;

The ctx field is the only mutable state: every call to update calls EVP_DigestUpdate(ctx, ...) in-place. Because EVP_MD_CTX is an opaque heap struct, EVPobject_dealloc must call EVP_MD_CTX_free to release it.

EVPobject does not subclass any existing Python type; it exposes PyBufferProcs so that memoryview(h) returns the current digest bytes without copying.

EVP_update GIL release (lines 280 to 450)

cpython 3.14 @ ab2d84fe1023/Modules/_hashlibmodule.c#L280-450

The update path releases the GIL when the input is large enough that OpenSSL's internal copies would stall other threads:

static int
EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
{
unsigned int process;
const unsigned char *cp = (const unsigned char *)vp;

while (len > 0) {
/* OpenSSL's EVP_DigestUpdate takes an unsigned int, not Py_ssize_t */
if (len > (Py_ssize_t)MUNCH_SIZE)
process = MUNCH_SIZE;
else
process = (unsigned int)len;
if (!EVP_DigestUpdate(self->ctx, (const void *)cp, process)) {
_setException(PyExc_ValueError, ...);
return -1;
}
len -= process;
cp += process;
}
return 0;
}

static PyObject *
_hashlib_HASH_update_impl(EVPobject *self, PyObject *obj)
{
Py_buffer view;
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) return NULL;

if (self->lock == NULL && view.len >= HASHXOF_DIGEST_SIZE) {
/* Release the GIL for large inputs. */
Py_BEGIN_ALLOW_THREADS
result = EVP_hash(self, view.buf, view.len);
Py_END_ALLOW_THREADS
} else {
result = EVP_hash(self, view.buf, view.len);
}
...
}

MUNCH_SIZE is INT_MAX (2^31 - 1) to respect the unsigned int argument of EVP_DigestUpdate. The GIL is released only when the input is large enough to make the lock acquisition worth it, currently gated on whether the input exceeds the XOF block size. For small inputs the GIL is held throughout to avoid the overhead of the Py_BEGIN_ALLOW_THREADS barriers.

EVP_digest finalization (lines 450 to 620)

cpython 3.14 @ ab2d84fe1023/Modules/_hashlibmodule.c#L450-620

digest() must not modify the live ctx so that update can be called again afterwards. It achieves this by copying the context into a temporary:

static PyObject *
_hashlib_HASH_digest_impl(EVPobject *self)
{
unsigned int digest_size;
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD_CTX *temp_ctx;

/* Work on a copy so the original stays live. */
temp_ctx = EVP_MD_CTX_new();
if (!EVP_MD_CTX_copy_ex(temp_ctx, self->ctx)) { ... }

if (!EVP_DigestFinal_ex(temp_ctx, digest, &digest_size)) { ... }
EVP_MD_CTX_free(temp_ctx);

return PyBytes_FromStringAndSize((const char *)digest, digest_size);
}

hexdigest calls the same logic and then hex-encodes the resulting bytes with _Py_strhex. copy() calls EVP_MD_CTX_copy_ex similarly, but keeps the copy alive as a new EVPobject rather than finalizing.

EVP_MAX_MD_SIZE is 64 bytes (512 bits), which covers SHA-512 and all smaller digests. XOF functions (SHAKE128, SHAKE256) use a different path that calls EVP_DigestFinalXOF with a caller-supplied length.

CPython 3.14 changes

Python 3.9 added the usedforsecurity=True keyword argument to new and to the constructor functions, allowing FIPS-mode builds to raise an error when non-FIPS algorithms are requested in a security context. The _hashlib.compare_digest function (constant-time comparison) was added in 3.3 and is unchanged in 3.14. BLAKE2 support moved from this file to a separate Modules/_blake2/ directory in 3.6 and is no longer present here.