diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:48:02 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-02 21:48:02 +0300 |
| commit | b751d102f158968aab681cb663d27b4c32197f62 (patch) | |
| tree | 85d03609314559df7705c2cb0ab4e37ab6d9715f /src/checksum.rs | |
| parent | 295b09ca25edbccac65401ee84fa420dd3888aad (diff) | |
feat: add preview update channel
Diffstat (limited to 'src/checksum.rs')
| -rw-r--r-- | src/checksum.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/checksum.rs b/src/checksum.rs new file mode 100644 index 00000000..4f61a33c --- /dev/null +++ b/src/checksum.rs @@ -0,0 +1,67 @@ +use std::{ + fs::File, + io::{self, Read}, + path::Path, +}; + +use sha2::{Digest, Sha256}; + +pub(crate) fn verify_sha256(path: &Path, expected: &str) -> io::Result<()> { + let expected = expected.trim().to_ascii_lowercase(); + if expected.len() != 64 || !expected.chars().all(|ch| ch.is_ascii_hexdigit()) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "expected sha256 must be 64 hexadecimal characters", + )); + } + + let actual = file_sha256(path)?; + if actual != expected { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!("sha256 mismatch: expected {expected}, got {actual}"), + )); + } + Ok(()) +} + +fn file_sha256(path: &Path) -> io::Result<String> { + let mut file = File::open(path)?; + let mut hasher = Sha256::new(); + let mut buffer = [0u8; 64 * 1024]; + loop { + let read = file.read(&mut buffer)?; + if read == 0 { + break; + } + hasher.update(&buffer[..read]); + } + Ok(to_lower_hex(&hasher.finalize())) +} + +fn to_lower_hex(bytes: &[u8]) -> String { + const HEX: &[u8; 16] = b"0123456789abcdef"; + let mut output = String::with_capacity(bytes.len() * 2); + for &byte in bytes { + output.push(HEX[(byte >> 4) as usize] as char); + output.push(HEX[(byte & 0x0f) as usize] as char); + } + output +} + +#[cfg(test)] +mod tests { + use std::fs; + + #[test] + fn verifies_matching_sha256() { + let path = std::env::temp_dir().join(format!("herdr-checksum-test-{}", std::process::id())); + fs::write(&path, b"herdr").unwrap(); + let result = super::verify_sha256( + &path, + "78193ef266c1e3c2ce4ea2a86d7fc87e8c52799653faaac8536533a1c9300f82", + ); + let _ = fs::remove_file(&path); + assert!(result.is_ok()); + } +} |
