After 12 years of relying on OpenSSL, the maintainers of pyca/cryptography are charting a new course due to fundamental disagreements with OpenSSL's development trajectory since version 3.0.
The maintainers of pyca/cryptography have issued a stark assessment of their relationship with OpenSSL, declaring that the library's direction since version 3.0 has created problems so significant that they are actively reducing their dependence on it. This represents a major shift for one of Python's most widely-used cryptographic libraries, which has built its entire foundation on OpenSSL for over a decade.
The Three Acts of OpenSSL's Decline
Paul Kehrer and Alex Gaynor, who have maintained the library since its inception, frame OpenSSL's history as a three-act tragedy. The pre-Heartbleed era (pre-2014) saw OpenSSL languishing as an under-maintained project. The immediate post-Heartbleed period brought reinviguration: proper code review, continuous integration, fuzz testing, and mature release processes. But the third act, beginning with OpenSSL 3.0's release in 2021, has been marked by significant regressions across the board.
The maintainers argue that OpenSSL 3.0 introduced performance regressions, API complexity, and internal refactors that failed to deliver promised improvements in testing, verification, or memory safety. Meanwhile, OpenSSL's forks—LibreSSL, BoringSSL, and AWS-LC—have made meaningful progress in these exact areas.
Performance Regressions as a Design Failure
The performance story is particularly telling. When pyca/cryptography migrated X.509 certificate parsing from OpenSSL to their own Rust implementation, they achieved a 10x performance improvement. Moving public key parsing to Rust made end-to-end X.509 path validation 60% faster. These aren't micro-optimization wins; they're the result of avoiding OpenSSL's unnecessary copies, allocations, hash tables, indirect calls, and locks.
OpenSSL's maintainers acknowledged the 5-8x regression in elliptic curve public key loading that pyca/cryptography reported, but their response was telling: regression was expected, and they shouldn't expect performance to return to 1.1.1 levels. This resignation to poor performance reflects deeper design problems.
The OSSL_PARAM Catastrophe
OpenSSL 3's API changes, particularly the introduction of OSSL_PARAM, represent a fundamental misunderstanding of API design. Instead of normal function arguments, OpenSSL now passes arrays of key-value pairs. This approach reduces performance, eliminates compile-time verification, increases verbosity, and makes code harder to read.
The practical impact is stark: performing ML-KEM encapsulation takes 37 lines with 6 fallible calls in OpenSSL, compared to 19 lines with 3 fallible calls in BoringSSL. The design was apparently motivated by generic configuration parsing, but this theoretical flexibility has created real-world pain.
Provider API Complexity Spiral
The "providers" system, introduced to replace the ENGINE APIs, exemplifies OpenSSL's compounding design mistakes. The ability to replace any algorithm at any point in program execution necessitated locks and allocations throughout the codebase. When this created performance problems, OpenSSL added caching and eventually RCU (Read-Copy-Update)—a complex memory management strategy that introduced difficult-to-diagnose bugs.
The result: worse performance than before, increased complexity, and new bug classes. None of the OpenSSL forks have adopted this approach, suggesting it was never necessary.
Testing and Verification Gaps
The maintainers describe the Python Cryptographic Authority as "a CI engineering project that incidentally produces a cryptography library," highlighting their belief that testing investment yields disproportionate returns in correctness and development speed.
OpenSSL's testing gaps became visible during the 3.0 development cycle, which required 19 pre-releases over 16 months and still relied heavily on community-reported regressions. Bug fixes frequently land without regression tests. OpenSSL's CI is "exceptionally flaky," and the project has tolerated this flakiness to the point that it masked a critical buffer overflow in the RSA implementation on AVX-512 CPUs in version 3.0.4. The CI caught the crash, but because it only occurred on some runners, it was dismissed as flakiness.
Three years later, the project still merges code with failing tests. The day the pyca/cryptography maintainers prepared their conference slides, five of ten recent commits had failing CI checks. The day before their talk, every commit had failing cross-compilation builds.
Meanwhile, formal verification has moved from academic novelty to practical reality. BoringSSL and AWS-LC have incorporated formally verified implementations and use automated reasoning for increased assurance. OpenSSL has not kept pace.
The Memory Safety Imperative
When OpenSSL was created, memory-safe languages required sacrificing performance and adding garbage collectors. That world no longer exists. pyca/cryptography has been migrating to Rust since 2019, gaining performance and avoiding several OpenSSL CVEs in the process.
A library committed to security needs a long-term migration plan to memory-safe languages. The maintainers see no initiative from OpenSSL on this critical issue.
Funding Isn't the Problem
Many assume open-source problems stem from underfunding. Post-Heartbleed, OpenSSL has received considerable funding and employs more full-time engineers than work on BoringSSL or LibreSSL. The issues described aren't caused by resource constraints but by design choices that the forks have avoided.
A Fork in the Road
In response, pyca/cryptography is implementing a three-part strategy to reduce OpenSSL dependence:
No OpenSSL requirement for new features: Future APIs, such as ML-KEM and ML-DSA, may be added exclusively for LibreSSL, BoringSSL, and AWS-LC.
Binary wheel changes: The project is investigating switching its pre-compiled wheels from OpenSSL to one of its forks.
Alternative libraries: They're tracking non-OpenSSL-derived libraries like Graviola as potential future alternatives.
These changes won't happen hastily—the maintainers recognize the impact on users and redistributors—but they feel compelled to act given the gravity of their concerns.
The message to OpenSSL users is clear: if you want to avoid the most drastic steps, engage with OpenSSL and contribute to improvements in performance, API design, testing, and memory safety. The maintainers have given OpenSSL a roadmap of what needs fixing; whether the project can change course remains to be seen.
For a community that has relied on OpenSSL for decades, this represents both a warning and an opportunity. pyca/cryptography's move may push OpenSSL toward necessary reforms, or it may accelerate the fragmentation of the cryptographic library landscape. Either way, the era of unquestioning OpenSSL dependence is over.

Comments
Please log in or register to join the discussion