From 86851fe70c0ff7ff1da98a82edabeef9c2ad989e Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Tue, 18 Oct 2022 21:18:23 +0200 Subject: Draft of iterative_conversion. --- src/passwordmaker/mod.rs | 56 +++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'src/passwordmaker/mod.rs') diff --git a/src/passwordmaker/mod.rs b/src/passwordmaker/mod.rs index a96698d..5e51ee9 100644 --- a/src/passwordmaker/mod.rs +++ b/src/passwordmaker/mod.rs @@ -1,10 +1,13 @@ -use std::iter::repeat; +use std::iter::SkipWhile; + use unicode_segmentation::UnicodeSegmentation; use leet::LeetReplacementTable; use grapheme::Grapheme; use base_conversion::BaseConversion; +use self::base_conversion::{IterativeBaseConversion, SixteenBytes, ArbitraryBytes}; + use super::Hasher; mod base_conversion; @@ -94,7 +97,6 @@ impl<'y, H : super::HasherList> super::PasswordMaker<'y, H>{ let message = yeet_upper_bytes(&message).collect::>(); let hash = H::MD5::hash(&message); let grapheme_indices = hash.convert_to_base(characters.len()); - let grapheme_indices = yoink_additional_graphemes_for_06_if_needed(grapheme_indices); GetGraphemesIterator { graphemes : characters, inner: GetGraphemesIteratorInner::V06(grapheme_indices)} } @@ -112,7 +114,6 @@ impl<'y, H : super::HasherList> super::PasswordMaker<'y, H>{ let data = yeet_upper_bytes(data); let hash = hmac::hmac::(key, data); let grapheme_indices = hash.convert_to_base(characters.len()); - let grapheme_indices = yoink_additional_graphemes_for_06_if_needed(grapheme_indices); GetGraphemesIterator { graphemes : characters, inner: GetGraphemesIteratorInner::V06(grapheme_indices)} } @@ -128,17 +129,17 @@ impl<'y, H : super::HasherList> super::PasswordMaker<'y, H>{ let data = leetified_data.as_deref().unwrap_or(data); let grapheme_indices = match algo { Algorithm::Md4 => - modern_hmac_to_grapheme_indices::(&key, data, characters.len()), + GetGraphemesIteratorInner::Modern16(modern_hmac_to_grapheme_indices::(&key, data, characters.len()).skip_while(is_zero)), Algorithm::Md5 => - modern_hmac_to_grapheme_indices::(&key, data, characters.len()), + GetGraphemesIteratorInner::Modern16(modern_hmac_to_grapheme_indices::(&key, data, characters.len()).skip_while(is_zero)), Algorithm::Sha1 => - modern_hmac_to_grapheme_indices::(&key, data, characters.len()), + GetGraphemesIteratorInner::Modern20(modern_hmac_to_grapheme_indices::(&key, data, characters.len()).skip_while(is_zero)), Algorithm::Sha256 => - modern_hmac_to_grapheme_indices::(&key, data, characters.len()), + GetGraphemesIteratorInner::Modern32(modern_hmac_to_grapheme_indices::(&key, data, characters.len()).skip_while(is_zero)), Algorithm::Ripemd160 => - modern_hmac_to_grapheme_indices::(&key, data, characters.len()), + GetGraphemesIteratorInner::Modern20(modern_hmac_to_grapheme_indices::(&key, data, characters.len()).skip_while(is_zero)), }; - GetGraphemesIterator { graphemes : characters, inner: GetGraphemesIteratorInner::Modern(grapheme_indices)} + GetGraphemesIterator { graphemes : characters, inner: grapheme_indices} } fn generate_password_part_modern<'a>( @@ -152,17 +153,17 @@ impl<'y, H : super::HasherList> super::PasswordMaker<'y, H>{ let message = pre_leet_level.as_ref().map(|l| l.leetify(&message)).unwrap_or(message); let grapheme_indices = match algo { Algorithm::Md4 => - modern_message_to_grapheme_indices::(&message, characters.len()), + GetGraphemesIteratorInner::Modern16(modern_message_to_grapheme_indices::(&message, characters.len()).skip_while(is_zero)), Algorithm::Md5 => - modern_message_to_grapheme_indices::(&message,characters.len()), + GetGraphemesIteratorInner::Modern16(modern_message_to_grapheme_indices::(&message,characters.len()).skip_while(is_zero)), Algorithm::Sha1 => - modern_message_to_grapheme_indices::(&message,characters.len()), + GetGraphemesIteratorInner::Modern20(modern_message_to_grapheme_indices::(&message,characters.len()).skip_while(is_zero)), Algorithm::Sha256 => - modern_message_to_grapheme_indices::(&message,characters.len()), + GetGraphemesIteratorInner::Modern32(modern_message_to_grapheme_indices::(&message,characters.len()).skip_while(is_zero)), Algorithm::Ripemd160 => - modern_message_to_grapheme_indices::(&message,characters.len()), + GetGraphemesIteratorInner::Modern20(modern_message_to_grapheme_indices::(&message,characters.len()).skip_while(is_zero)), }; - GetGraphemesIterator { graphemes : characters, inner: GetGraphemesIteratorInner::Modern(grapheme_indices)} + GetGraphemesIterator { graphemes : characters, inner: grapheme_indices} } } @@ -195,9 +196,15 @@ fn combine_prefix_password_suffix<'a, T : Iterator>>(password: .collect() } +fn is_zero(i : &usize) -> bool { + *i == 0 +} + enum GetGraphemesIteratorInner { - Modern(std::iter::Rev>), - V06(std::iter::Chain>, std::iter::Rev>>) + Modern16(SkipWhile,fn(&usize)->bool>), + Modern20(SkipWhile,usize>,fn(&usize)->bool>), + Modern32(SkipWhile,usize>,fn(&usize)->bool>), + V06(IterativeBaseConversion) } struct GetGraphemesIterator<'a> { graphemes : &'a Vec>, @@ -212,21 +219,23 @@ impl<'a> Iterator for GetGraphemesIterator<'a> { fn next(&mut self) -> Option { let idx = match &mut self.inner { - GetGraphemesIteratorInner::Modern(i) => i.next(), + GetGraphemesIteratorInner::Modern16(i) => i.next(), + GetGraphemesIteratorInner::Modern20(i) => i.next(), + GetGraphemesIteratorInner::Modern32(i) => i.next(), GetGraphemesIteratorInner::V06(i) => i.next(), }; idx.and_then(|idx| self.graphemes.get(idx).cloned()) } } -fn modern_hmac_to_grapheme_indices(key : &str, data: &str, divisor : usize) -> std::iter::Rev> +fn modern_hmac_to_grapheme_indices(key : &str, data: &str, divisor : usize) -> <::Output as BaseConversion>::Output where T:Hasher, ::Output: BaseConversion + AsRef<[u8]> { hmac::hmac::(key.bytes(), data.bytes()).convert_to_base(divisor) } -fn modern_message_to_grapheme_indices(data: &str, divisor : usize) -> std::iter::Rev> +fn modern_message_to_grapheme_indices(data: &str, divisor : usize) -> <::Output as BaseConversion>::Output where T:Hasher, ::Output: BaseConversion { @@ -307,11 +316,4 @@ impl AlgoSelection { #[allow(clippy::cast_possible_truncation)] //clippy, stop complaining. Truncating is the very purpose of this function... fn yeet_upper_bytes(input : &str) -> impl Iterator + Clone + '_ { input.encode_utf16().map(|wide_char| wide_char as u8) -} - -//signature subject to change, but need named types... -fn yoink_additional_graphemes_for_06_if_needed(input : std::iter::Rev>) - -> std::iter::Chain>, std::iter::Rev>> -{ - repeat(0_usize).take(32-input.len()).chain(input) } \ No newline at end of file -- cgit v1.2.3 From 36b7ec5ea805196749c7f10f1d8e03ae03564f2b Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Fri, 4 Nov 2022 20:51:12 +0100 Subject: More Clippy lints. Now Clippy is happy. --- .../base_conversion/iterative_conversion_impl/mod.rs | 10 +++++----- .../iterative_conversion_impl/precomputed_constants.rs | 14 +++++++------- src/passwordmaker/base_conversion/mod.rs | 1 + src/passwordmaker/mod.rs | 18 ++++++++++++++---- 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src/passwordmaker/mod.rs') diff --git a/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs b/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs index 3d5351a..b805272 100644 --- a/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs +++ b/src/passwordmaker/base_conversion/iterative_conversion_impl/mod.rs @@ -476,7 +476,7 @@ impl ArbitraryBytes{ } fn find_first_nonzero_digit(&self) -> usize{ - self.0.iter().enumerate().skip_while(|(_,v)| **v == 0).next().map(|(x,_)| x).unwrap_or(N) + self.0.iter().enumerate().find(|(_,v)| **v != 0).map_or(N,|(x,_)| x) } fn get_digit_from_right(&self, i : usize) -> u32{ @@ -504,7 +504,7 @@ impl ArbitraryBytes{ fn slice_overflowing_sub_assign(lhs : &mut [u32], rhs: &[u32]) -> bool{ debug_assert_eq!(lhs.len(), rhs.len()); lhs.iter_mut().zip(rhs.iter()).rev().fold(false,|carry,(a,b)| { - let r = b.overflowing_add(carry as u32); + let r = b.overflowing_add(u32::from(carry)); let s = a.overflowing_sub(r.0); *a = s.0; r.1 || s.1 @@ -514,7 +514,7 @@ fn slice_overflowing_sub_assign(lhs : &mut [u32], rhs: &[u32]) -> bool{ fn slice_overflowing_add_assign(lhs : &mut [u32], rhs : &[u32]) -> bool { debug_assert_eq!(lhs.len(), rhs.len()); lhs.iter_mut().zip(rhs.iter()).rev().fold(false, |carry, (a, b)| { - let r = b.overflowing_add(carry as u32); + let r = b.overflowing_add(u32::from(carry)); let s = a.overflowing_add(r.0); *a = s.0; r.1 || s.1 @@ -522,8 +522,8 @@ fn slice_overflowing_add_assign(lhs : &mut [u32], rhs : &[u32]) -> bool { } fn u64_from_u32s(m : u32, l : u32) -> u64{ - let m = m as u64; - let l = l as u64; + let m = u64::from(m); + let l = u64::from(l); (m << 32) | l } diff --git a/src/passwordmaker/base_conversion/iterative_conversion_impl/precomputed_constants.rs b/src/passwordmaker/base_conversion/iterative_conversion_impl/precomputed_constants.rs index e845176..1127692 100644 --- a/src/passwordmaker/base_conversion/iterative_conversion_impl/precomputed_constants.rs +++ b/src/passwordmaker/base_conversion/iterative_conversion_impl/precomputed_constants.rs @@ -4,17 +4,17 @@ use super::super::iterative_conversion::PrecomputedMaxPowers; impl PrecomputedMaxPowers for ArbitraryBytes<5>{ fn lookup(base : &usize) -> Option<(Self, usize)> { - get_from_cache(base, &CONSTANT_MAX_POWER_CACHE_5) + get_from_cache(*base, &CONSTANT_MAX_POWER_CACHE_5) } } impl PrecomputedMaxPowers for ArbitraryBytes<8>{ fn lookup(base : &usize) -> Option<(Self, usize)> { - get_from_cache(base, &CONSTANT_MAX_POWER_CACHE_8) + get_from_cache(*base, &CONSTANT_MAX_POWER_CACHE_8) } } -fn get_from_cache(base : &usize, cache : &[([u32;N], usize)]) -> Option<(ArbitraryBytes, usize)>{ +fn get_from_cache(base : usize, cache : &[([u32;N], usize)]) -> Option<(ArbitraryBytes, usize)>{ base.checked_sub(2).and_then(|idx|cache.get(idx)) .map(|c| (ArbitraryBytes(c.0), c.1)) } @@ -24,9 +24,9 @@ const CONSTANT_MAX_POWER_CACHE_8 : [([u32;8],usize);128] = gen_const_max_power_c //----------------------------------------------------------------------------------------- -/// This version of find_highest_fitting_power is not optimized. But it can run in const contexts. Only use it there, use the normal one everywhere else. +/// This version of `find_highest_fitting_power` is not optimized. But it can run in const contexts. Only use it there, use the normal one everywhere else. const fn const_find_highest_fitting_power(base : usize) -> ([u32;N],usize){ - let start = super::from_usize(&base); + let start = super::from_usize(base); let mut x = (start, 1); while let Some(next) = const_mul_usize(const_clone(&x.0),base) { @@ -81,7 +81,7 @@ mod iterative_conversion_constants_tests{ for (base, mut power, exponent) in entries { //exponent is the largest fitting exponent. Soo, if we divide exponent times, we should end up with 1. for _i in 0..exponent { - let remainder = power.div_assign_with_remainder_usize(&base); + let remainder = power.div_assign_with_remainder_usize(base); assert_eq!(remainder, 0); } assert_eq!(power, (&1usize).into()); @@ -95,7 +95,7 @@ mod iterative_conversion_constants_tests{ for (base, mut power, exponent) in entries { //exponent is the largest fitting exponent. Soo, if we divide exponent times, we should end up with 1. for _i in 0..exponent { - let remainder = power.div_assign_with_remainder_usize(&base); + let remainder = power.div_assign_with_remainder_usize(base); assert_eq!(remainder, 0); } assert_eq!(power, (&1usize).into()); diff --git a/src/passwordmaker/base_conversion/mod.rs b/src/passwordmaker/base_conversion/mod.rs index 6640880..6415904 100644 --- a/src/passwordmaker/base_conversion/mod.rs +++ b/src/passwordmaker/base_conversion/mod.rs @@ -14,6 +14,7 @@ pub(super) trait BaseConversion { fn convert_to_base(self, base : usize) -> Self::Output; } +#[allow(clippy::trait_duplication_in_bounds)] //False positive in clippy. usize != u32. impl BaseConversion for T where T : ToArbitraryBytes>, for<'a> T::Output: From<&'a usize> + From<&'a u32> + PaddedShiftLeft> + PrecomputedMaxPowers, diff --git a/src/passwordmaker/mod.rs b/src/passwordmaker/mod.rs index 61a0a95..c9ec1e3 100644 --- a/src/passwordmaker/mod.rs +++ b/src/passwordmaker/mod.rs @@ -201,15 +201,25 @@ fn combine_prefix_password_suffix<'a, T : Iterator>>(password: result } +#[allow(clippy::trivially_copy_pass_by_ref)] //signature is actually determined by Iterator::skip_while(). There's simply no choice. fn is_zero(i : &usize) -> bool { *i == 0 } +type BaseConversion16 = IterativeBaseConversion; +type BaseConversion16Modern = SkipWhilebool>; + +type BaseConversion20 = IterativeBaseConversion,usize>; +type BaseConversion20Modern = SkipWhilebool>; + +type BaseConversion32 = IterativeBaseConversion,usize>; +type BaseConversion32Modern = SkipWhilebool>; + enum GetGraphemesIteratorInner { - Modern16(SkipWhile,fn(&usize)->bool>), - Modern20(SkipWhile,usize>,fn(&usize)->bool>), - Modern32(SkipWhile,usize>,fn(&usize)->bool>), - V06(IterativeBaseConversion) + Modern16(BaseConversion16Modern), + Modern20(BaseConversion20Modern), + Modern32(BaseConversion32Modern), + V06(BaseConversion16) } struct GetGraphemesIterator<'a> { graphemes : &'a Vec>, -- cgit v1.2.3 From c385c90148178ad38b17491d45f5dcc2cbe06c9c Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Fri, 4 Nov 2022 21:31:36 +0100 Subject: Remove obsolete comment about base conversion. It's done, so no point in keeping the TODO around :D --- src/passwordmaker/mod.rs | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/passwordmaker/mod.rs') diff --git a/src/passwordmaker/mod.rs b/src/passwordmaker/mod.rs index c9ec1e3..405d469 100644 --- a/src/passwordmaker/mod.rs +++ b/src/passwordmaker/mod.rs @@ -224,9 +224,6 @@ enum GetGraphemesIteratorInner { struct GetGraphemesIterator<'a> { graphemes : &'a Vec>, inner : GetGraphemesIteratorInner - //There really should be a better solution than storing those values. If we had arbitrary-length multiplication and subtraction maybe? - //like, finding the highest potence of divisor that still is smaller than the dividend, and dividing by that one to get the left-most digit, - //dividing the remainder of this operation by the next-lower potence of divisor to get the second digit, and so on? } impl<'a> Iterator for GetGraphemesIterator<'a> { -- cgit v1.2.3