From f8a7c5527aa5b00169794a71af0dacb4924b6ae9 Mon Sep 17 00:00:00 2001 From: beneth Date: Sun, 12 Apr 2020 19:08:43 +0200 Subject: [PATCH] Broken b64 implementation (Ugly and no padding) --- set1/chal1/src/main.rs | 91 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/set1/chal1/src/main.rs b/set1/chal1/src/main.rs index e912976..686174b 100644 --- a/set1/chal1/src/main.rs +++ b/set1/chal1/src/main.rs @@ -5,29 +5,88 @@ //// use std::env; +use std::convert::TryInto; +static BASE64_TABLE: &'static [char] = &['A','B','C','D','E','F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' ,'W' ,'X' ,'Y' ,'Z', + 'a','b','c','d','e','f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v' ,'w' ,'x' ,'y' ,'z', + '0','1','2','3','4','5', '6', '7', '8', '9', '+', '/']; + +/// Convert Hex String to char +/// +/// # Examples +/// +/// ~~~ +/// hex_to_char("49") => I +/// ~~~ +/// TODO: the name is not accurate. Take a string and convert to u8 fn hex_to_char(s: &str) -> Result { - u8::from_str_radix(s, 16).map(|n| n as char) + u8::from_str_radix(s, 16).map(|n| n as char) } fn main() { - let args: Vec = env::args().collect(); - let input = &args[1]; + let args: Vec = env::args().collect(); + let input = &args[1]; - let char_vec: Vec = input.chars().collect(); - let split = &char_vec.chunks(2) - .map(|chunk| chunk.iter().collect::()) - .collect::>(); + let mut input_str = String::new(); - // Printing the string in Ascii format - for decoding example - for (i, s) in split.iter().enumerate() { - match hex_to_char(s) { - Ok(s) => print!("{}", s), - Err(e) => println!("\nError decoding char '{}' at index {}", e, i), - } + let char_vec: Vec = input.chars().collect(); + let hex_char = &char_vec + .chunks(2) + .map(|chunk| chunk.iter().collect::()) + .collect::>(); + + // Printing the string in Ascii format - for decoding example + print!("Input string in ASCII is : « "); + for (i, s) in hex_char.into_iter().enumerate() { + match hex_to_char(s) { + Ok(s) => input_str.push(s), + Err(e) => println!("\nError decoding char '{}' at index {}", e, i), } - println!(); + } + println!(" »"); - // Now we can unroll the base64 algorithm - // We need to : http://www.herongyang.com/Encoding/Base64-Encoding-Algorithm.html + // Convert hex_char : Vec into Vec + // Warning: Panic if not base16 + // See this with .map_err if we need to improve : + // https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=e241493d100ecaadac3c99f37d0f766f + let hex: Vec = hex_char + .into_iter() + .map(|i| u8::from_str_radix(i, 16).unwrap()) + .collect(); + + println!(" Len is : {}, is it modulo 3-bytes ? {}", + &hex.len(), + if &hex.len()%3 == 0 { "true" } else { "false"} + ); + + print!("b64_encode({:?}) ==> ", &input_str); + + // Ugly right ? + for j in (0..hex.len()).step_by(3) { + let mut arr = [0u8;4]; + + // Must handle Padding here ! + // Index will be out of bound + // Find a way in rust to detect that ? or just compute here. + // Si padding 1 = '=' + arr[3] = 0 + // Si padding 2 = '==' + arr[3] & arr[4] = 0 + arr[0] = 0; + for i in 0..3 { + arr[i+1] = hex[i+j]; + } + let tmp = u32::from_be_bytes(arr); + let tmp1:usize = ((tmp>>18) & 0x3F).try_into().unwrap(); + let tmp2:usize = ((tmp>>12) & 0x3F).try_into().unwrap(); + + // If this fail we need to PAD '==' + let tmp3:usize = ((tmp>>6) & 0x3F).try_into().unwrap(); + // If this fail we need to PAD '=' + let tmp4:usize = ((tmp) & 0x3F).try_into().unwrap(); + + print!("{}", BASE64_TABLE[tmp1]); + print!("{}", BASE64_TABLE[tmp2]); + print!("{}", BASE64_TABLE[tmp3]); + print!("{}", BASE64_TABLE[tmp4]); + } + println!(); }