Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

native-ossl

native-ossl is an idiomatic Rust wrapper around the OpenSSL 3.x C library. It exposes the full EVP_* cryptographic API — hashing, symmetric encryption, MAC, asymmetric keys, key derivation, randomness, X.509, and TLS — through safe, zero-copy Rust types.

What it provides

  • Digests — streaming SHA-2, SHA-3, SHAKE (XOF), SM3 via DigestAlg + DigestCtx
  • Symmetric encryption — AES-GCM, AES-CBC, ChaCha20-Poly1305, and more via CipherAlg
  • MAC — HMAC, CMAC, KMAC via MacAlg + MacCtx
  • Asymmetric keys — RSA, ECDSA, Ed25519, X25519, ML-KEM, ML-DSA via Pkey<T>
  • Key derivation — HKDF, PBKDF2, scrypt via typed builders; raw KdfCtx for anything else
  • RandomnessRand::fill for simple use; RandCtx for seeded DRBG hierarchies
  • X.509 — certificate parsing, building, and self-signing via X509 and X509Builder
  • TLS — full TLS 1.2 / 1.3 client and server via SslCtx and Ssl
  • Library contexts — FIPS-provider isolation via LibCtx

What it does not do

  • Does not require OpenSSL headers at runtime; bindings are generated by bindgen at build time against the system’s installed headers.
  • Does not ship its own copy of OpenSSL; it links the system library dynamically.
  • Does not expose deprecated OpenSSL 1.x APIs (ENGINE, BN_* arithmetic, legacy cipher names, etc.).
  • Does not provide async I/O; Ssl is synchronous. Async wrappers are a separate concern and can be built on top of the BIO layer.

Minimum requirements

RequirementVersion
OpenSSL3.5.0 or later
Rust1.77 or later
bindgen (build dep)0.72 or later
pkg-configsystem

The build script enforces the OpenSSL version at compile time. If an older library is found, the build fails with a clear diagnostic message.

Quick example

#![allow(unused)]
fn main() {
use native_ossl::digest::DigestAlg;

// Fetch the algorithm descriptor once — it is Send + Sync and can be shared.
let sha256 = DigestAlg::fetch(c"SHA2-256", None)?;
assert_eq!(sha256.output_len(), 32);

// Stream arbitrary data through a stateful context.
let mut ctx = sha256.new_context()?;
ctx.update(b"hello, ")?;
ctx.update(b"world")?;

let mut out = [0u8; 32];
ctx.finish(&mut out)?;
println!("{}", hex::encode(out));
}

Crate layout

native-ossl/              workspace root
├── native-ossl-sys/      raw FFI (bindgen output, unsafe only)
├── native-ossl/          safe Rust wrappers (public API)
└── examples/
    └── encrypt-demo/     hybrid RSA-OAEP + AES-256-GCM demo

All public API lives in native-ossl. The native-ossl-sys crate is an implementation detail; callers never import it directly.