added md2 and md4, updated API to v2

This commit is contained in:
Frederik Palmø 2022-09-16 14:07:57 +02:00
parent 1c43531f3f
commit 167a6cb25a
12 changed files with 656 additions and 825 deletions

592
Cargo.lock generated
View File

@ -2,598 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "cast"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
dependencies = [
"rustc_version",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"bitflags",
"textwrap",
"unicode-width",
]
[[package]]
name = "criterion"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "lore"
version = "2.0.0"
dependencies = [
"criterion",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "plotters"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
[[package]]
name = "plotters-svg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
[[package]]
name = "serde"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -12,8 +12,3 @@ categories = ["algorithms", "compression", "cryptography"]
exclude = []
[dev-dependencies]
criterion = { version = "^0.3", features = ["html_reports"] }
[[bench]]
name = "md5"
harness = false

View File

@ -1,14 +0,0 @@
use criterion::*;
use lore::md5;
fn md5(c: &mut Criterion) {
c.bench_function("md5", |b| {
b.iter(|| {
let hash = md5::hash(black_box("tihi xd"));
hash.to_hex_string();
})
});
}
criterion_group!(benches, md5);
criterion_main!(benches);

1
rust-toolchain Normal file
View File

@ -0,0 +1 @@
nightly

View File

@ -1,10 +1,3 @@
use lore::md5;
fn main() {
let input = "lol xd";
assert_eq!(
md5::hash(input).to_hex_string(),
"982d7f24f8985a6baa5cf129acc73561"
);
println!("{}", lore::md2("abc"));
}

64
src/hash.rs Normal file
View File

@ -0,0 +1,64 @@
use std::fmt::Display;
pub mod md2;
pub mod md4;
pub mod md5;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Digest<const S: usize>([u8; S]);
impl<const S: usize> Display for Digest<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(
&self
.0
.iter()
.map(|u| format!("{:02x}", u))
.collect::<Vec<_>>()
.join(""),
)
}
}
pub(crate) fn bytes_to_words_le(bytes: impl AsRef<[u8]>) -> Vec<u32> {
bytes
.as_ref()
.array_chunks::<4>()
.map(|chunk| u32::from_le_bytes(*chunk))
.collect()
}
pub(crate) fn words_to_bytes_le(words: impl AsRef<[u32]>) -> Vec<u8> {
words
.as_ref()
.iter()
.flat_map(|w| w.to_le_bytes())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bytes_to_words_le_works() {
assert_eq!(
vec![0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476],
bytes_to_words_le([
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
0x32, 0x10
])
)
}
#[test]
fn words_to_bytes_le_works() {
assert_eq!(
vec![
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
0x32, 0x10
],
words_to_bytes_le([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476])
)
}
}

140
src/hash/md2.rs Normal file
View File

@ -0,0 +1,140 @@
use crate::hash::Digest;
/// see RFC1319
const S: [u8; 256] = [
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
];
fn pad(message: impl AsRef<[u8]>) -> Vec<u8> {
let mut message = message.as_ref().to_vec();
let padding_length = 16 - (message.len() % 16);
message.append(&mut vec![padding_length as u8; padding_length]);
message
}
fn checksum(message: impl AsRef<[u8]>) -> Vec<u8> {
let mut message = message.as_ref().to_vec();
let mut checksum = vec![0u8; 16];
let mut last = 0;
for block in message.array_chunks::<16>() {
for i in 0..16 {
checksum[i] ^= S[(block[i] ^ last) as usize];
last = checksum[i];
}
}
message.append(&mut checksum);
message
}
/// Compute the MD2 hash of the input bytes
/// # Examples
/// ```
/// let input = "abc";
/// let digest = lore::md2(input);
///
/// assert_eq!(digest.to_string(), "da853b0d3f88d99b30283a69e6ded6bb");
/// ```
pub fn hash(msg: impl AsRef<[u8]>) -> Digest<16> {
let padded = checksum(pad(msg));
let buffer = padded
.array_chunks::<16>()
.fold([0u8; 48], |mut buffer, chunk| {
// copy chunk into buffer
for i in 0..16 {
buffer[16 + i] = chunk[i];
buffer[32 + i] = buffer[16 + i] ^ buffer[i];
}
// do 18 rounds
let mut t = 0;
for i in 0..18 {
for b in buffer.iter_mut() {
*b ^= S[t as usize];
t = *b;
}
t = t.wrapping_add(i);
}
buffer
});
let digest = *buffer.array_chunks::<16>().next().unwrap();
Digest(digest)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn md2_pad() {
// assert that padding length is always correct
assert!(pad([]).len() % 16 == 0);
assert!(pad([0u8]).len() % 16 == 0);
assert!(pad([0u8; 15]).len() % 16 == 0);
assert!(pad([0u8; 16]).len() % 16 == 0);
assert!(pad([0u8; 476]).len() % 16 == 0);
// check some simple cases
assert_eq!(vec![16u8; 16], pad([]));
assert_eq!(
vec![0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15],
pad([0u8])
);
}
#[test]
fn md2_checksum() {
assert_eq!(
vec![
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 98, 56, 103, 182,
175, 82, 121, 94, 95, 33, 78, 151, 32, 190, 234, 141
],
checksum(vec![16u8; 16])
);
assert_eq!(
vec![
0u8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 41, 224, 10, 216,
109, 48, 122, 164, 206, 220, 139, 100, 42, 212, 254, 68
],
checksum(vec![
0u8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
])
);
}
#[test]
fn md2_hash() {
assert_eq!(
"a9046c73e00331af68917d3804f70655",
hash(b"hello").to_string()
);
assert_eq!("8350e5a3e24c153df2275c9f80692773", hash(b"").to_string());
assert_eq!("32ec01ec4a6dac72c0ab96fb34c0b5d1", hash(b"a").to_string());
assert_eq!("da853b0d3f88d99b30283a69e6ded6bb", hash(b"abc").to_string());
assert_eq!(
"03d85a0d629d2c442e987525319fc471",
hash(b"The quick brown fox jumps over the lazy dog").to_string()
);
}
}

239
src/hash/md4.rs Normal file
View File

