An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
CryptoPals Crypto Challenges Using Rust: Detect single-character XOR
This is Challenge 4 of Cryptopals challenges implemented in Rust language.
Context
This challenge is same as Challenge 3, except that instead of giving a single cipher text string, we're given many cipher strings (per line in given challenge file). One of which has been encrypted by single-character XOR. We have to find which one & decrypt the message.
I'd highly recommend checking out Challenge 3 first, if you haven't yet.
You might've guessed what we're going to do. We'll do exactly same as previous challenge, by trying to decrypt the cipher text by brute-forcing with every char, till we find one with best looking letter frequency score, except we're going to do it with every cipher text line. However in this case we'll be accumulating best score across all cipher texts. Only the message which was actually encrypted by single-char XOR would make sense as English text after decryption. So, it should yield best score.
Crack
Code would be very identical to previous challenge except we added another loop for going through cipher text line in given input file.
use hex;use std::fs::File;use std::io::{BufRead, BufReader};pub fn detect_message(path: &str) -> String { let mut message = String::new(); let mut best_score: f64 = f64::MIN; let file = File::open(path).expect("Error reading file!"); let lines = BufReader::new(file).lines(); let mut line: String; let mut key: u16; for line_result in lines { line = line_result.unwrap(); for c in 0..255 { key = c as u16; let msg_bytes: Vec<u16> = hex::decode(&line.trim()) .unwrap() .iter() .map(|&b| (b as u16) ^ key) .collect(); let msg = String::from_utf16(&msg_bytes).unwrap(); let score = calc_letter_freq_score(&msg); if score > best_score { best_score = score; message = String::from(msg); } } } message}
Note that we're using same letter frequency score calculation function calc_letter_freq_score()
from previous challenge:
const LETTER_FREQ: [f64; 27] = [ 0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, // A-G 0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, // H-N 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, // O-U 0.00978, 0.02360, 0.00150, 0.01974, 0.00074, 0.19181, // V-Z & space char];pub fn calc_letter_freq_score(s: &str) -> f64 { let mut counts = vec![0_u32; 27]; let mut score: f64 = 0_f64; s.chars().for_each(|c| match c { 'a'..='z' => { counts[c as usize - 97] += 1; } 'A'..='Z' => { counts[c as usize - 65] += 1; } ' ' => counts[26] += 1, _ => {} }); for i in 0..27 { score += (counts[i] as f64) * LETTER_FREQ[i]; } score}
And we've cracked the message yet again!
See the code on Github
Find me on:
Twitter - @heyNvN
Original Link: https://dev.to/thenvn/cryptopals-crypto-challenges-using-rust-121o
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To