cryptopals/set1/chal1/src/main.rs

103 lines
3.0 KiB
Rust

////
// Cryptopal set 1 chal 1 : https://cryptopals.com/sets/1/challenges/1
// Run with :
// cargo run -- 49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
////
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<char, std::num::ParseIntError> {
u8::from_str_radix(s, 16).map(|n| n as char)
}
fn main() {
let mut input_str = String::new();
let args: Vec<String> = env::args().collect();
let input = &args[1];
let char_vec: Vec<char> = input.chars().collect();
let hex_char = &char_vec
.chunks(2)
.map(|chunk| chunk.iter().collect::<String>())
.collect::<Vec<_>>();
// Printing the string in Ascii format - for hexa to Ascii example
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),
}
}
// Convert hex_char : Vec<String> into Vec<u8>
// 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<u8> = hex_char
.into_iter()
.map(|i| u8::from_str_radix(i, 16).unwrap())
.collect();
// TODO !
// TODO: Make not ugly and move to function b64_encode(Vec<u8>) -> str
// TODO !
let mut output = String::new();
for j in (0..hex.len()).step_by(3) {
let mut pad = 0;
let mut arr = [0u8;4];
arr[0] = 0;
for i in 0..3 {
if i+j == hex.len() {
arr[i+1] = 0;
pad = 1;
} else if i+j > hex.len() {
arr[i+1] = 0;
pad = 2;
} else {
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();
output.push(BASE64_TABLE[tmp1]);
output.push(BASE64_TABLE[tmp2]);
if pad == 2 {
output.push_str("==");
break
} else {
let tmp3:usize = ((tmp>>6) & 0x3F).try_into().unwrap();
output.push(BASE64_TABLE[tmp3]);
}
if pad == 1 {
output.push_str("=");
break
} else {
let tmp4:usize = ((tmp) & 0x3F).try_into().unwrap();
output.push(BASE64_TABLE[tmp4]);
}
}
println!("Input string is '{}'", input);
println!("Hex String to ASCII '{}'", &input_str);
println!("Base64 encode '{}'", output);
}