Hash Generator — Rust source
Compute SHA-1, SHA-256, SHA-384 and SHA-512 hashes of any text at once, using the browser's native SubtleCrypto. Copy each digest. 100% client-side.
This is the Rust implementation — the same logic the interactive tool runs, in a shareable, citable form.
// hash — SHA-1 / SHA-256 / SHA-384 / SHA-512 digest of a UTF-8 string.
//
// Language: Rust
// CosmoDev polyglot showcase port of the `hash` tool.
// Ported from src/tools/HashGenerator.tsx — display source, part of CosmoDev's
// polyglot tool pages.
//
// Unkeyed SHA digests using the RustCrypto `sha1` and `sha2` crates. Rust's
// standard library deliberately ships no cryptographic primitives, so the
// idiomatic and secure path is the audited RustCrypto family — these are the
// de-facto standard hashing crates in the Rust ecosystem. Add to Cargo.toml:
//
// sha1 = "0.10"
// sha2 = "0.10"
//
// Behavior mirrors the TypeScript reference: UTF-8 input, lowercase hex
// output, and rejection of unknown algorithm names. Each digest is computed
// in a single call; no streaming state is retained between calls.
use sha1::Sha1;
// sha2 re-exports the `Digest` trait, so pulling it from here (rather than the
// underlying `digest` crate) keeps the Cargo.toml limited to sha1 + sha2.
use sha2::{Digest, Sha256, Sha384, Sha512};
/// Canonical algorithm names. The spellings match the TypeScript union so the
/// same string works across every port.
pub const SHA1: &str = "SHA-1";
pub const SHA256: &str = "SHA-256";
pub const SHA384: &str = "SHA-384";
pub const SHA512: &str = "SHA-512";
/// Errors returned by [`digest`]. Kept as a concrete enum (not a string) so
/// callers can `match` on the kind — the idiomatic Rust error shape.
#[derive(Debug, PartialEq, Eq)]
pub enum HashError {
/// The algorithm string was not one of the supported names.
UnknownAlgorithm(String),
}
impl std::fmt::Display for HashError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HashError::UnknownAlgorithm(a) => write!(f, "unsupported hash algorithm: {a}"),
}
}
}
impl std::error::Error for HashError {}
/// Lowercase hexadecimal encoding of a byte sequence.
///
/// Generic over `AsRef<[u8]>` so it accepts slices, arrays, and the
/// `GenericArray` output returned by `finalize()` without an intermediate
/// allocation. Lookup-table based to avoid the per-byte `format!` allocation
/// that clippy flags.
fn to_hex<T: AsRef<[u8]>>(bytes: T) -> String {
const HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
let bytes = bytes.as_ref();
let mut out = String::with_capacity(bytes.len() * 2);
for &b in bytes {
out.push(HEX_DIGITS[(b >> 4) as usize] as char);
out.push(HEX_DIGITS[(b & 0x0f) as usize] as char);
}
out
}
/// Compute the named digest of `text` and return it as lowercase hex.
///
/// `text` is treated as UTF-8 bytes (Rust `&str` is always valid UTF-8, so
/// no encoding step is needed). The `Digest` trait's `chain().finalize()`
/// is the idiomatic one-shot entry point: feed the bytes, consume the hasher,
/// and receive the fixed-length output.
pub fn digest(algorithm: &str, text: &str) -> Result<String, HashError> {
// Dispatch on the algorithm name. Each arm fixes the hasher type at
// compile time, so the digest length is statically determined.
let bytes = match algorithm {
SHA1 => Sha1::digest(text.as_bytes()).to_vec(),
SHA256 => Sha256::digest(text.as_bytes()).to_vec(),
SHA384 => Sha384::digest(text.as_bytes()).to_vec(),
SHA512 => Sha512::digest(text.as_bytes()).to_vec(),
other => return Err(HashError::UnknownAlgorithm(other.to_string())),
};
Ok(to_hex(bytes))
}
/// Compute every supported digest of `text`, returning a vector of
/// `(algorithm, hex)` pairs — the Rust equivalent of the Record the React
/// island renders. Each hash is independent; an unknown name short-circuits.
pub fn hash_all(text: &str) -> Result<Vec<(&'static str, String)>, HashError> {
[SHA1, SHA256, SHA384, SHA512]
.iter()
.map(|&alg| Ok((alg, digest(alg, text)?)))
.collect()
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →