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

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.