zeroize

Securely clear secrets from memory using a simple trait that resists compiler optimization

Library
Cargo
v1.9.0
681 stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
71 /100 Good
Development Activity 76
Maintenance 36
Community 84
Maturity 60
Momentum 28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
79 /100 Good
Architecture 78
Code Quality 80
Innovation 75
Learning Curve 82

zeroize is the RustCrypto project’s crate for securely zeroing memory that holds secrets — passwords, keys, or any sensitive buffer — in a way that the compiler cannot silently optimize away. Ordinary memory writes intended to clear a secret are a classic target for dead-store elimination, since the compiler sees no further reads of the value; zeroize instead uses core::ptr::write_volatile and core::sync::atomic memory fences to force the write through, without relying on FFI, inline assembly, or platform-specific tricks.

The crate is no_std by default, has zero required dependencies, and works on WASM as well as embedded targets, making it usable anywhere from a bare-metal firmware image to a server-side cryptography stack. An optional derive feature (zeroize_derive) generates Zeroize/ZeroizeOnDrop implementations for structs and enums so an entire data structure can be cleared with one call or automatically zeroed when it goes out of scope. As one of the RustCrypto project’s foundational utility crates, zeroize is a near-universal dependency across the Rust cryptography ecosystem — used by TLS, key-management, and cryptocurrency wallet code wherever secret material needs to be reliably erased.

What You Get

  • A Zeroize trait implemented for Rust’s core numeric types, arrays, and slices, callable with a single .zeroize() method
  • #![no_std] support with no required dependencies, usable in embedded, WASM, and bare-metal contexts
  • An optional zeroize_derive-powered #[derive(Zeroize, ZeroizeOnDrop)] for automatically clearing whole structs and enums
  • Pure-Rust implementation using core::ptr::write_volatile and memory fences — no FFI, no inline assembly, no platform-specific code paths
  • Optional alloc/std feature flags for zeroizing heap-allocated collections like Vec and String

Common Use Cases

  • Clearing password buffers, private keys, or session tokens from memory immediately after use
  • Implementing Drop for structs holding cryptographic key material so secrets are erased automatically when they go out of scope
  • Building higher-level cryptography or key-management crates that need a dependable, audited zeroing primitive rather than rolling their own
  • Embedded and WASM cryptography where FFI-based zeroing tricks (e.g. calling explicit_bzero) aren’t available

Under The Hood

Architecture The crate centers on a single Zeroize trait defined in src/lib.rs (856 lines), implemented for primitive numeric types, fixed-size arrays, and slices, plus optional alloc/std implementations for Vec/String-like types gated behind feature flags. src/barrier.rs (102 lines) provides the core volatile-write-plus-fence primitive that the trait implementations call into, while src/aarch64.rs and src/x86.rs hold now-vestigial architecture-specific hooks (the crate’s own comments note these are no-op features retained for compatibility). An optional zeroize_derive proc-macro crate (a sibling in the same workspace) generates Zeroize/ZeroizeOnDrop impls for user-defined structs and enums, keeping the derive logic decoupled from the core zeroing primitive. Tech Stack Pure Rust, no_std by default with alloc/std opt-in features, Rust 2024 edition, MSRV 1.85; the only non-dev dependencies are optional (serde for serialization support, zeroize_derive for the derive macro), and the crate is part of a larger RustCrypto/utils Cargo workspace alongside many sibling utility crates (hex-literal, block-buffer, cpufeatures, etc.). Code Quality tests/ covers the trait’s plain-type implementations (tests/zeroize.rs), heap-allocated types under the alloc feature (tests/alloc.rs), and the derive macro’s generated code (tests/zeroize_derive.rs), giving reasonable confidence across both the manual and derive-based API surfaces. The workspace enforces a strict Clippy/rustc lint set (unsafe_code scrutiny, missing_docs, cast_* lints), and the crate’s core correctness claim — that writes aren’t optimized away — is inherently hard to unit-test and instead relies on documented use of write_volatile/atomic fences rather than empirical benchmarking in CI. API Design The API is deliberately minimal: one trait, one method (.zeroize()), plus an opt-in derive for structs — there’s very little to learn beyond calling .zeroize() on values that hold secrets, and the derive macro removes boilerplate for anyone building their own secret-holding types.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers