aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml4
-rw-r--r--benches/hashrate_16_hmac.rs73
-rw-r--r--src/passwordmaker/hmac.rs42
3 files changed, 82 insertions, 37 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 1f1d5c4..5d5ee1e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -46,5 +46,9 @@ name = "hashrate_16"
harness = false
[[bench]]
+name = "hashrate_16_hmac"
+harness = false
+
+[[bench]]
name = "leet"
harness = false
diff --git a/benches/hashrate_16_hmac.rs b/benches/hashrate_16_hmac.rs
new file mode 100644
index 0000000..9a8deb7
--- /dev/null
+++ b/benches/hashrate_16_hmac.rs
@@ -0,0 +1,73 @@
+mod mock_hashers;
+
+use std::time::Duration;
+
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use passwordmaker_rs::HashAlgorithm;
+use mock_hashers::Pwm;
+
+fn criterion_bench_16bytes_hmac_typical(c: &mut Criterion) {
+ let pwm = Pwm::new(
+ HashAlgorithm::HmacMd5,
+ passwordmaker_rs::UseLeetWhenGenerating::NotAtAll,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
+ "",
+ "",
+ 12,
+ "",
+ ""
+ ).unwrap();
+ c.bench_function("16 bytes HMAC typical", |b| b.iter(|| {
+ pwm.generate(
+ black_box("This is a long string. With many, many characters. For no particular reason.".to_owned()),
+ black_box("And another relatively long string for no reason other than it being long.".to_owned())
+ )
+ }));
+}
+
+fn criterion_bench_16bytes_hmac_full_divide(c: &mut Criterion) {
+ let pwm = Pwm::new(
+ HashAlgorithm::HmacMd5,
+ passwordmaker_rs::UseLeetWhenGenerating::NotAtAll,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
+ "",
+ "",
+ 20,
+ "",
+ ""
+ ).unwrap();
+ c.bench_function("16 bytes HMAC full divide", |b| b.iter(|| {
+ pwm.generate(
+ black_box("This is a long string. With many, many characters. For no particular reason.".to_owned()),
+ black_box("And another relatively long string for no reason other than it being long.".to_owned())
+ )
+ }));
+}
+
+fn criterion_bench_16bytes_hmac_worst_case(c: &mut Criterion) {
+ let pwm = Pwm::new(
+ HashAlgorithm::HmacMd5,
+ passwordmaker_rs::UseLeetWhenGenerating::NotAtAll,
+ "XY",
+ "",
+ "",
+ 128,
+ "",
+ ""
+ ).unwrap();
+ c.bench_function("16 bytes HMAC worst case", |b| b.iter(|| {
+ pwm.generate(
+ black_box("This is a long string. With many, many characters. For no particular reason.".to_owned()),
+ black_box("And another relatively long string for no reason other than it being long.".to_owned())
+ )
+ }));
+}
+
+criterion_group!(name = benches;
+ // This can be any expression that returns a `Criterion` object.
+ config = Criterion::default().significance_level(0.02).sample_size(500).measurement_time(Duration::from_secs(10));
+ targets = criterion_bench_16bytes_hmac_typical,
+ criterion_bench_16bytes_hmac_full_divide,
+ criterion_bench_16bytes_hmac_worst_case,
+);
+criterion_main!(benches);
diff --git a/src/passwordmaker/hmac.rs b/src/passwordmaker/hmac.rs
index 4c9d6aa..62b77fd 100644
--- a/src/passwordmaker/hmac.rs
+++ b/src/passwordmaker/hmac.rs
@@ -3,15 +3,13 @@ use crate::Hasher;
pub(super) fn hmac<T, K, M>(key : K, data : M) -> T::Output
where T : Hasher,
T::Output : AsRef<[u8]>,
- K : Iterator<Item=u8> + Clone,
+ K : Iterator<Item=u8>,
M : Iterator<Item=u8>,
{
- let key_len = key.clone().count();
- let key = if key_len > 64 {
- KeyOrHash::from_hash(T::hash(&key.collect::<Vec<_>>()))
- } else {
- KeyOrHash::from_key(key)
- };
+ let key = key.collect::<Vec<_>>();
+ let key_hash = if key.len() > 64 { Some(T::hash(&key)) } else { None };
+ let key = key_hash.as_ref().map(T::Output::as_ref).map(<&[u8]>::into_iter).unwrap_or_else(|| (&key).into_iter()).copied();
+
let key = key.chain(std::iter::repeat(0)); //if key[i] does not exist, use 0 instead.
let mut inner_pad = [0u8;64];
@@ -25,34 +23,4 @@ pub(super) fn hmac<T, K, M>(key : K, data : M) -> T::Output
let hash = T::hash(&inner_pad.iter().copied().chain(data).collect::<Vec<_>>());
T::hash(&outer_pad.iter().chain(hash.as_ref().iter()).copied().collect::<Vec<_>>())
-}
-
-enum KeyOrHash<K: Iterator<Item=u8>, H: AsRef<[u8]>> {
- Key(K),
- Hash{
- hash : H,
- idx : usize
- }
-}
-
-impl<K: Iterator<Item=u8>, H: AsRef<[u8]>> KeyOrHash<K, H>{
- fn from_key(key : K) -> Self {
- Self::Key(key)
- }
- fn from_hash(hash : H) -> Self {
- Self::Hash { hash, idx: 0 }
- }
-}
-
-impl<K: Iterator<Item=u8>, H: AsRef<[u8]>> Iterator for KeyOrHash<K, H>{
- type Item = u8;
- fn next(&mut self) -> Option<Self::Item> {
- match self {
- KeyOrHash::Key(k) => k.next(),
- KeyOrHash::Hash { hash: owned, idx } => {
- *idx += 1;
- owned.as_ref().get(*idx-1).copied()
- },
- }
- }
} \ No newline at end of file