Skip to main content

Crate crypt_sha512

Crate crypt_sha512 

Source
Expand description

§crypt-sha512

A no_std-compatible Rust implementation of the SHA512-crypt password hashing algorithm ($6$ Unix crypt format), ported from Ulrich Drepper’s reference C implementation.

The four cryptographic primitives this crate needs — SHA-512, a CSPRNG, a constant-time comparison, and a non-elidable memory wipe — are delegated to a backend selected at build time via cargo features. This lets the crate slot into projects that have already standardized on a particular crypto stack without dragging in a second one.

§Backend selection

Exactly one of the following features must be enabled. There is no default; selecting zero or more than one is a compile error.

FeatureStackBuild requirements
backend-aws-lcaws-lc-sysC compiler, cmake
backend-boringboring-sys (BoringSSL)C/C++ compiler, cmake, go
backend-opensslopenssl-sysOpenSSL headers/libs (libssl-dev / brew install openssl)
backend-rust-cryptosha2 + getrandom + subtle + zeroizenone (pure Rust)

The public API is identical regardless of backend; switching is a manifest-only change.

§Features

  • no_std-compatible — only requires alloc.
  • Auto-zeroizing input type — passwords are passed as a Password newtype whose Drop impl wipes the backing buffer with the backend’s non-elidable zeroing primitive (OPENSSL_cleanse for the FFI backends, zeroize::Zeroize for backend-rust-crypto).
  • Timing-attack resistant — verification compares with the backend’s constant-time memcmp.
  • Cryptographically secure salts — generated with the backend’s CSPRNG.
  • Unix $6$ compatible — output is bit-identical to glibc / libxcrypt.

§Usage

[dependencies]
crypt-sha512 = { version = "1.0.0", default-features = false, features = ["backend-aws-lc"] }

§Hash a new password

use crypt_sha512::{hash, Password};

// Default work factor (5000 rounds), random salt
let h = hash(Password::from("hunter2".to_string()), None);

// Higher work factor for more sensitive deployments
let h = hash(Password::from("hunter2".to_string()), Some(100_000));

§Verify a password

use crypt_sha512::{hash, verify, InvalidHash, Password};

let stored = hash(Password::from("correct horse battery staple"), None);

assert_eq!(verify(Password::from("correct horse battery staple"), &stored), Ok(true));
assert_eq!(verify(Password::from("Tr0ub4dor&3"), &stored), Ok(false));

// Malformed hash strings are reported separately from a wrong password.
assert_eq!(verify(Password::from("anything"), "not a hash"), Err(InvalidHash));

verify distinguishes three outcomes:

  • Ok(true) — the hash parses and the password matches.
  • Ok(false) — the hash parses and the password does not match.
  • Err(InvalidHash) — the hash string is malformed; no comparison was performed. Useful for handling multiple hash types or detecting data corruption separately from authentication failures.

§Hash with an explicit salt (low-level)

For interoperability tests or when you need to control the salt directly:

use crypt_sha512::{hash_with_salt, Password};

let h = hash_with_salt(Password::from("password"), b"$6$rounds=10000$saltstring");
assert!(h.starts_with("$6$rounds=10000$saltstring$"));

§The Password type

Password is the only way to feed plaintext into this crate’s hashing functions. It deliberately:

  • accepts From<String>, From<&str>, From<Vec<u8>>, and Password::from_bytes;
  • does not implement Clone, so secrets aren’t silently duplicated;
  • does not implement Display, and its Debug impl elides the contents, so secrets can’t accidentally land in logs;
  • zeroes its buffer with the active backend’s non-elidable zeroing primitive on drop — including on panic.

Pass it by value into hash, hash_with_salt, or verify; the function takes ownership and the buffer is wiped before the call returns.

§Hash format

$6$[rounds=N$]salt$digest
  • $6$ — SHA512-crypt identifier.
  • rounds=N$ — optional; default is 5000. Values are clamped into [1000, 999_999_999] per the SHA-crypt spec.
  • salt — up to 16 bytes from the crypt base64 alphabet.
  • digest — 86 bytes, crypt base64.

§MSRV

Rust 1.81.

§License

BSD 2-Clause. See the LICENSE file in the repository.

§Provenance

The hashing algorithm is a direct port of Ulrich Drepper’s public-domain SHA-crypt reference implementation. The b64_from_24bit macro mirrors the shape of the original C macro; tests reuse Drepper’s published vectors.

Structs§

InvalidHash
Error returned by verify when the supplied hash string is not a well-formed SHA512-crypt ($6$…$…) value.
Password
A password whose backing memory is securely zeroed when dropped.

Functions§

hash
Hash a password with a freshly generated, cryptographically secure random salt.
hash_with_salt
Compute a SHA512-crypt ($6$) hash with an explicit, caller-provided salt.
verify
Verify a password against a SHA512-crypt ($6$) hash using constant-time comparison.