Skip to main content

openssl-encrypt-randomx

Project-owned RandomX KDF bindings for openssl-encrypt (gitlab#285), wrapping the official tevador/RandomX C library — vendored in-tree and pinned at v1.1.10 (f9ae3f235183c452962edd2a15384bdc67f7a11e, see RANDOMX_PIN). This is the exact upstream version the abandoned PyPI RandomX binding vendors, so KDF output is byte-identical and existing encrypted files keep decrypting.

API

import randomx_native

vm = randomx_native.RandomX(key)              # light mode (256 MB cache)
vm = randomx_native.RandomX(key, full_mem=True)  # fast mode (2080 MB dataset)
digest = vm.calculate_hash(data)              # -> 32 bytes

The constructor signature matches the reference binding (RandomX(key, full_mem=False, secure=..., large_pages=False, threads=0)), so it is a drop-in for the surface openssl_encrypt uses.

Security posture

Deliberate divergences from the reference binding (output is unaffected):

  • secure=True by default: JIT pages are never writable and executable at the same time (W^X). Opt out explicitly if you must. jit=False forces the interpreted VM entirely; strict=True raises instead of silently degrading when a requested configuration is unavailable, and vm.flags / vm.requested_flags / vm.degraded expose what actually happened (SECURE is reported only while a JIT is active).
  • No process aborts from the C++ library: page-protection or allocation failures inside RandomX (SELinux/PaX/seccomp denying mprotect, exhausted mappings) throw C++ exceptions with no internal catch; a project-owned shim (src/rxs_shim.cpp) converts them into Python RuntimeErrors instead of undefined behavior at the FFI boundary.
  • Empty keys are refused (ValueError) — an empty KDF key is always a bug.
  • Zeroization (Rust side): the binding's own copies of keys and hashed messages live in buffers wiped on drop (Rust zeroize), and calculate_hash_into(data, bytearray(32)) lets callers keep digests in wipeable buffers.
  • Thread safety: the VM serializes access internally; concurrent use from Python threads cannot corrupt the non-thread-safe C VM.
  • Portable hardware AES: no -march=native (builds are reproducible per architecture), but AES intrinsics are compiled in and runtime-gated (cpuid/hwcaps) — on AES-capable CPUs RandomX uses constant-time hardware AES exactly like the reference binding, instead of the table-based soft AES fallback (a cache-timing side channel and a KDF slowdown).
  • Supply chain: the C library is vendored verbatim (no network at build time) with recorded provenance (RANDOMX_PIN), a sha256 manifest (RANDOMX_SRC.sha256) recomputed by the test suite on every run, a committed Cargo.lock, and a build that refuses fast-math-style CFLAGS/CXXFLAGS (they would change KDF output). randomx_native.RANDOMX_UPSTREAM_COMMIT exposes the pin at runtime.

Known residuals, stated plainly: the vendored C library keeps a verbatim copy of the key in randomx_cache::cacheKey and (light mode) a second one in randomx_vm::cacheKey — both std::strings freed without wiping — and the 256 MB cache / 2080 MB dataset hold key-derived state the C API cannot wipe before release. In fast mode the cache (and its key copy) is released as soon as the dataset is initialized. Digests returned by calculate_hash are immutable Python bytes; use calculate_hash_into where the caller needs wipeable output. These residuals match or improve on the reference binding's behavior.

Building

pip install maturin
maturin build --release   # or: maturin develop --release

Requires a C/C++ toolchain (the vendored RandomX library is compiled into the extension) and Rust.

Releasing (maintainer, user-owned step)

CI (randomx-wheel job) builds the wheel + sdist on every development-branch pipeline and verifies the official RandomX v1.1.10 vector against the produced wheel. Publishing to PyPI is a manual release step, triggered from CI (preferred) or done locally as a fallback.

Preferred: the publish-randomx-pypi CI job (gitlab#285). On a pipeline whose randomx-wheel job succeeded, press its play button — it uploads the exact integrity-gated, vector-smoked randomx-dist/ artifact via twine, using the existing account-scoped PYPI_API_TOKEN_PROD CI variable (an account-scoped token is required for the very first upload, which creates the PyPI project — PyPI trusted publishing supports gitlab.com only, not this self-hosted instance). If that token is ever narrowed to per-project scope, give this job its own openssl-encrypt-randomx-scoped token. Note: PyPI accepts only manylinux/musllinux-tagged Linux wheels — if the wheel is rejected as plain linux_x86_64, upload the sdist alone and fix the wheel tagging (maturin audits the wheel automatically when the build environment allows it).

Fallback: local upload. Rebuild locally and re-run the same gates the CI job applies before uploading:

cd randomx_native
sha256sum -c --quiet RANDOMX_SRC.sha256      # vendored-tree integrity
maturin build --release -o dist && maturin sdist -o dist
pip install dist/openssl_encrypt_randomx-*.whl --force-reinstall
python3 -c "import randomx_native; \
  assert randomx_native.RandomX(b'test key 000').calculate_hash(b'This is a test').hex() \
  == '639183aae1bf4c9a35884cb46b09cad9175f04efd7684e7262a0ac1c2f0b4e3f'"
twine upload dist/*            # needs the maintainer's PyPI credentials

After the first publish, the requirements files can pin openssl-encrypt-randomx by version + --hash (closing review finding F3: --require-hashes becomes possible on every arch), and the aarch64 fork pin for the abandoned RandomX package can be retired.

Metadata

Release files for openssl-encrypt-randomx 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openssl-encrypt-randomx 1.0.0
File Size Uploaded
openssl_encrypt_randomx-1.0.0.tar.gz 133.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openssl-encrypt-randomx 1.0.0
File Interpreter ABI Platform
openssl_encrypt_randomx-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.34+ x86-64 Details

Total release size: 438.3 kB

Release files / openssl_encrypt_randomx-1.0.0.tar.gz

Download URL openssl_encrypt_randomx-1.0.0.tar.gz
Size 133.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3941e2cc7a314fc62ed6f3fbed5293473fd75ba734036593d9fcaef7ec16ea5e
BLAKE2b-256 checksum
How to use checksums
e00b0c57da5aca25d2088ada60d863ff00c67e010b274b7926fc9d90eda95c43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / openssl_encrypt_randomx-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl

Download URL openssl_encrypt_randomx-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl
Size 304.7 kB
Tags CPython 3.13 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
9f99b32abefa1f4482094b5a7a36dc4352b29306055fe72ae7fbc581b90d1da2
BLAKE2b-256 checksum
How to use checksums
7b5f26400a8f367cbe14c78fce40010e459de598d39114b7d484dc558a37faaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page