Skip to main content

Modules/_hashopenssl.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/_hashopenssl.c

Modules/_hashopenssl.c implements the _hashlib C extension, which backs hashlib using OpenSSL's EVP (envelope) API. A second implementation (Modules/md5module.c, sha1module.c, etc.) provides fallback pure-C implementations for platforms without OpenSSL.

Map

LinesSymbolRole
1-200EVPobject struct, EVPnewHash object wrapping EVP_MD_CTX*
201-500EVP_update, EVP_digest, EVP_hexdigestCore update/finalize
501-800EVP_copyClone a hash state
801-1100openssl_md5, openssl_sha1, ..., openssl_sha3_256Named constructors
1101-1500hashlib_newhashlib.new(name) dispatch
1501-1800pbkdf2_hmacPBKDF2-HMAC key derivation
1801-2200hmac_new, hmac_digestHMAC via OpenSSL

Reading

EVPobject

Each hashlib.md5() / hashlib.sha256() / etc. call creates an EVPobject that wraps an OpenSSL EVP_MD_CTX*.

// CPython: Modules/_hashopenssl.c:166 EVPobject
typedef struct {
PyObject_HEAD
PyThread_type_lock lock; /* for thread-safe updates */
EVP_MD_CTX *ctx; /* OpenSSL context */
int usedforsecurity;
} EVPobject;

EVP_update

// CPython: Modules/_hashopenssl.c:342 EVP_update
static PyObject *
EVP_update(EVPobject *self, PyObject *args)
{
Py_buffer view;
if (!PyArg_ParseTuple(args, "y*:update", &view))
return NULL;
if (self->lock == NULL && view.len >= HASHXOF_LOCK_THRESHOLD)
self->lock = PyThread_allocate_lock();
if (self->lock != NULL)
PyThread_acquire_lock(self->lock, 1);
EVP_DigestUpdate(self->ctx, view.buf, view.len);
if (self->lock != NULL)
PyThread_release_lock(self->lock);
PyBuffer_Release(&view);
Py_RETURN_NONE;
}

Thread safety: update() acquires a per-object lock for large inputs. Short updates are unprotected (CPython GIL provides safety for those cases).

pbkdf2_hmac

Calls OpenSSL's PKCS5_PBKDF2_HMAC directly, which is significantly faster than a pure-Python PBKDF2 loop.

// CPython: Modules/_hashopenssl.c:1620 _hashlib_pbkdf2_hmac_impl
static PyObject *
_hashlib_pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
Py_buffer *password, Py_buffer *salt,
int iterations, Py_ssize_t dklen)
{
...
PKCS5_PBKDF2_HMAC(password->buf, password->len,
salt->buf, salt->len,
iterations, digest, dklen, dk);
...
}

gopy notes

Status: not yet ported. Go's crypto/md5, crypto/sha1, crypto/sha256, crypto/sha512, golang.org/x/crypto/sha3 cover the standard hash algorithms. pbkdf2_hmac maps to golang.org/x/crypto/pbkdf2. The hashlib.new(name) dispatch requires a registry mapping algorithm name strings to Go hash constructors. Thread safety is handled by Go's memory model without explicit locks.