78 lines
2.2 KiB
Rust
78 lines
2.2 KiB
Rust
|
|
use std::{fs, io, str};
|
||
|
|
|
||
|
|
use sha2::{Digest, Sha256};
|
||
|
|
|
||
|
|
use crate::error::ValidateError;
|
||
|
|
|
||
|
|
pub struct HashChecker;
|
||
|
|
impl HashChecker {
|
||
|
|
pub fn check(filename: &str, expected_hash: &str) -> Result<(), ValidateError> {
|
||
|
|
let mut result = Ok(());
|
||
|
|
if filename != "stdout" && (!expected_hash.is_empty()) {
|
||
|
|
let actual_hash = HashChecker::sha256sum(filename);
|
||
|
|
if actual_hash != expected_hash {
|
||
|
|
result = Err(ValidateError::Sha256Mismatch);
|
||
|
|
}
|
||
|
|
match result {
|
||
|
|
Ok(()) => println!("✅ Checksum OK."),
|
||
|
|
Err(ValidateError::Sha256Mismatch) => println!(
|
||
|
|
"❌ Checksum verification failed for {filename}:\n expected: {expected_hash}\n got: {actual_hash}"),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
result
|
||
|
|
}
|
||
|
|
|
||
|
|
fn sha256sum(filename: &str) -> String {
|
||
|
|
let mut hasher = Sha256::new();
|
||
|
|
let mut file = fs::File::open(filename).unwrap();
|
||
|
|
|
||
|
|
io::copy(&mut file, &mut hasher).unwrap();
|
||
|
|
let computed_hash = hasher.finalize();
|
||
|
|
drop(file);
|
||
|
|
|
||
|
|
format!("{computed_hash:x}")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
macro_rules! assert_err {
|
||
|
|
($expression:expr, $($pattern:tt)+) => {
|
||
|
|
match $expression {
|
||
|
|
$($pattern)+ => (),
|
||
|
|
ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_check_api_fails_when_checksum_mismatch() {
|
||
|
|
let expected = "AAAA847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
|
||
|
|
|
||
|
|
assert_err!(
|
||
|
|
HashChecker::check("LICENCE.md", expected),
|
||
|
|
Err(ValidateError::Sha256Mismatch)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_sha256sum_api() {
|
||
|
|
let expected = "21d7847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
|
||
|
|
|
||
|
|
let actual = HashChecker::sha256sum("LICENCE.md");
|
||
|
|
|
||
|
|
assert_eq!(actual, expected);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_check_api_works_when_typical() {
|
||
|
|
let expected = "21d7847124bfb9d9a9d44af6f00d8003006c44b9ef9ba458b5d4d3fc5f81bde5";
|
||
|
|
|
||
|
|
let is_match = HashChecker::check("LICENCE.md", expected).is_ok();
|
||
|
|
|
||
|
|
assert!(is_match);
|
||
|
|
}
|
||
|
|
}
|