@ -0,0 +1,239 @@
use crate::hash::{bytes_to_words_le, words_to_bytes_le, Digest};
// based on RFC1320
const A: u32 = 0x67452301;
const B: u32 = 0xefcdab89;
const C: u32 = 0x98badcfe;
const D: u32 = 0x10325476;
// additional constants for round 1, 2 & 3
const C1: u32 = 0;
const C2: u32 = 0x5a827999;
const C3: u32 = 0x6ed9eba1;
// shifts & indices for each step
const S: [u32; 48] = [
3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13,
3, 5, 9, 13, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15,
];
const W: [usize; 48] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14,
3, 7, 11, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15,
];
// round functions
const F: fn(u32, u32, u32) -> u32 = |x, y, z| (x & y) | (!x & z);
const G: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| (x & y) | (x & z) | (y & z);
const H: fn(u32, u32, u32) -> u32 = |x: u32, y: u32, z: u32| x ^ y ^ z;
// pad the message to next 512-bit interval
pub(crate) fn pad(message: impl AsRef<[u8]>) -> Vec<u8> {
let mut message = message.as_ref().to_vec();
let message_length = message.len().wrapping_mul(8) as u64;
// add 1 bit (le)
message.push(0x80);
// add 0 bits until length in bits is congruent to 448 mod 512
while (message.len()) % 64 != 56 {
message.push(0u8)
}
// append message length (64 bits)
message.extend(message_length.to_le_bytes());
message
}
// compute an invidiual step in the md4 algorithm
fn step([mut a, b, c, d]: [u32; 4], words: &[u32], index: usize) -> [u32; 4] {
// choose function and constant based on which round is currently active
let (rc, f) = match index {
0..=15 => (C1, F),
16..=31 => (C2, G),
32..=47 => (C3, H),
_ => panic!("This function shouldn't be called using an index outside 0..48"),
};
// main operation
a = f(b, c, d)
.wrapping_add(a)
.wrapping_add(words[W[index]])
.wrapping_add(rc)
.rotate_left(S[index]);
[a, b, c, d]
}
/// Compute the MD4 hash of the input bytes
/// # Examples
/// ```
/// let input = "abc";
/// let digest = lore::md4(input);
///
/// assert_eq!(digest.to_string(), "a448017aaf21d8525fc10ae87aa6729d");
/// ```
pub fn hash(message: impl AsRef<[u8]>) -> Digest<16> {
let padded = pad(message);
let buffer = padded.array_chunks::<64>().map(bytes_to_words_le).fold(
[A, B, C, D],
|[a, b, c, d], words| {
// perform rounds on this chunk of data
let mut state = [a, b, c, d];
for i in 0..48 {
state = step(state, &words, i);
state.rotate_right(1);
}
[
a.wrapping_add(state[0]),
b.wrapping_add(state[1]),
c.wrapping_add(state[2]),
d.wrapping_add(state[3]),
]
},
);
let digest = *words_to_bytes_le(buffer)
.array_chunks::<16>()
.next()
.unwrap();
Digest(digest)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn md4_pad() {
assert_eq!(pad([1u8]).len() % 64, 0);
assert_eq!(pad([1u8; 63]).len() % 64, 0);
assert_eq!(pad([1u8; 65]).len() % 64, 0);
assert_eq!(pad([1u8; 511]).len() % 64, 0);
assert_eq!(pad([1u8; 512]).len() % 64, 0);
assert_eq!(pad([1u8; 513]).len() % 64, 0);
assert_eq!(pad([1u8; 4472]).len() % 64, 0);
assert_eq!(
vec![
0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
],
pad([1u8])
);
}
#[test]
fn md4_hash() {
assert_eq!(
"1bee69a46ba811185c194762abaeae90",
hash("The quick brown fox jumps over the lazy dog").to_string()
);
assert_eq!(
"b86e130ce7028da59e672d56ad0113df",
hash("The quick brown fox jumps over the lazy cog").to_string()
);
assert_eq!("31d6cfe0d16ae931b73c59d7e0c089c0", hash("").to_string());
// RFC 1320 test suite
assert_eq!(hash("").to_string(), "31d6cfe0d16ae931b73c59d7e0c089c0");
assert_eq!(hash("a").to_string(), "bde52cb31de33e46245e05fbdbd6fb24");
assert_eq!(hash("abc").to_string(), "a448017aaf21d8525fc10ae87aa6729d");
assert_eq!(
hash("message digest").to_string(),
"d9130a8164549fe818874806e1c7014b"
);
assert_eq!(
hash("abcdefghijklmnopqrstuvwxyz").to_string(),
"d79e1c308aa5bbcdeea8ed63df412da9"
);
assert_eq!(
hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").to_string(),
"043f8582f241db351ce627e153e7f0e4"
);
assert_eq!(
hash(
"12345678901234567890123456789012345678901234567890123456789012345678901234567890"
)
.to_string(),
"e33b4ddc9c38f2199c3e7b164fcc0536"
);
assert_eq!(
hash("Rosetta Code").to_string(),
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
)
}
#[test]
fn md4_steps() {
let expected: [[u32; 4]; 48] = [
[0x2b9b7a8b, 0xefcdab89, 0x98badcfe, 0x10325476],
[0x1ebbf3f6, 0x2b9b7a8b, 0xefcdab89, 0x98badcfe],
[0xf636674f, 0x1ebbf3f6, 0x2b9b7a8b, 0xefcdab89],
[0x3e787c49, 0xf636674f, 0x1ebbf3f6, 0x2b9b7a8b],
[0x127b1453, 0x3e787c49, 0xf636674f, 0x1ebbf3f6],
[0x9c35a18a, 0x127b1453, 0x3e787c49, 0xf636674f],
[0x7e1c9145, 0x9c35a18a, 0x127b1453, 0x3e787c49],
[0x0adad780, 0x7e1c9145, 0x9c35a18a, 0x127b1453],
[0x85c62aed, 0x0adad780, 0x7e1c9145, 0x9c35a18a],
[0x881a850b, 0x85c62aed, 0x0adad780, 0x7e1c9145],
[0xf71e7006, 0x881a850b, 0x85c62aed, 0x0adad780],
[0x135c5da7, 0xf71e7006, 0x881a850b, 0x85c62aed],
[0x0727d7d9, 0x135c5da7, 0xf71e7006, 0x881a850b],
[0x9b7d493d, 0x0727d7d9, 0x135c5da7, 0xf71e7006],
[0x1e300fd2, 0x9b7d493d, 0x0727d7d9, 0x135c5da7],
[0xb60174a1, 0x1e300fd2, 0x9b7d493d, 0x0727d7d9],
[0x2a7873ab, 0xb60174a1, 0x1e300fd2, 0x9b7d493d],
[0x86074f26, 0x2a7873ab, 0xb60174a1, 0x1e300fd2],
[0x68021c3d, 0x86074f26, 0x2a7873ab, 0xb60174a1],
[0xc9ad2750, 0x68021c3d, 0x86074f26, 0x2a7873ab],
[0x6b1b8763, 0xc9ad2750, 0x68021c3d, 0x86074f26],
[0x329a0609, 0x6b1b8763, 0xc9ad2750, 0x68021c3d],
[0x3f3a2e5c, 0x329a0609, 0x6b1b8763, 0xc9ad2750],
[0x34e64be9, 0x3f3a2e5c, 0x329a0609, 0x6b1b8763],
[0x0de3f443, 0x34e64be9, 0x3f3a2e5c, 0x329a0609],
[0x5fddbd79, 0x0de3f443, 0x34e64be9, 0x3f3a2e5c],
[0x494abd6f, 0x5fddbd79, 0x0de3f443, 0x34e64be9],
[0x9069bba6, 0x494abd6f, 0x5fddbd79, 0x0de3f443],
[0x0d815e5e, 0x9069bba6, 0x494abd6f, 0x5fddbd79],
[0x753ed018, 0x0d815e5e, 0x9069bba6, 0x494abd6f],
[0xee224d71, 0x753ed018, 0x0d815e5e, 0x9069bba6],
[0xd232eb01, 0xee224d71, 0x753ed018, 0x0d815e5e],
[0x57e97dc9, 0xd232eb01, 0xee224d71, 0x753ed018],
[0x252ee4a0, 0x57e97dc9, 0xd232eb01, 0xee224d71],
[0x8d5bd7ef, 0x252ee4a0, 0x57e97dc9, 0xd232eb01],
[0x92942054, 0x8d5bd7ef, 0x252ee4a0, 0x57e97dc9],
[0x38475e43, 0x92942054, 0x8d5bd7ef, 0x252ee4a0],
[0x22f47377, 0x38475e43, 0x92942054, 0x8d5bd7ef],
[0xe6878422, 0x22f47377, 0x38475e43, 0x92942054],
[0x5ab5fed1, 0xe6878422, 0x22f47377, 0x38475e43],
[0x32463ee3, 0x5ab5fed1, 0xe6878422, 0x22f47377],
[0x85465040, 0x32463ee3, 0x5ab5fed1, 0xe6878422],
[0xb801aa18, 0x85465040, 0x32463ee3, 0x5ab5fed1],
[0xd796ec48, 0xb801aa18, 0x85465040, 0x32463ee3],
[0x5f8a08a4, 0xd796ec48, 0xb801aa18, 0x85465040],
[0x7b15aa48, 0x5f8a08a4, 0xd796ec48, 0xb801aa18],
[0x2722e8cf, 0x7b15aa48, 0x5f8a08a4, 0xd796ec48],
[0x11062517, 0x2722e8cf, 0x7b15aa48, 0x5f8a08a4],
];
// perform first step of md4 round 1
let words: [u32; 16] = [
0x65736f52, 0x20617474, 0x65646f43, 0x00000080, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000060, 0x00000000,
];
let mut state: [u32; 4] = [A, B, C, D];
#[allow(clippy::needless_range_loop)]
for i in 0..48 {
state = step(state, &words, i);
assert_eq!(expected[i], state);
state.rotate_right(1);
}
}
}

