Getting Started
Prerequisites
Install OpenSSL development headers (3.0.7 or later):
# Fedora / RHEL
sudo dnf install openssl-devel
# Ubuntu / Debian
sudo apt install libssl-dev pkg-config
# macOS (Homebrew)
brew install openssl@3
export PKG_CONFIG_PATH="$(brew --prefix openssl@3)/lib/pkgconfig"
Verify the version:
pkg-config --modversion openssl
# must print 3.0.7 or later
Adding the dependency
In your Cargo.toml:
[dependencies]
native-ossl = { path = "../native-ossl" }
The crate is not yet published to crates.io; use a path or git dependency for now.
First programme: SHA-256
use native_ossl::digest::DigestAlg;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let sha256 = DigestAlg::fetch(c"SHA2-256", None)?;
let mut ctx = sha256.new_context()?;
ctx.update(b"The quick brown fox jumps over the lazy dog")?;
let mut digest = [0u8; 32];
ctx.finish(&mut digest)?;
println!("{}", hex::encode(digest));
// d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
Ok(())
}
First programme: AES-256-GCM
use native_ossl::{
cipher::{AeadDecryptCtx, AeadEncryptCtx, CipherAlg},
rand::Rand,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let alg = CipherAlg::fetch(c"AES-256-GCM", None)?;
// Generate a random key and nonce.
let mut key = [0u8; 32];
let mut nonce = [0u8; 12];
Rand::fill(&mut key)?;
Rand::fill(&mut nonce)?;
let plaintext = b"secret message";
// Encrypt.
let mut enc = AeadEncryptCtx::new(&alg, &key, &nonce, None)?;
let mut ciphertext = vec![0u8; plaintext.len()];
let n = enc.update(plaintext, &mut ciphertext)?;
enc.finalize(&mut ciphertext[n..])?;
let mut tag = [0u8; 16];
enc.tag(&mut tag)?;
// Decrypt and verify.
let mut dec = AeadDecryptCtx::new(&alg, &key, &nonce, None)?;
dec.set_tag(&tag)?;
let mut recovered = vec![0u8; ciphertext.len()];
let n = dec.update(&ciphertext, &mut recovered)?;
dec.finalize(&mut recovered[n..])?;
assert_eq!(&recovered, plaintext);
println!("round-trip OK");
Ok(())
}
Error handling
Every fallible function returns Result<T, ErrorStack>. ErrorStack holds the full
OpenSSL error queue captured at the point of failure. It implements std::error::Error,
so it works with ? and Box<dyn Error> equally well.
#![allow(unused)]
fn main() {
match DigestAlg::fetch(c"NO-SUCH-ALGORITHM", None) {
Ok(_) => unreachable!(),
Err(e) => eprintln!("OpenSSL error: {e}"),
}
}
See Error Handling for a full treatment.