diff --git a/src/set1.rs b/src/set1.rs index 8001b9f..cd22874 100644 --- a/src/set1.rs +++ b/src/set1.rs @@ -8,36 +8,12 @@ pub struct Base64Bytes(Vec); impl std::fmt::Display for Base64Bytes { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Base64Bytes(digits) = self; - let mut r: Vec = digits - .iter() - .map(|d| match d { - 0..=25 => *d + ('A' as u8), - 26..=51 => *d - 26 + ('a' as u8), - 52..=61 => *d - 52 + ('0' as u8), - 62 => '+' as u8, - 63 => '/' as u8, - _ => panic!("Unexpected base64 digit '{}'", d), - }) - .collect(); - // Handle padding - let pad = '=' as u8; - match r.len() % 4 { - 0 => (), - 2 => { - r.push(pad); - r.push(pad); - } - 3 => r.push(pad), - _ => (), - } - - write!(f, "Base64({})", str::from_utf8(r.as_slice()).unwrap()) + write!(f, "Base64({})", self.to_base64_string()) } } impl Base64Bytes { - pub fn to_string(&self) -> String { + pub fn to_base64_string(&self) -> String { let Base64Bytes(digits) = self; let mut r: Vec = digits .iter() @@ -106,6 +82,7 @@ impl HexBytes { } } + #[allow(dead_code)] pub fn to_utf8_string(&self) -> String { let HexBytes(v) = self; String::from(str::from_utf8(&v).unwrap()) @@ -120,6 +97,33 @@ impl HexBytes { r } + fn is_ascii(&self) -> bool { + let HexBytes(v) = self; + for &c in v.iter() { + if c < 32 || c > 127 { + return false; + } + } + true + } + + fn ascii_score(&self) -> u32 { + let HexBytes(v) = self; + let mut r = 0; + for &c in v.iter() { + match c { + 32 => r += 2, + 33..=64 => r += 1, + 65..=90 => r += 3, + 91..=96 => r += 1, + 97..=122 => r += 3, + 123..=127 => r += 1, + _ => (), + } + } + r + } + fn xor(HexBytes(a): &HexBytes, HexBytes(b): &HexBytes) -> HexBytes { HexBytes( Iterator::zip(a.iter(), b.iter()) @@ -127,14 +131,18 @@ impl HexBytes { .collect(), ) } + + fn xor_byte(HexBytes(a): &HexBytes, byte: u8) -> HexBytes { + HexBytes(a.iter().map(|e| e ^ byte).collect()) + } } pub fn challenge1() { - let input = HexBytes::from_str("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"); - let expected = String::from("SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"); - let result = input.to_base64(); - if result.to_string() == expected { - println!("[okay] Challenge 1: {}", result); + let a = HexBytes::from_str("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"); + let e = String::from("SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"); + let r = a.to_base64(); + if r.to_base64_string() == e { + println!("[okay] Challenge 1: {}", r); } else { println!("[fail] Challenge 1") } @@ -152,4 +160,19 @@ pub fn challenge2() { } } -pub fn challenge3() {} +pub fn challenge3() { + let a = + HexBytes::from_str("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"); + + let mut h: Vec = (0..=255).map(|i| HexBytes::xor_byte(&a, i)).collect(); + h.sort_by(|a, b| a.ascii_score().partial_cmp(&b.ascii_score()).unwrap()); + let h: Vec = h.into_iter().filter(|b| b.is_ascii()).collect(); + let r = h[h.len() - 1].to_utf8_string(); + let e = String::from("Cooking MC's like a pound of bacon"); + + if r == e { + println!("[okay] Challenge 3: {}", r); + } else { + println!("[fail] Challenge 3: {}", r); + } +}