SNAPKITTYWEST's picture
chore: push full sov-kernel-monster content from local build
9425aed verified
Raw
History Blame Contribute Delete
1.93 kB
//! SHA-256d (Double SHA-256) Hashing
//! Prevents length-extension attacks
use sha2::{Sha256, Digest};
/// Compute SHA-256 hash of bytes
pub fn hash_bytes(data: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(data);
let result = hasher.finalize();
hex::encode(result)
}
/// Compute SHA-256 hash of string
pub fn hash_string(s: &str) -> String {
hash_bytes(s.as_bytes())
}
/// Compute SHA-256d (double SHA-256)
/// First hash produces hex string, second hash operates on that string
pub fn hash_double(data: &[u8]) -> String {
let first = hash_bytes(data);
hash_string(&first)
}
/// SnapSHA256d label format
/// Format: "snapsha256d:<64-char-hex>"
pub fn snapsha256d(data: &[u8]) -> String {
format!("snapsha256d:{}", hash_double(data))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sha256_empty() {
let hash = hash_bytes(b"");
assert_eq!(hash.len(), 64);
assert_eq!(
hash,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
);
}
#[test]
fn test_sha256d_empty() {
let hash = hash_double(b"");
assert_eq!(hash.len(), 64);
// Double hash of empty string
assert_ne!(hash, hash_bytes(b""));
}
#[test]
fn test_snapsha256d_format() {
let label = snapsha256d(b"test");
assert!(label.starts_with("snapsha256d:"));
assert_eq!(label.len(), 12 + 64); // "snapsha256d:" + 64 hex chars
}
#[test]
fn test_deterministic() {
let data = b"hello world";
let h1 = hash_double(data);
let h2 = hash_double(data);
assert_eq!(h1, h2);
}
#[test]
fn test_different_inputs() {
let h1 = hash_double(b"hello");
let h2 = hash_double(b"world");
assert_ne!(h1, h2);
}
}