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.
| Feature | Stack | Build requirements |
|---|---|---|
backend-aws-lc | aws-lc-sys | C compiler, cmake |
backend-boring | boring-sys (BoringSSL) | C/C++ compiler, cmake, go |
backend-openssl | openssl-sys | OpenSSL headers/libs (libssl-dev / brew install openssl) |
backend-rust-crypto | sha2 + getrandom + subtle + zeroize | none (pure Rust) |
The public API is identical regardless of backend; switching is a manifest-only change.
§Features
no_std-compatible — only requiresalloc.- Auto-zeroizing input type — passwords are passed as a
Passwordnewtype whoseDropimpl wipes the backing buffer with the backend’s non-elidable zeroing primitive (OPENSSL_cleansefor the FFI backends,zeroize::Zeroizeforbackend-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>>, andPassword::from_bytes; - does not implement
Clone, so secrets aren’t silently duplicated; - does not implement
Display, and itsDebugimpl 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§
- Invalid
Hash - Error returned by
verifywhen 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.