Init commit
This commit is contained in:
parent
c50b7e8bd3
commit
954848a11a
7 changed files with 145 additions and 2 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/.vscode
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lore"
|
||||||
|
version = "1.0.0"
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "lore"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2018"
|
||||||
|
description = "Zero-dependency hashing algorithms"
|
||||||
|
license = "BSD-3-Clause"
|
||||||
|
readme = "README.md"
|
||||||
|
homepage = "https://git.palmoe.dk/vodofrede/lore/"
|
||||||
|
repository = "https://git.palmoe.dk/vodofrede/lore/"
|
||||||
|
keywords = ["algorithms", "compression", "cryptography", "md5", "hash"]
|
||||||
|
categories = ["algorithms", "compression", "cryptography"]
|
||||||
|
exclude = []
|
||||||
|
|
||||||
|
[dependencies]
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) <year> <owner>. All rights reserved.
|
Copyright (c) 2021 vodofrede. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
# lore
|
# Lore
|
||||||
|
|
||||||
|
Hashing algorithms. Currently only implements md5.
|
||||||
|
|
||||||
|
Doesn't use any dependencies.
|
||||||
|
|
||||||
|
Performance/stability not guaranteed.
|
||||||
|
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod md5;
|
114
src/md5.rs
Normal file
114
src/md5.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
// round functions as defined in RFC1321
|
||||||
|
const F: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| (x & y) | (!x & z);
|
||||||
|
const G: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| (x & z) | (y & !z);
|
||||||
|
const H: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| x ^ y ^ z;
|
||||||
|
const I: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| y ^ (x | !z);
|
||||||
|
|
||||||
|
// constants used in RFC132
|
||||||
|
const K: [u32; 64] = [
|
||||||
|
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||||
|
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||||
|
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||||
|
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||||
|
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||||
|
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||||
|
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||||
|
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||||||
|
];
|
||||||
|
|
||||||
|
// shifts per round
|
||||||
|
const S: [u32; 64] = [
|
||||||
|
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9,
|
||||||
|
14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15,
|
||||||
|
21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
|
||||||
|
];
|
||||||
|
|
||||||
|
fn op(
|
||||||
|
function: impl Fn(u32, u32, u32) -> u32,
|
||||||
|
state: (u32, u32, u32, u32),
|
||||||
|
word: u32,
|
||||||
|
index: usize,
|
||||||
|
) -> u32 {
|
||||||
|
function(state.1, state.2, state.3)
|
||||||
|
.wrapping_add(state.0)
|
||||||
|
.wrapping_add(word)
|
||||||
|
.wrapping_add(K[index])
|
||||||
|
.rotate_left(S[index])
|
||||||
|
.wrapping_add(state.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preprocess(msg: impl AsRef<[u8]>) -> Vec<u8> {
|
||||||
|
let mut message = msg.as_ref().to_vec();
|
||||||
|
let len_in_bits = message.len().wrapping_mul(8) as u64;
|
||||||
|
|
||||||
|
// padding
|
||||||
|
// add one bit first (le), then pad with zeroes
|
||||||
|
message.push(0b10000000);
|
||||||
|
while (message.len() * 8) % 512 != 448 {
|
||||||
|
message.push(0u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// append length
|
||||||
|
message.extend(len_in_bits.to_le_bytes());
|
||||||
|
|
||||||
|
message
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(input: impl AsRef<[u8]>) -> String {
|
||||||
|
let (a, b, c, d) = preprocess(input).chunks_exact(64).fold(
|
||||||
|
(0x67452301u32, 0xefcdab89u32, 0x98badcfeu32, 0x10325476u32),
|
||||||
|
|(mut a0, mut b0, mut c0, mut d0), chunk| {
|
||||||
|
let mut words = [0u32; 16];
|
||||||
|
for (word, c) in words.iter_mut().zip(chunk.chunks_exact(4)) {
|
||||||
|
*word = u32::from_le_bytes(c.try_into().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut a, mut b, mut c, mut d) = (a0, b0, c0, d0);
|
||||||
|
|
||||||
|
for i in (0..4).map(|i| i * 4) {
|
||||||
|
a = op(F, (a, b, c, d), words[i], i);
|
||||||
|
d = op(F, (d, a, b, c), words[i + 1], i + 1);
|
||||||
|
c = op(F, (c, d, a, b), words[i + 2], i + 2);
|
||||||
|
b = op(F, (b, c, d, a), words[i + 3], i + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (4..8).map(|i| i * 4) {
|
||||||
|
a = op(G, (a, b, c, d), words[(5 * i + 1) % 16], i);
|
||||||
|
d = op(G, (d, a, b, c), words[(5 * (i + 1) + 1) % 16], i + 1);
|
||||||
|
c = op(G, (c, d, a, b), words[(5 * (i + 2) + 1) % 16], i + 2);
|
||||||
|
b = op(G, (b, c, d, a), words[(5 * (i + 3) + 1) % 16], i + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (8..12).map(|i| i * 4) {
|
||||||
|
a = op(H, (a, b, c, d), words[(3 * i + 5) % 16], i);
|
||||||
|
d = op(H, (d, a, b, c), words[(3 * (i + 1) + 5) % 16], i + 1);
|
||||||
|
c = op(H, (c, d, a, b), words[(3 * (i + 2) + 5) % 16], i + 2);
|
||||||
|
b = op(H, (b, c, d, a), words[(3 * (i + 3) + 5) % 16], i + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (12..16).map(|i| i * 4) {
|
||||||
|
a = op(I, (a, b, c, d), words[(7 * i) % 16], i);
|
||||||
|
d = op(I, (d, a, b, c), words[(7 * (i + 1)) % 16], i + 1);
|
||||||
|
c = op(I, (c, d, a, b), words[(7 * (i + 2)) % 16], i + 2);
|
||||||
|
b = op(I, (b, c, d, a), words[(7 * (i + 3)) % 16], i + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
a0 = a0.wrapping_add(a);
|
||||||
|
b0 = b0.wrapping_add(b);
|
||||||
|
c0 = c0.wrapping_add(c);
|
||||||
|
d0 = d0.wrapping_add(d);
|
||||||
|
|
||||||
|
(a0, b0, c0, d0)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{:08x}{:08x}{:08x}{:08x}",
|
||||||
|
a.swap_bytes(),
|
||||||
|
b.swap_bytes(),
|
||||||
|
c.swap_bytes(),
|
||||||
|
d.swap_bytes()
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in a new issue