Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 1, 2022 02:20 pm GMT

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

naveeen.com


Original Link: https://dev.to/thenvn/cryptopals-crypto-challenges-using-rust-121o

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To