use digest::Digest;
use ripemd::Ripemd160;
use sha2::{Sha256, Sha512};
use sha3::{Keccak256, Sha3_256, Sha3_512};
#[must_use]
pub fn sha256(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn sha256d(data: &[u8]) -> [u8; 32] {
sha256(&sha256(data))
}
#[must_use]
pub fn sha512(data: &[u8]) -> [u8; 64] {
let mut hasher = Sha512::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn sha3_256(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha3_256::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn sha3_512(data: &[u8]) -> [u8; 64] {
let mut hasher = Sha3_512::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn keccak256(data: &[u8]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn ripemd160(data: &[u8]) -> [u8; 20] {
let mut hasher = Ripemd160::new();
hasher.update(data);
hasher.finalize().into()
}
#[must_use]
pub fn hash160(data: &[u8]) -> [u8; 20] {
ripemd160(&sha256(data))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sha256_empty() {
let hash = sha256(b"");
let expected = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
assert_eq!(hex::encode(hash), expected);
}
#[test]
fn test_sha256_hello() {
let hash = sha256(b"hello");
let expected = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824";
assert_eq!(hex::encode(hash), expected);
}
#[test]
fn test_sha256d() {
let hash = sha256d(b"hello");
let single = sha256(b"hello");
assert_ne!(hash, single);
assert_eq!(hash, sha256d(b"hello"));
}
#[test]
fn test_sha512_hello() {
let hash = sha512(b"hello");
assert_eq!(hash.len(), 64);
assert_eq!(hash, sha512(b"hello"));
}
#[test]
fn test_deterministic_hashing() {
let data = b"deterministic test";
assert_eq!(sha256(data), sha256(data));
assert_eq!(sha512(data), sha512(data));
assert_eq!(keccak256(data), keccak256(data));
assert_eq!(ripemd160(data), ripemd160(data));
}
#[test]
fn test_hash160() {
let data = b"test";
let hash = hash160(data);
assert_eq!(hash.len(), 20);
let manual = ripemd160(&sha256(data));
assert_eq!(hash, manual);
}
}
#[cfg(test)]
mod hex {
pub(crate) fn encode(bytes: impl AsRef<[u8]>) -> String {
bytes
.as_ref()
.iter()
.map(|b| format!("{:02x}", b))
.collect()
}
}