1-1.rs (1423B)
1 use cryptopals::utils::read_buffer; 2 3 fn main() -> Result<(), Box<dyn std::error::Error>> { 4 let hex_input = read_buffer()?; 5 let bytes = hex_to_bytes(&hex_input); 6 let base64_output = bytes_to_base64(&bytes); 7 8 println!("{}", base64_output); 9 10 Ok(()) 11 } 12 13 const BASE64_TABLE: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 14 15 fn hex_to_bytes(hex: &str) -> Vec<u8> { 16 hex.as_bytes() 17 .chunks(2) 18 .map(|chunk| { 19 let s = std::str::from_utf8(chunk).unwrap(); 20 u8::from_str_radix(s, 16).expect("Invalid hex") 21 }) 22 .collect() 23 } 24 25 fn bytes_to_base64(bytes: &[u8]) -> String { 26 let mut result = String::with_capacity((bytes.len() + 2) / 3 * 4); 27 28 for chunk in bytes.chunks(3) { 29 let b0 = chunk[0] as usize; 30 let b1 = chunk.get(1).map(|&b| b as usize).unwrap_or(0); 31 let b2 = chunk.get(2).map(|&b| b as usize).unwrap_or(0); 32 33 let n = (b0 << 16) | (b1 << 8) | b2; 34 35 result.push(BASE64_TABLE[(n >> 18) & 0x3F] as char); 36 result.push(BASE64_TABLE[(n >> 12) & 0x3F] as char); 37 38 if chunk.len() > 1 { 39 result.push(BASE64_TABLE[(n >> 6) & 0x3F] as char); 40 } else { 41 result.push('='); 42 } 43 44 if chunk.len() > 2 { 45 result.push(BASE64_TABLE[n & 0x3F] as char); 46 } else { 47 result.push('='); 48 } 49 } 50 result 51 }