From 3bfb55ece2f70fc9b1969a2ec9c55f7a00358b90 Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Tue, 11 Oct 2022 23:31:21 +0200 Subject: Refactor base_conversion. Fix hmac byte bug. Moved the basis conversion into a submodule, to ease the upcoming rewrite. Add a couple of new integration tests. Fix a bug caused by misreading the PasswordMaker Pro HMAC code. --- src/passwordmaker/base_conversion/remainders.rs | 74 +++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/passwordmaker/base_conversion/remainders.rs (limited to 'src/passwordmaker/base_conversion/remainders.rs') diff --git a/src/passwordmaker/base_conversion/remainders.rs b/src/passwordmaker/base_conversion/remainders.rs new file mode 100644 index 0000000..93570a1 --- /dev/null +++ b/src/passwordmaker/base_conversion/remainders.rs @@ -0,0 +1,74 @@ +/// Adds `calc_remainders(divisor)` method to types that have some implementation of the Division trait. +pub(super) trait CalcRemainders{ + fn calc_remainders(self, divisor : D) -> Remainders; +} + +/// Implement `Division` to enable the `calc_remainders()` method for your type. +pub(super) trait Division where Self:Sized { + /// does in-place arbitrary-length division. Returns remainder. + fn divide(self, divisor : &D) -> DivisionResult; + fn is_zero(&self) -> bool; +} + +/// Or mark your type as `UseGenericDivision` to just use `/` and `%` operators for types. Makes only sense for integers. +pub(super) trait UseGenericDivision : Clone + + for <'a> std::ops::Div<&'a Self, Output = Self> + + for <'a> std::ops::Rem<&'a Self, Output = Self> + + Default + + Eq {} + +impl CalcRemainders for T + where T:Division +{ + fn calc_remainders(self, divisor : D) -> Remainders { + Remainders::new(self,divisor) + } +} + +pub(super) struct Remainders{ + value : Option, + divisor : U, +} + +impl> Remainders { + fn new(value : T, divisor : U) -> Self { + let value = if value.is_zero() { None } else { Some(value) }; + Remainders { + value, + divisor, + } + } +} + +impl> Iterator for Remainders{ + type Item=U; + + fn next(&mut self) -> Option { + if let Some(v) = self.value.take() { + let DivisionResult{result, remainder} = v.divide(&self.divisor); + self.value = if result.is_zero() { None } else { Some(result) }; + Some(remainder) + } else { + None + } + } +} + +pub(super) struct DivisionResult, U> { + pub result : T, + pub remainder : U, +} + +impl Division for U + where U: UseGenericDivision +{ + fn divide(self, divisor : &Self) -> DivisionResult { + DivisionResult { + result: self.clone().div(divisor), + remainder: self.rem(divisor) + } + } + fn is_zero(&self) -> bool { + *self == Self::default() + } +} \ No newline at end of file -- cgit v1.2.3