Skip to content

Commit

Permalink
add buffered hash in sha256
Browse files Browse the repository at this point in the history
  • Loading branch information
mimanshu-maheshwari committed Apr 4, 2024
1 parent 6148ab7 commit 216293c
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 94 deletions.
62 changes: 33 additions & 29 deletions examples/file-hasher.rs
Original file line number Diff line number Diff line change
@@ -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");
}
}
4 changes: 4 additions & 0 deletions src/hashes.rs
Original file line number Diff line number Diff line change
@@ -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<R: Read>(&mut self, handle: &mut R) -> String;
}
40 changes: 24 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Read> = 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());
}
142 changes: 95 additions & 47 deletions src/sha256.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<u8>,
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 {
Expand Down Expand Up @@ -78,9 +88,12 @@ impl Sha256 {
}
}

fn add_padding(temp_block_buf: &mut Vec<u8>) {
fn add_padding(temp_block_buf: &mut Vec<u8>, len: Option<usize>) {
// 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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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));
Expand All @@ -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<R: Read>(&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]
)
}
}
6 changes: 6 additions & 0 deletions src/sha512.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -109,6 +110,7 @@ const K: [u64; MESSAGE_SCHEDULE_SIZE] = [
0x6c44198c4a475817,
];

#[derive(Debug)]
pub struct Sha512 {
data: Vec<u8>,
}
Expand Down Expand Up @@ -227,6 +229,10 @@ impl Sha512 {
}

impl AhsahHasher for Sha512 {
fn hash_bufferd<R: Read>(&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());
Expand Down
3 changes: 1 addition & 2 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ 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)]
pub kind: HasherKind,

/// Path to file
#[arg(short, long)]
pub path: String,
pub path: Option<String>,
}

#[allow(unused)]
Expand Down

0 comments on commit 216293c

Please sign in to comment.