parent
f0789c977f
commit
3535fbd1f5
|
@ -0,0 +1,3 @@
|
||||||
|
[target.x86_64-unknown-linux-gnu]
|
||||||
|
linker = "/usr/bin/clang"
|
||||||
|
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Clink-arg=-Wl,--no-rosegment"]
|
|
@ -8,5 +8,8 @@ edition = "2021"
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
overflow-checks = false
|
overflow-checks = false
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
|
76
src/lib.rs
76
src/lib.rs
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
const SHA1_CONST: &[u32] = &[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
|
const SHA1_CONST: &[u32] = &[0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
|
||||||
|
|
||||||
|
fn u32_rotate_left(val: u32, places: u32) -> u32 {
|
||||||
|
val << places | (val >> (32 - places))
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SHA1Hash {
|
pub struct SHA1Hash {
|
||||||
len: usize,
|
len: usize,
|
||||||
data_len: usize,
|
data_len: usize,
|
||||||
|
@ -33,11 +37,14 @@ impl SHA1Hash {
|
||||||
let mut buffer = [0u32; 80];
|
let mut buffer = [0u32; 80];
|
||||||
|
|
||||||
let mut buffer_ndx = 0;
|
let mut buffer_ndx = 0;
|
||||||
for chunk_ndx in (0..self.chunk.len()).step_by(4) {
|
|
||||||
let mut word = [0u8; 4];
|
let mut chunk_ndx = 0;
|
||||||
|
let mut word = [0u8; 4];
|
||||||
|
while chunk_ndx < self.chunk.len() {
|
||||||
word.copy_from_slice(&self.chunk[chunk_ndx..chunk_ndx + 4]);
|
word.copy_from_slice(&self.chunk[chunk_ndx..chunk_ndx + 4]);
|
||||||
buffer[buffer_ndx] = u32::from_be_bytes(word);
|
buffer[buffer_ndx] = u32::from_be_bytes(word);
|
||||||
buffer_ndx += 1;
|
buffer_ndx += 1;
|
||||||
|
chunk_ndx += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ndx in buffer_ndx..80 {
|
for ndx in buffer_ndx..80 {
|
||||||
|
@ -54,7 +61,10 @@ impl SHA1Hash {
|
||||||
let mut f;
|
let mut f;
|
||||||
let mut k;
|
let mut k;
|
||||||
|
|
||||||
for (i, word) in buffer.iter().enumerate() {
|
let mut i = 0;
|
||||||
|
while i < buffer.len() {
|
||||||
|
let word = buffer[i];
|
||||||
|
|
||||||
match i {
|
match i {
|
||||||
0..=19 => {
|
0..=19 => {
|
||||||
f = d ^ (b & (c ^ d));
|
f = d ^ (b & (c ^ d));
|
||||||
|
@ -75,12 +85,14 @@ impl SHA1Hash {
|
||||||
_ => unreachable!("Loop range is 0 to 79"),
|
_ => unreachable!("Loop range is 0 to 79"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let temp = a.rotate_left(5) + f + e + k + word;
|
let temp = u32_rotate_left(a, 5) + f + e + k + word;
|
||||||
e = d;
|
e = d;
|
||||||
d = c;
|
d = c;
|
||||||
c = b.rotate_left(30);
|
c = u32_rotate_left(b, 30);
|
||||||
b = a;
|
b = a;
|
||||||
a = temp;
|
a = temp;
|
||||||
|
|
||||||
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state[0] += a;
|
self.state[0] += a;
|
||||||
|
@ -146,48 +158,60 @@ impl SHA1Hash {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
fn verify_sha1(buf: &[u8], expected_hash: &[u8; 20]) {
|
||||||
fn verify_single_block() {
|
|
||||||
let mut sha1 = SHA1Hash::new();
|
let mut sha1 = SHA1Hash::new();
|
||||||
|
|
||||||
let msg = "The quick brown fox jumps over the lazy dog\n";
|
sha1.digest(buf);
|
||||||
|
|
||||||
sha1.digest(msg.as_bytes());
|
|
||||||
|
|
||||||
let output = sha1.finalize();
|
let output = sha1.finalize();
|
||||||
|
|
||||||
|
assert_eq!(&output, expected_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_single_block() {
|
||||||
|
let msg = "The quick brown fox jumps over the lazy dog\n";
|
||||||
|
|
||||||
let expected_hash =
|
let expected_hash =
|
||||||
b"\xbe\x41\x77\x68\xb5\xc3\xc5\xc1\xd9\xbc\xb2\xe7\xc1\x19\x19\x6d\xd7\x6b\x55\x70";
|
b"\xbe\x41\x77\x68\xb5\xc3\xc5\xc1\xd9\xbc\xb2\xe7\xc1\x19\x19\x6d\xd7\x6b\x55\x70";
|
||||||
assert_eq!(&output, expected_hash);
|
|
||||||
|
verify_sha1(msg.as_bytes(), expected_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_multi_blocks() {
|
fn verify_multi_blocks() {
|
||||||
let mut sha1 = SHA1Hash::new();
|
|
||||||
|
|
||||||
let msg = "OOPSIE WOOPSIE!! Uwu We make a fucky wucky!! A wittle fucko boingo! The code monkeys at our headquarters are working VEWY HAWD to fix this!\n";
|
let msg = "OOPSIE WOOPSIE!! Uwu We make a fucky wucky!! A wittle fucko boingo! The code monkeys at our headquarters are working VEWY HAWD to fix this!\n";
|
||||||
|
|
||||||
sha1.digest(msg.as_bytes());
|
|
||||||
|
|
||||||
let output = sha1.finalize();
|
|
||||||
|
|
||||||
let expected_hash =
|
let expected_hash =
|
||||||
b"\x14\x09\x49\x37\xfb\x7c\x3c\x30\x02\xda\x1a\x8d\x30\x84\x7f\x1d\xc9\x2b\x36\x0b";
|
b"\x14\x09\x49\x37\xfb\x7c\x3c\x30\x02\xda\x1a\x8d\x30\x84\x7f\x1d\xc9\x2b\x36\x0b";
|
||||||
assert_eq!(&output, expected_hash);
|
|
||||||
|
verify_sha1(msg.as_bytes(), expected_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify_64_bytes() {
|
fn verify_64_bytes() {
|
||||||
let mut sha1 = SHA1Hash::new();
|
|
||||||
|
|
||||||
let msg = "a".repeat(64);
|
let msg = "a".repeat(64);
|
||||||
|
|
||||||
sha1.digest(msg.as_bytes());
|
|
||||||
|
|
||||||
let output = sha1.finalize();
|
|
||||||
|
|
||||||
let expected_hash =
|
let expected_hash =
|
||||||
b"\x00\x98\xba\x82\x4b\x5c\x16\x42\x7b\xd7\xa1\x12\x2a\x5a\x44\x2a\x25\xec\x64\x4d";
|
b"\x00\x98\xba\x82\x4b\x5c\x16\x42\x7b\xd7\xa1\x12\x2a\x5a\x44\x2a\x25\xec\x64\x4d";
|
||||||
assert_eq!(&output, expected_hash);
|
|
||||||
|
verify_sha1(msg.as_bytes(), expected_hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify_speed() {
|
||||||
|
let mut sha1 = SHA1Hash::new();
|
||||||
|
let size = 1048576; // 1024 bytes * 1024 * 1024 = 1GB
|
||||||
|
let buf = [0x55u8; 1024];
|
||||||
|
|
||||||
|
for _ in 0..size {
|
||||||
|
sha1.digest(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = sha1.finalize();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
&output,
|
||||||
|
b"\xa4\x14\xa6\x96\x2c\x6f\x87\x47\x7d\xf2\xc0\x10\xae\x36\x27\xe5\xf1\x9f\x0e\xed"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue