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/mod.rs | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/passwordmaker/base_conversion/mod.rs (limited to 'src/passwordmaker/base_conversion/mod.rs') diff --git a/src/passwordmaker/base_conversion/mod.rs b/src/passwordmaker/base_conversion/mod.rs new file mode 100644 index 0000000..705917a --- /dev/null +++ b/src/passwordmaker/base_conversion/mod.rs @@ -0,0 +1,65 @@ +use std::convert::TryInto; + +use self::remainders::CalcRemainders; + +mod remainders; +mod remainders_impl; + +/// Converts an input to a different base (which fits in usize). Returns the digits starting at the most significant one. +pub(super) trait BaseConversion { + // return type is subject to change. Hopefully soon the math will be rewritten, so we can skip the Vec and IntoIter. + // will have to remain an ExactSizeIterator though. + fn convert_to_base(self, base : usize) -> std::iter::Rev>; +} + +impl BaseConversion for T where T : ToI32Array{ + fn convert_to_base(self, base : usize) -> std::iter::Rev> { + self.to_int_array().calc_remainders(base).collect::>().into_iter().rev() + } +} + +impl BaseConversion for [u8;16]{ + fn convert_to_base(self, base : usize) -> std::iter::Rev> { + u128::from_be_bytes(self).calc_remainders(base as u128).map(|ll| ll as usize).collect::>().into_iter().rev() + } +} + + + +// Rust 1.52 only has a very limited support for const generics. This means, we'll have to live with this not-too-constrained solution... +// Well, it's private, so no big loss. +trait ToI32Array { + type Output; + fn to_int_array(self) -> Self::Output; +} + +//this could of course be done in a generic manner, but it's ugly without array_mut, which we don't have in Rust 1.52. +//Soo, pedestrian's approach :D +impl ToI32Array for [u8;20] { + type Output = [u32; 5]; + fn to_int_array(self) -> [u32; 5] { + [ + u32::from_be_bytes(self[0..4].try_into().unwrap()), + u32::from_be_bytes(self[4..8].try_into().unwrap()), + u32::from_be_bytes(self[8..12].try_into().unwrap()), + u32::from_be_bytes(self[12..16].try_into().unwrap()), + u32::from_be_bytes(self[16..20].try_into().unwrap()), + ] + } +} + +impl ToI32Array for [u8;32] { + type Output = [u32; 8]; + fn to_int_array(self) -> [u32; 8] { + [ + u32::from_be_bytes(self[0..4].try_into().unwrap()), + u32::from_be_bytes(self[4..8].try_into().unwrap()), + u32::from_be_bytes(self[8..12].try_into().unwrap()), + u32::from_be_bytes(self[12..16].try_into().unwrap()), + u32::from_be_bytes(self[16..20].try_into().unwrap()), + u32::from_be_bytes(self[20..24].try_into().unwrap()), + u32::from_be_bytes(self[24..28].try_into().unwrap()), + u32::from_be_bytes(self[28..32].try_into().unwrap()), + ] + } +} \ No newline at end of file -- cgit v1.2.3