//// // Cryptopal set 1 chal 1 : https://cryptopals.com/sets/1/challenges/1 // Run with : // cargo run -- 49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d //// use std::env; /// Convert Hexadecimal Vec to String /// /// # Examples /// /// ~~~ /// let test: Vec = vec![String::from("41"), /// String::from("42")]; /// assert_eq!(hex_to_string(&test), "AB"); /// ~~~ fn hex_to_string(hex_char: &Vec) -> String { let mut output = String::new(); // Printing the string in Ascii format - for hexa to Ascii example for (i, s) in hex_char.into_iter().enumerate() { match u8::from_str_radix(&s, 16).map(|n| n as char) { Ok(s) => output.push(s), Err(e) => println!("\nError decoding char '{}' at index {}", e, i), } } output } /// Encode a Vector of bytes to Base64 and return the base 64 String /// /// # Examples /// /// ~~~ /// let test: Vec = vec![0x41, 0x42]; // "[A,B] in ascii" /// let b64_encode = base64_encode(&test); /// assert_eq!(b64_encode, "QUI="); /// ~~~ fn base64_encode(input: &Vec) -> String { 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', '+', '/']; let mut output = String::new(); for j in (0..input.len()).step_by(3) { let mut pad = 0; let mut arr = [0u8;4]; arr[0] = 0; for i in 0..3 { if i+j == input.len() { arr[i+1] = 0; pad = 1; } else if i+j > input.len() { arr[i+1] = 0; pad = 2; } else { arr[i+1] = input[i+j]; } } let tmp = u32::from_be_bytes(arr); let tmp1 = (tmp>>18) & 0x3F; let tmp2 = (tmp>>12) & 0x3F; output.push(BASE64_TABLE[tmp1 as usize]); output.push(BASE64_TABLE[tmp2 as usize]); if pad == 2 { output.push_str("=="); break } else { let tmp3 = (tmp>>6) & 0x3F; output.push(BASE64_TABLE[tmp3 as usize]); } if pad == 1 { output.push_str("="); break } else { let tmp4 = (tmp) & 0x3F; output.push(BASE64_TABLE[tmp4 as usize]); } } output } fn main() { // Test base64 encode() let test: Vec = vec![0x41, 0x42]; let b64_encode = base64_encode(&test); assert_eq!(b64_encode, "QUI="); // Test hex_to_string() let test: Vec = vec![String::from("41"), String::from("42")]; assert_eq!(hex_to_string(&test), "AB"); // Get command line argument let args: Vec = env::args().collect(); let input = &args[1]; let char_vec: Vec = input.chars().collect(); // Convert Vec to Vec with 2 hexadecimal chars // ie: ['4','1','4','2'] => ["41", "42"] let hex_char = &char_vec .chunks(2) .map(|chunk| chunk.iter().collect::()) .collect::>(); // 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(); // Convert Hexadecimal Vec to String // ie: ["41", "42"] => "AB" let input_str = hex_to_string(&hex_char); let output = base64_encode(&hex); println!("→ Input string is « {} »", input); println!("→ Hex String to ASCII « {} »", &input_str); println!("→ Base64 encode « {} »", output); }