aboutsummaryrefslogtreecommitdiff
path: root/src/passwordmaker/base_conversion/mod.rs
diff options
context:
space:
mode:
authorAndreas Grois <andi@grois.info>2022-10-11 23:31:21 +0200
committerAndreas Grois <andi@grois.info>2022-10-11 23:31:21 +0200
commit3bfb55ece2f70fc9b1969a2ec9c55f7a00358b90 (patch)
tree52d952ef77eaaf23598f51d59bfbf1f1b559ca04 /src/passwordmaker/base_conversion/mod.rs
parente5e3f40059239cba68d0ed8dd3c958545c80fbea (diff)
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.
Diffstat (limited to 'src/passwordmaker/base_conversion/mod.rs')
-rw-r--r--src/passwordmaker/base_conversion/mod.rs65
1 files changed, 65 insertions, 0 deletions
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<std::vec::IntoIter<usize>>;
+}
+
+impl<const N : usize, T> BaseConversion for T where T : ToI32Array<Output = [u32;N]>{
+ fn convert_to_base(self, base : usize) -> std::iter::Rev<std::vec::IntoIter<usize>> {
+ self.to_int_array().calc_remainders(base).collect::<Vec<_>>().into_iter().rev()
+ }
+}
+
+impl BaseConversion for [u8;16]{
+ fn convert_to_base(self, base : usize) -> std::iter::Rev<std::vec::IntoIter<usize>> {
+ u128::from_be_bytes(self).calc_remainders(base as u128).map(|ll| ll as usize).collect::<Vec<_>>().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