diff --git a/Cargo.lock b/Cargo.lock index b97e50a..63896af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,4 +4,4 @@ version = 4 [[package]] name = "emsha" -version = "1.0.1" +version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 60c6594..a51ac72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ repository = "https://git.wntrmute.dev/wntrmute/emsha-rs" categories = ["cryptography", "no-std", "embedded"] keywords = ["sha256", "hmac", "hash", "embedded", "no_std"] license-file = "LICENSE" -version = "1.0.1" +version = "1.0.2" edition = "2024" publish = ["kellnr"] diff --git a/src/bin/sha256.rs b/src/bin/sha256.rs new file mode 100644 index 0000000..53e6f4e --- /dev/null +++ b/src/bin/sha256.rs @@ -0,0 +1,57 @@ +//! Demonstrator of SHA256 hashing. + +use emsha::{self, sha256, Hash}; +use emsha::hexstr::to_hex; +use std::fs::File; +use std::io::Read; +use std::io::{self, BufReader}; + +const CHUNK_SIZE: usize = 512; + +fn transmute_error(res: emsha::Result<()>) -> io::Result<()> { + match res { + Ok(_) => Ok(()), + Err(e) => return Err( + io::Error::new( + io::ErrorKind::Other, + format!("{:}", e), /* error */)), + } +} + +fn hash_file(path: &str) -> io::Result<()> { + let mut ctx = sha256::SHA256::default(); + + let file = File::open(path)?; + let mut reader = BufReader::with_capacity(CHUNK_SIZE, file); + + let mut buffer = vec![0u8; CHUNK_SIZE]; + + loop { + let bytes_read = reader.read(&mut buffer)?; + + if bytes_read == 0 { + break; // EOF reached + } + + transmute_error( ctx.update(&buffer[..bytes_read]))? + } + + let mut d: [u8; sha256::SIZE] = [0; sha256::SIZE]; + let mut h: [u8; sha256::HEX_SIZE] = [0; sha256::HEX_SIZE]; + transmute_error(ctx.finalize(&mut d))?; + to_hex(&d, &mut h); + + println!("{:} {:}", String::from_utf8_lossy(&h), path); + + Ok(()) +} + +fn main() -> io::Result<()>{ + let args: Vec = std::env::args().collect(); + + for i in 1..args.len() { + hash_file(args[i].as_str())?; + } + + Ok(()) +} \ No newline at end of file diff --git a/tests/common.rs b/src/hexstr.rs similarity index 78% rename from tests/common.rs rename to src/hexstr.rs index 9e446dc..02f3541 100644 --- a/tests/common.rs +++ b/src/hexstr.rs @@ -1,3 +1,4 @@ +//! Various utilities for encoding to and from hex strings. const LUT: [&str; 256] = [ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", @@ -25,7 +26,8 @@ const LUT: [&str; 256] = [ "fd", "fe", "ff", ]; -pub fn hexstr( +/// Convert the binary array in `input` to a hex-encoded array in `output`. +pub fn to_hex( input: &[u8; N], output: &mut [u8; M], ) { @@ -41,3 +43,21 @@ pub fn hexstr( i += 1; } } + +/// +pub fn from_hex( + input: &[u8; M], + output: &mut [u8; N], +) { + assert_eq!(M, N * 2); + let mut i: usize = 0; + let mut o: usize = 0; + + while i < input.len() { + let s = LUT[input[i] as usize].as_bytes(); + output[o] = s[0] << 4 + s[1]; + + i += 2; + o += 1; + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index f21c9ab..18c0d1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,3 +118,4 @@ pub trait Hash { mod common; pub mod hmac; pub mod sha256; +pub mod hexstr; \ No newline at end of file diff --git a/src/sha256.rs b/src/sha256.rs index 17f080a..ece3de4 100644 --- a/src/sha256.rs +++ b/src/sha256.rs @@ -31,6 +31,9 @@ const MB_SIZE: usize = 64; /// SIZE is the output size for a SHA-256 digest. pub const SIZE: usize = 32; +/// HEX_SIZE is the size for hex-encoded output. +pub const HEX_SIZE: usize = 64; + fn u32_to_chunk_in_place(x: u32, chunk: &mut [u8]) { assert!(chunk.len() >= 4); chunk[0] = ((x & 0xff000000) >> 24) as u8; diff --git a/tests/hmac.rs b/tests/hmac.rs index a05e7b6..7b9ca6a 100644 --- a/tests/hmac.rs +++ b/tests/hmac.rs @@ -1,5 +1,4 @@ -mod common; -use common::hexstr; +use emsha::hexstr::to_hex; use emsha::{Hash, Result, hmac, sha256}; #[test] @@ -16,7 +15,7 @@ fn test_hmac_00() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) @@ -33,7 +32,7 @@ fn test_hmac_01() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) @@ -53,7 +52,7 @@ fn test_hmac_02() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) @@ -74,7 +73,7 @@ fn test_hmac_03() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) @@ -92,7 +91,7 @@ fn test_hmac_04() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) @@ -109,7 +108,7 @@ fn test_hmac_05() -> Result<()> { let mut h = hmac::HMAC_SHA256::new(&k)?; h.update(input)?; h.finalize(&mut digest)?; - hexstr(&digest, &mut hdigest); + to_hex(&digest, &mut hdigest); assert_eq!(&hdigest, output); Ok(()) diff --git a/tests/sha256.rs b/tests/sha256.rs index 0b021db..08d0a6c 100644 --- a/tests/sha256.rs +++ b/tests/sha256.rs @@ -1,5 +1,4 @@ -mod common; -use common::hexstr; +use emsha::hexstr::to_hex; use emsha::sha256; use emsha::{Hash, Result}; @@ -65,7 +64,7 @@ fn test_golden_tests() -> Result<()> { while i < golden_tests.len() { h.update(golden_tests[i].input)?; h.finalize(&mut d)?; - hexstr(&d, &mut s); + to_hex(&d, &mut s); assert_eq!(s, golden_tests[i].output); h.reset()?;