From 216293cf2e96da84d8586fb9452174f5745fad5e Mon Sep 17 00:00:00 2001 From: MIMANSHU MAHESHWARI Date: Thu, 4 Apr 2024 23:00:39 +0530 Subject: [PATCH] add buffered hash in sha256 --- examples/file-hasher.rs | 62 ++++++++++-------- src/hashes.rs | 4 ++ src/main.rs | 40 ++++++----- src/sha256.rs | 142 +++++++++++++++++++++++++++------------- src/sha512.rs | 6 ++ src/utils.rs | 3 +- 6 files changed, 163 insertions(+), 94 deletions(-) diff --git a/examples/file-hasher.rs b/examples/file-hasher.rs index 832f825..f33a7a4 100644 --- a/examples/file-hasher.rs +++ b/examples/file-hasher.rs @@ -1,42 +1,46 @@ -use ahsah::{utils::{Args, HasherKind}, hashes::AhsahHasher, sha512::Sha512, sha256::Sha256}; +use ahsah::{ + hashes::AhsahHasher, + sha256::Sha256, + sha512::Sha512, + utils::{Args, HasherKind}, +}; +use clap::Parser; use std::{ fs::File, io::{BufReader, Read}, }; -use clap::Parser; - - fn main() { let args = Args::parse(); - let file = File::open(&args.path).expect("Unable to open file"); - let mut buf_reader = BufReader::new(file); - let mut buffer = [0; 1024]; - match &args.kind { - HasherKind::Sha512 =>{ - let mut hasher = Sha512::new(); - while let Ok(n) = buf_reader.read(&mut buffer) { - if n == 0 { - break; + if let Some(path) = &args.path { + let file = File::open(path).expect("Unable to open file"); + let mut buf_reader = BufReader::new(file); + let mut buffer = [0; 1024]; + match &args.kind { + HasherKind::Sha512 => { + let mut hasher = Sha512::new(); + while let Ok(n) = buf_reader.read(&mut buffer) { + if n == 0 { + break; + } + hasher.digest(&buffer[..n]); } - hasher.digest(&buffer[..n]); + println!("Hashing {} bytes", hasher.len()); + println!("{}", hasher.finish()); } - println!("Hashing {} bytes", hasher.len()); - println!("{}", hasher.finish()); - - - } , - HasherKind::Sha256 =>{ - let mut hasher = Sha256::new(); - while let Ok(n) = buf_reader.read(&mut buffer) { - if n == 0 { - break; + HasherKind::Sha256 => { + let mut hasher = Sha256::new(); + while let Ok(n) = buf_reader.read(&mut buffer) { + if n == 0 { + break; + } + hasher.digest(&buffer[..n]); } - hasher.digest(&buffer[..n]); + println!("Hashing {} bytes", hasher.len()); + println!("{}", hasher.finish()); } - println!("Hashing {} bytes", hasher.len()); - println!("{}", hasher.finish()); - - } , + } + } else { + panic!("File path not provided"); } } diff --git a/src/hashes.rs b/src/hashes.rs index aee5996..82f64f2 100644 --- a/src/hashes.rs +++ b/src/hashes.rs @@ -1,4 +1,8 @@ +use std::io::Read; + pub trait AhsahHasher { fn digest(&mut self, data: &[u8]); fn finish(&mut self) -> String; + + fn hash_bufferd(&mut self, handle: &mut R) -> String; } diff --git a/src/main.rs b/src/main.rs index 3e24b5c..34c531f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,33 @@ -use ahsah::{hashes::AhsahHasher, sha512::Sha512}; +use ahsah::{ + hashes::AhsahHasher, + sha256::Sha256, + sha512::Sha512, + utils::{Args, HasherKind}, +}; +use clap::Parser; use std::{ - env::args, fs::File, - io::{BufReader, Read}, + io::{stdin, BufReader, Read}, + path::Path, }; fn main() { - let mut hasher = Sha512::new(); - let file_path = match args().skip(1).next() { - Some(val) => val, - None => String::from("res/test.txt"), + let args = Args::parse(); + let mut handle: Box = match args.path { + Some(path) => { + let path = Path::new(&path); + Box::new(BufReader::new(File::open(path).unwrap())) + } + None => Box::new(stdin().lock()), }; - let file = File::open(&file_path).expect("Unable to open file"); - let mut buf_reader = BufReader::new(file); - let mut buffer = [0; 1024]; - while let Ok(n) = buf_reader.read(&mut buffer) { - if n == 0 { - break; + match args.kind { + HasherKind::Sha512 => { + let mut hasher = Sha512::new(); + println!("{}", hasher.hash_bufferd(&mut handle)); + } + HasherKind::Sha256 => { + let mut hasher = Sha256::new(); + println!("{}", hasher.hash_bufferd(&mut handle)); } - hasher.digest(&buffer[..n]); } - println!("Hashing {} bytes", hasher.len()); - println!("{}", hasher.finish()); } diff --git a/src/sha256.rs b/src/sha256.rs index 9472ea4..e2a6ad5 100644 --- a/src/sha256.rs +++ b/src/sha256.rs @@ -1,5 +1,6 @@ use super::hashes::AhsahHasher; use super::utils::{ch, maj, sigma_0, sigma_1, sum_0, sum_1}; +use std::io::prelude::Read; /// Message buffer size in bits const BUFFER_SIZE_BITS: usize = 512; @@ -30,13 +31,22 @@ const K: [u32; BUFFER_SIZE_U8] = [ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, ]; +#[derive(Debug)] pub struct Sha256 { data: Vec, + hashes: [u32; HASH_SIZE_U32], + chunk: [u32; BUFFER_SIZE_U32], + bytes_len: usize, } impl Sha256 { pub fn new() -> Self { - Self { data: Vec::new() } + Self { + data: Vec::new(), + hashes: H.clone(), + bytes_len: 0, + chunk: [0; BUFFER_SIZE_U32], + } } pub fn len(&self) -> usize { @@ -78,9 +88,12 @@ impl Sha256 { } } - fn add_padding(temp_block_buf: &mut Vec) { + fn add_padding(temp_block_buf: &mut Vec, len: Option) { // length of message in bits. - let l = temp_block_buf.len() * 8; + let l = match len { + None => temp_block_buf.len() * 8, + Some(val) => val * 8, + }; // add a bit at the end of message temp_block_buf.push(0x80u8); @@ -102,7 +115,7 @@ impl Sha256 { fn copy_buf_u8_to_u32(u8_block: &[u8], u32_block: &mut [u32; BUFFER_SIZE_U32], start: usize) { assert!( BUFFER_SIZE_U8 <= u8_block.len() - start, - "Remaining bits in buffer are {val}, Expected {BUFFER_SIZE_U8} bits", + "Remaining bytes in buffer are {val}, Expected {BUFFER_SIZE_U8} bytes", val = (u8_block.len() - start) ); for i in 0..BUFFER_SIZE_U32 { @@ -132,39 +145,21 @@ impl Sha256 { temp_block_buf.push((len >> 8) as u8 & 0xff); temp_block_buf.push((len >> 0) as u8 & 0xff); } -} - -impl AhsahHasher for Sha256 { - fn digest(&mut self, data: &[u8]) { - for byte in data { - self.data.push(byte.clone()); - } - } - - /// Main hasher function - fn finish(&mut self) -> String { - // let msg_len: usize = self.data.len(); - - // A single u32 in this buffer is a word of size 32 bits - let mut chunk = [0; BUFFER_SIZE_U32]; - - // read message data into temporary buffer. - - /* padding message start */ - Self::add_padding(&mut self.data); - /* padding message end */ - - let mut hash_value = H.clone(); - for i in (0..self.data.len()).step_by(BUFFER_SIZE_U8) { + fn hash_algo(&mut self, data: Option<&[u8]>) { + let data = match data { + Some(data) => data, + None => &self.data[..], + }; + for i in (0..data.len()).step_by(BUFFER_SIZE_U8) { // copy into active block buffer - Self::copy_buf_u8_to_u32(&mut self.data, &mut chunk, i); + Self::copy_buf_u8_to_u32(&data, &mut self.chunk, i); // initialize registers // message schedule array let mut w = [0; MESSAGE_SCHEDULE_SIZE]; - w[0..16].copy_from_slice(&chunk[..]); + w[0..16].copy_from_slice(&mut self.chunk[..]); for i in 16..MESSAGE_SCHEDULE_SIZE { let sigma_0 = sigma_0(w[i - 15], (7, 18, 3)); let sigma_1 = sigma_1(w[i - 2], (17, 19, 10)); @@ -173,33 +168,86 @@ impl AhsahHasher for Sha256 { .wrapping_add(w[i - 16]) .wrapping_add(w[i - 7]); } - let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = hash_value.clone(); + let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = &self.hashes.clone(); Self::compression( &w, ( &mut a, &mut b, &mut c, &mut d, &mut e, &mut f, &mut g, &mut h, ), ); - hash_value[0] = a.wrapping_add(hash_value[0]); - hash_value[1] = b.wrapping_add(hash_value[1]); - hash_value[2] = c.wrapping_add(hash_value[2]); - hash_value[3] = d.wrapping_add(hash_value[3]); - hash_value[4] = e.wrapping_add(hash_value[4]); - hash_value[5] = f.wrapping_add(hash_value[5]); - hash_value[6] = g.wrapping_add(hash_value[6]); - hash_value[7] = h.wrapping_add(hash_value[7]); + self.hashes[0] = a.wrapping_add(self.hashes[0]); + self.hashes[1] = b.wrapping_add(self.hashes[1]); + self.hashes[2] = c.wrapping_add(self.hashes[2]); + self.hashes[3] = d.wrapping_add(self.hashes[3]); + self.hashes[4] = e.wrapping_add(self.hashes[4]); + self.hashes[5] = f.wrapping_add(self.hashes[5]); + self.hashes[6] = g.wrapping_add(self.hashes[6]); + self.hashes[7] = h.wrapping_add(self.hashes[7]); + } + } +} + +impl AhsahHasher for Sha256 { + + fn hash_bufferd(&mut self, handle: &mut R) -> String { + let mut buffer = [0; BUFFER_SIZE_U8]; + while let Ok(n) = handle.read(&mut buffer) { + self.bytes_len += n; + if n == 0 { + break; + } else if n == BUFFER_SIZE_U8 { + self.hash_algo(Some(&buffer)); + } else { + let mut data = Vec::new(); + for d in &buffer[..n] { + data.push(*d); + } + Self::add_padding(&mut data, Some(self.bytes_len)); + self.hash_algo(Some(&data)); + } + } + format!( + "{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}", + self.hashes[0], + self.hashes[1], + self.hashes[2], + self.hashes[3], + self.hashes[4], + self.hashes[5], + self.hashes[6], + self.hashes[7] + ) + } + + fn digest(&mut self, data: &[u8]) { + for byte in data { + self.data.push(byte.clone()); } + } + + /// Main hasher function + fn finish(&mut self) -> String { + // let msg_len: usize = self.data.len(); + // A single u32 in this buffer is a word of size 32 bits + // let mut chunk = [0; BUFFER_SIZE_U32]; + + // read message data into temporary buffer. + + /* padding message start */ + Self::add_padding(&mut self.data, None); + /* padding message end */ + self.hash_algo(None); format!( "{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}{:08x}", - hash_value[0], - hash_value[1], - hash_value[2], - hash_value[3], - hash_value[4], - hash_value[5], - hash_value[6], - hash_value[7] + self.hashes[0], + self.hashes[1], + self.hashes[2], + self.hashes[3], + self.hashes[4], + self.hashes[5], + self.hashes[6], + self.hashes[7] ) } } diff --git a/src/sha512.rs b/src/sha512.rs index af2ef15..d6c937f 100644 --- a/src/sha512.rs +++ b/src/sha512.rs @@ -1,5 +1,6 @@ use super::hashes::AhsahHasher; use super::utils::{ch, maj, sigma_0, sigma_1, sum_0, sum_1}; +use std::io::Read; /// Message buffer size in bits const BUFFER_SIZE_BITS: usize = 1024; @@ -109,6 +110,7 @@ const K: [u64; MESSAGE_SCHEDULE_SIZE] = [ 0x6c44198c4a475817, ]; +#[derive(Debug)] pub struct Sha512 { data: Vec, } @@ -227,6 +229,10 @@ impl Sha512 { } impl AhsahHasher for Sha512 { + fn hash_bufferd(&mut self, _handle: &mut R) -> String { + todo!("implement the hash_bufferd for sha512"); + } + fn digest(&mut self, data: &[u8]) { for byte in data { self.data.push(byte.clone()); diff --git a/src/utils.rs b/src/utils.rs index 1f59a32..57a4245 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -13,7 +13,6 @@ pub enum HasherKind { #[derive(Parser, Debug)] #[command(version, about, long_about = None)] pub struct Args { - /// Type of hasher you want to run. // #[arg(short, long)] #[arg(short, long, value_enum)] @@ -21,7 +20,7 @@ pub struct Args { /// Path to file #[arg(short, long)] - pub path: String, + pub path: Option, } #[allow(unused)]