cryptopals

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

1-3.rs (2188B)


      1 use cryptopals::utils::read_buffer;
      2 
      3 fn main() -> Result<(), Box<dyn std::error::Error>> {
      4     println!("Enter crypted buffer");
      5     let crypted = hex_to_bytes(&read_buffer()?);
      6     let (key, msg, score) = crack_single_byte_xor(&crypted);
      7     println!(
      8         "key: {}, msg: {}, score: {}",
      9         bytes_to_hex(&[key]),
     10         bytes_to_hex(&xor(&crypted, &[key])),
     11         score
     12     );
     13     println!("msg (text): {}", String::from_utf8_lossy(&msg));
     14     Ok(())
     15 }
     16 fn hex_to_bytes(hex: &str) -> Vec<u8> {
     17     hex.as_bytes()
     18         .chunks(2)
     19         .map(|chunk| {
     20             let s = std::str::from_utf8(chunk).unwrap();
     21             u8::from_str_radix(s, 16).expect("Invalid hex")
     22         })
     23         .collect()
     24 }
     25 fn bytes_to_hex(bytes: &[u8]) -> String {
     26     bytes.iter().map(|b| format!("{:02x}", b)).collect()
     27 }
     28 fn xor(first: &[u8], second: &[u8]) -> Vec<u8> {
     29     first
     30         .iter()
     31         .zip(second.iter().cycle())
     32         .map(|(a, b)| a ^ b)
     33         .collect()
     34 }
     35 fn score_text(bytes: &[u8]) -> f64 {
     36     let mut score = 0.0;
     37     for &b in bytes {
     38         match b.to_ascii_lowercase() {
     39             b'e' => score += 12.02,
     40             b't' => score += 9.10,
     41             b'a' => score += 8.12,
     42             b'o' => score += 7.68,
     43             b'i' => score += 7.31,
     44             b'n' => score += 6.95,
     45             b's' => score += 6.28,
     46             b'r' => score += 6.02,
     47             b'h' => score += 5.92,
     48             b'd' => score += 4.32,
     49             b'l' => score += 3.98,
     50             b'u' => score += 2.88,
     51             b' ' => score += 15.0,
     52             0..=31 | 127 => score -= 50.0,
     53             32..=126 => score += 1.0,
     54             _ => score -= 10.0,
     55         }
     56     }
     57     score
     58 }
     59 
     60 fn crack_single_byte_xor(crypted: &[u8]) -> (u8, Vec<u8>, f64) {
     61     let mut best_score = f64::MIN;
     62     let mut best_key = 0;
     63     let mut best_msg = Vec::new();
     64 
     65     for key in 0..=255 {
     66         let decrypted: Vec<u8> = crypted.iter().map(|&b| b ^ key).collect();
     67         let score = score_text(&decrypted);
     68 
     69         if score > best_score {
     70             best_score = score;
     71             best_key = key;
     72             best_msg = decrypted;
     73         }
     74     }
     75     (best_key, best_msg, best_score)
     76 }