197
src/hash/md5.rs Normal file
View File

@ -0,0 +1,197 @@
use crate::hash::{bytes_to_words_le, md4::pad, words_to_bytes_le, Digest};
// based on RFC1321
const A: u32 = 0x67452301;
const B: u32 = 0xefcdab89;
const C: u32 = 0x98badcfe;
const D: u32 = 0x10325476;
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 & indices for each step
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,
];
const W: [usize; 64] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8,
13, 2, 7, 12, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, 0, 7, 14, 5, 12, 3, 10, 1,
8, 15, 6, 13, 4, 11, 2, 9,
];
// round functions
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);
fn step([mut a, b, c, d]: [u32; 4], words: &[u32], index: usize) -> [u32; 4] {
let f = match index {
0..=15 => F,
16..=31 => G,
32..=47 => H,
48..=63 => I,
_ => panic!("This function shouldn't be called using an index outside 0..48"),
};
a = f(b, c, d)
.wrapping_add(a)
.wrapping_add(words[W[index]])
.wrapping_add(K[index])
.rotate_left(S[index])
.wrapping_add(b);
[a, b, c, d]
}
/// Compute the MD5 hash of the input bytes
/// # Examples
/// ```
/// let input = "lol";
/// let digest = lore::md5(input);
///
/// assert_eq!(digest.to_string(), "9cdfb439c7876e703e307864c9167a15");
/// ```
pub fn hash(message: impl AsRef<[u8]>) -> Digest<16> {
let padded = pad(message);
let buffer = padded.array_chunks::<64>().map(bytes_to_words_le).fold(
[A, B, C, D],
|[a, b, c, d], words| {
println!("{words:08x?}");
let mut state = [a, b, c, d];
for i in 0..64 {
state = step(state, &words, i);
println!("{state:08x?}");
state.rotate_right(1);
}
[
a.wrapping_add(state[0]),
b.wrapping_add(state[1]),
c.wrapping_add(state[2]),
d.wrapping_add(state[3]),
]
},
);
let digest = *words_to_bytes_le(buffer)
.array_chunks::<16>()
.next()
.unwrap();
Digest(digest)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn md5_hash() {
assert_eq!("d41d8cd98f00b204e9800998ecf8427e", hash("").to_string());
assert_eq!(
"73e51861b65c1e83d6136fb6a002585e",
hash("tihi xd").to_string()
);
assert_eq!("9cdfb439c7876e703e307864c9167a15", hash("lol").to_string());
assert_eq!(
"fd6f92edff2b7db7cd92b494c4926ef0",
hash("Lorem ipsum dolor sit amet. Nam placeat iste aut dolorem necessitatibus sit unde magni. Nam cumque quia nam fugit quibusdam ut incidunt minima nam dignissimos iusto et voluptatum magnam. Et pariatur eius vel excepturi odit libero sit molestiae consequatur vel nostrum ullam. Sit sint beatae eos doloribus sapiente aut aperiam ullam ut laboriosam debitis! Qui reiciendis rerum est omnis galisum aut similique iure est dolores fuga sit rerum dicta. Aut excepturi fuga et enim ipsum a quia ut velit atque id iste nobis. Non molestiae vero et veritatis aliquam sed enim ducimus. At sunt tempora quo quisquam unde aut ipsum nulla et fugit eius in nulla fugit qui magnam excepturi aut rerum officia. Et officia magnam eos reiciendis voluptatum ea voluptas recusandae in similique enim. Ut provident laudantium ut temporibus eius ut laudantium voluptate aut ducimus impedit. Et asperiores aperiam sit deleniti voluptas ex porro omnis ut voluptas assumenda aut necessitatibus aliquid.").to_string()
);
}
#[test]
fn md5_steps() {
let expected: [[u32; 4]; 64] = [
[0x5954a129, 0xefcdab89, 0x98badcfe, 0x10325476],
[0x3171555d, 0x5954a129, 0xefcdab89, 0x98badcfe],
[0x24368ecc, 0x3171555d, 0x5954a129, 0xefcdab89],
[0x1d414db3, 0x24368ecc, 0x3171555d, 0x5954a129],
[0x9da81fec, 0x1d414db3, 0x24368ecc, 0x3171555d],
[0x983a9b4c, 0x9da81fec, 0x1d414db3, 0x24368ecc],
[0x01f76eec, 0x983a9b4c, 0x9da81fec, 0x1d414db3],
[0x82251f6b, 0x01f76eec, 0x983a9b4c, 0x9da81fec],
[0x3648b77a, 0x82251f6b, 0x01f76eec, 0x983a9b4c],
[0xa57749ed, 0x3648b77a, 0x82251f6b, 0x01f76eec],
[0x69859a5a, 0xa57749ed, 0x3648b77a, 0x82251f6b],
[0x8dd64e23, 0x69859a5a, 0xa57749ed, 0x3648b77a],
[0x4cc08388, 0x8dd64e23, 0x69859a5a, 0xa57749ed],
[0x9a1db095, 0x4cc08388, 0x8dd64e23, 0x69859a5a],
[0xf3a1ec18, 0x9a1db095, 0x4cc08388, 0x8dd64e23],
[0x68bf5f16, 0xf3a1ec18, 0x9a1db095, 0x4cc08388],
[0x08cf03db, 0x68bf5f16, 0xf3a1ec18, 0x9a1db095],
[0x03bceaa0, 0x08cf03db, 0x68bf5f16, 0xf3a1ec18],
[0x2809715f, 0x03bceaa0, 0x08cf03db, 0x68bf5f16],
[0xc305e2e6, 0x2809715f, 0x03bceaa0, 0x08cf03db],
[0x0386e9c7, 0xc305e2e6, 0x2809715f, 0x03bceaa0],
[0x0f4c9f59, 0x0386e9c7, 0xc305e2e6, 0x2809715f],
[0x8814e065, 0x0f4c9f59, 0x0386e9c7, 0xc305e2e6],
[0xd8d052d2, 0x8814e065, 0x0f4c9f59, 0x0386e9c7],
[0x8ff59707, 0xd8d052d2, 0x8814e065, 0x0f4c9f59],
[0x4069945d, 0x8ff59707, 0xd8d052d2, 0x8814e065],
[0x213a0570, 0x4069945d, 0x8ff59707, 0xd8d052d2],
[0xf2affb96, 0x213a0570, 0x4069945d, 0x8ff59707],
[0x555223a9, 0xf2affb96, 0x213a0570, 0x4069945d],
[0x37ba19ca, 0x555223a9, 0xf2affb96, 0x213a0570],
[0x003749f2, 0x37ba19ca, 0x555223a9, 0xf2affb96],
[0x20617338, 0x003749f2, 0x37ba19ca, 0x555223a9],
[0xf3e971ee, 0x20617338, 0x003749f2, 0x37ba19ca],
[0x4ec4ee85, 0xf3e971ee, 0x20617338, 0x003749f2],
[0xe62bf9a6, 0x4ec4ee85, 0xf3e971ee, 0x20617338],
[0x0ae8a02f, 0xe62bf9a6, 0x4ec4ee85, 0xf3e971ee],
[0xbc31561a, 0x0ae8a02f, 0xe62bf9a6, 0x4ec4ee85],
[0x6a9f6576, 0xbc31561a, 0x0ae8a02f, 0xe62bf9a6],
[0x42e91ea3, 0x6a9f6576, 0xbc31561a, 0x0ae8a02f],
[0x7a181668, 0x42e91ea3, 0x6a9f6576, 0xbc31561a],
[0xedcc403b, 0x7a181668, 0x42e91ea3, 0x6a9f6576],
[0x1fcae4da, 0xedcc403b, 0x7a181668, 0x42e91ea3],
[0x217c84d1, 0x1fcae4da, 0xedcc403b, 0x7a181668],
[0xf02591fa, 0x217c84d1, 0x1fcae4da, 0xedcc403b],
[0x5375b853, 0xf02591fa, 0x217c84d1, 0x1fcae4da],
[0xecd77499, 0x5375b853, 0xf02591fa, 0x217c84d1],
[0x4bd1053f, 0xecd77499, 0x5375b853, 0xf02591fa],
[0x7625a818, 0x4bd1053f, 0xecd77499, 0x5375b853],
[0xf7223b53, 0x7625a818, 0x4bd1053f, 0xecd77499],
[0x2e422a17, 0xf7223b53, 0x7625a818, 0x4bd1053f],
[0xe5235245, 0x2e422a17, 0xf7223b53, 0x7625a818],
[0x8e8a212d, 0xe5235245, 0x2e422a17, 0xf7223b53],
[0x551950d2, 0x8e8a212d, 0xe5235245, 0x2e422a17],
[0xf067530c, 0x551950d2, 0x8e8a212d, 0xe5235245],
[0xdb4e97cc, 0xf067530c, 0x551950d2, 0x8e8a212d],
[0x5b429768, 0xdb4e97cc, 0xf067530c, 0x551950d2],
[0xb0c06d7a, 0x5b429768, 0xdb4e97cc, 0xf067530c],
[0xd1906cf3, 0xb0c06d7a, 0x5b429768, 0xdb4e97cc],
[0x3fc74ed9, 0xd1906cf3, 0xb0c06d7a, 0x5b429768],
[0xa6b24624, 0x3fc74ed9, 0xd1906cf3, 0xb0c06d7a],
[0xf9d3c272, 0xa6b24624, 0x3fc74ed9, 0xd1906cf3],
[0x4e25ae2a, 0xf9d3c272, 0xa6b24624, 0x3fc74ed9],
[0x1db436d8, 0x4e25ae2a, 0xf9d3c272, 0xa6b24624],
[0x9350b12d, 0x1db436d8, 0x4e25ae2a, 0xf9d3c272],
];
let words: [u32; 16] = [
0x69686974, 0x80647820, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000038, 0x00000000,
];
let mut state = [A, B, C, D];
#[allow(clippy::needless_range_loop)]
for i in 0..64 {
state = step(state, &words, i);
assert_eq!(expected[i], state);
state.rotate_right(1);
}
}
}

7
src/hash/sha1.rs Normal file
View File

@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sha1() {}
}

View File

@ -1 +1,7 @@
pub mod md5;
#![feature(array_chunks)]
mod hash;
pub use hash::md2::hash as md2;
pub use hash::md4::hash as md4;
pub use hash::md5::hash as md5;

View File

@ -1,205 +0,0 @@
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,
];
pub struct Hash([u32; 4]);
impl Hash {
pub fn to_hex_string(&self) -> String {
format!(
"{:08x}{:08x}{:08x}{:08x}",
self.0[0], self.0[1], self.0[2], self.0[3]
)
}
}
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
}
#[inline(always)]
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)
}
pub fn hash(input: impl AsRef<[u8]>) -> Hash {
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);
// round 1
a = op(F, (a, b, c, d), words[0], 0);
d = op(F, (d, a, b, c), words[1], 1);
c = op(F, (c, d, a, b), words[2], 2);
b = op(F, (b, c, d, a), words[3], 3);
a = op(F, (a, b, c, d), words[4], 4);
d = op(F, (d, a, b, c), words[5], 5);
c = op(F, (c, d, a, b), words[6], 6);
b = op(F, (b, c, d, a), words[7], 7);
a = op(F, (a, b, c, d), words[8], 8);
d = op(F, (d, a, b, c), words[9], 9);
c = op(F, (c, d, a, b), words[10], 10);
b = op(F, (b, c, d, a), words[11], 11);