autoformat

This commit is contained in:
Thomas Lindner 2023-12-26 21:34:53 +01:00
parent 311f274645
commit 27ecc42699
7 changed files with 69 additions and 31 deletions

View file

@ -3,12 +3,20 @@ use std::ascii::escape_default;
use std::iter::repeat; use std::iter::repeat;
pub fn escape(text: &[u8]) -> String { pub fn escape(text: &[u8]) -> String {
String::from_utf8(text.iter().map(|ch| escape_default(ch.clone())).flatten().collect()).unwrap() String::from_utf8(
text.iter()
.map(|ch| escape_default(ch.clone()))
.flatten()
.collect(),
)
.unwrap()
} }
pub fn score(plaintext: &[u8]) -> u32 { pub fn score(plaintext: &[u8]) -> u32 {
let ranking = [24, 7, 15, 17, 26, 11, 10, 19, 22, 4, 5, 16, 13, let ranking = [
21, 23, 8, 2, 18, 20, 25, 14, 6, 12, 3, 9, 1]; 24, 7, 15, 17, 26, 11, 10, 19, 22, 4, 5, 16, 13, 21, 23, 8, 2, 18, 20, 25, 14, 6, 12, 3, 9,
1,
];
let mut score = 0; let mut score = 0;
for ch in plaintext.iter() { for ch in plaintext.iter() {
@ -27,11 +35,14 @@ pub fn score(plaintext: &[u8]) -> u32 {
} }
pub fn hamming(v1: &[u8], v2: &[u8]) -> u32 { pub fn hamming(v1: &[u8], v2: &[u8]) -> u32 {
v1.iter().zip(v2.iter()).map(|(a, b)| a ^ b) v1.iter()
.zip(v2.iter())
.map(|(a, b)| a ^ b)
.map(|x| ((x & 0xaa) >> 1) + (x & 0x55)) .map(|x| ((x & 0xaa) >> 1) + (x & 0x55))
.map(|x| ((x & 0xcc) >> 2) + (x & 0x33)) .map(|x| ((x & 0xcc) >> 2) + (x & 0x33))
.map(|x| ((x & 0xf0) >> 4) + (x & 0x0f)) .map(|x| ((x & 0xf0) >> 4) + (x & 0x0f))
.map(|x| x as u32).sum() .map(|x| x as u32)
.sum()
} }
#[cfg(test)] #[cfg(test)]
@ -86,8 +97,10 @@ pub fn break_repeating_xor_cipher(ciphertext: &[u8]) -> Vec<u8> {
let mut distance = 0; let mut distance = 0;
let maxoffset = ciphertext.len() / length - 1; let maxoffset = ciphertext.len() / length - 1;
for offset in 0..maxoffset { for offset in 0..maxoffset {
distance += hamming(&ciphertext[offset * length .. (offset + 1) * length], distance += hamming(
&ciphertext[(offset + 1) * length .. (offset + 2) * length]); &ciphertext[offset * length..(offset + 1) * length],
&ciphertext[(offset + 1) * length..(offset + 2) * length],
);
} }
// scale and normalize // scale and normalize
distance *= 1024; distance *= 1024;
@ -102,7 +115,11 @@ pub fn break_repeating_xor_cipher(ciphertext: &[u8]) -> Vec<u8> {
let mut decryptedcolumns: Vec<Vec<u8>> = vec![]; let mut decryptedcolumns: Vec<Vec<u8>> = vec![];
for offset in 0..keylength { for offset in 0..keylength {
let ciphercolumn: Vec<u8> = ciphertext[offset..].iter().step_by(keylength).cloned().collect(); let ciphercolumn: Vec<u8> = ciphertext[offset..]
.iter()
.step_by(keylength)
.cloned()
.collect();
let (decrypted, _) = break_xor_cipher(ciphercolumn.as_slice()); let (decrypted, _) = break_xor_cipher(ciphercolumn.as_slice());
decryptedcolumns.push(decrypted); decryptedcolumns.push(decrypted);
} }

View file

@ -1,7 +1,7 @@
use log::error; use log::error;
use rustc_serialize::base64::{ToBase64, STANDARD};
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use rustc_serialize::base64::{STANDARD, ToBase64}; use std::io::{stdin, BufRead};
use std::io::{BufRead, stdin};
fn main() { fn main() {
env_logger::init(); env_logger::init();
@ -9,7 +9,7 @@ fn main() {
for line in stdin().lock().lines().filter_map(|x| x.ok()) { for line in stdin().lock().lines().filter_map(|x| x.ok()) {
match line.from_hex() { match line.from_hex() {
Ok(v) => println!("{}", v.to_base64(STANDARD)), Ok(v) => println!("{}", v.to_base64(STANDARD)),
Err(e) => error!("{}", e) Err(e) => error!("{}", e),
} }
} }
} }
@ -22,6 +22,9 @@ mod tests {
fn challenge1_hex2base64() { fn challenge1_hex2base64() {
let v = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d".from_hex().unwrap(); let v = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d".from_hex().unwrap();
let r = v.to_base64(STANDARD); let r = v.to_base64(STANDARD);
assert_eq!(r, "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"); assert_eq!(
r,
"SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"
);
} }
} }

View file

@ -1,11 +1,14 @@
use common::fixed_xor_cipher; use common::fixed_xor_cipher;
use log::error; use log::error;
use rustc_serialize::hex::{FromHex, ToHex}; use rustc_serialize::hex::{FromHex, ToHex};
use std::io::{BufRead, stdin}; use std::io::{stdin, BufRead};
struct Pairwise<T: Iterator>(T); struct Pairwise<T: Iterator>(T);
impl<T> Iterator for Pairwise<T> where T: Iterator { impl<T> Iterator for Pairwise<T>
where
T: Iterator,
{
type Item = (T::Item, T::Item); type Item = (T::Item, T::Item);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -22,9 +25,12 @@ fn main() {
for (line1, line2) in Pairwise(stdin().lock().lines().filter_map(|x| x.ok())) { for (line1, line2) in Pairwise(stdin().lock().lines().filter_map(|x| x.ok())) {
match (line1.from_hex(), line2.from_hex()) { match (line1.from_hex(), line2.from_hex()) {
(Ok(v1), Ok(v2)) => println!("{}", fixed_xor_cipher(v1.as_slice(), v2.as_slice()).to_hex()), (Ok(v1), Ok(v2)) => println!(
"{}",
fixed_xor_cipher(v1.as_slice(), v2.as_slice()).to_hex()
),
(Err(e), _) => error!("{}", e), (Err(e), _) => error!("{}", e),
(_, Err(e)) => error!("{}", e) (_, Err(e)) => error!("{}", e),
} }
} }
} }

View file

@ -1,7 +1,7 @@
use common::break_xor_cipher; use common::break_xor_cipher;
use log::error; use log::error;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use std::io::{BufRead, stdin}; use std::io::{stdin, BufRead};
fn main() { fn main() {
env_logger::init(); env_logger::init();
@ -12,10 +12,10 @@ fn main() {
let (decrypted, _) = break_xor_cipher(ciphertext.as_slice()); let (decrypted, _) = break_xor_cipher(ciphertext.as_slice());
match String::from_utf8(decrypted) { match String::from_utf8(decrypted) {
Ok(s) => println!("{}", s), Ok(s) => println!("{}", s),
Err(e) => error!("{}", e) Err(e) => error!("{}", e),
} }
} }
Err(e) => error!("{}", e) Err(e) => error!("{}", e),
} }
} }
} }
@ -26,8 +26,13 @@ mod tests {
#[test] #[test]
fn challenge3_xor_cipher() { fn challenge3_xor_cipher() {
let ciphertext = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736".from_hex().unwrap(); let ciphertext = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
.from_hex()
.unwrap();
let (decrypted, _) = break_xor_cipher(ciphertext.as_slice()); let (decrypted, _) = break_xor_cipher(ciphertext.as_slice());
assert_eq!(String::from_utf8(decrypted).unwrap(), "Cooking MC's like a pound of bacon"); assert_eq!(
String::from_utf8(decrypted).unwrap(),
"Cooking MC's like a pound of bacon"
);
} }
} }

View file

@ -2,7 +2,7 @@ use common::break_xor_cipher;
use log::error; use log::error;
use rustc_serialize::hex::FromHex; use rustc_serialize::hex::FromHex;
use std::error::Error; use std::error::Error;
use std::io::{BufRead, stdin}; use std::io::{stdin, BufRead};
fn detect_xor(input: &mut dyn BufRead) -> Result<String, Box<dyn Error>> { fn detect_xor(input: &mut dyn BufRead) -> Result<String, Box<dyn Error>> {
let mut maxscore = 0; let mut maxscore = 0;
@ -24,21 +24,24 @@ fn main() {
match detect_xor(&mut stdin().lock()) { match detect_xor(&mut stdin().lock()) {
Ok(s) => println!("{}", s), Ok(s) => println!("{}", s),
Err(e) => error!("{}", e) Err(e) => error!("{}", e),
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use super::*;
#[test] #[test]
fn challenge4_detect_xor() { fn challenge4_detect_xor() {
let cargo_manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let cargo_manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let testinput = File::open(cargo_manifest_dir.join("4.txt")).unwrap(); let testinput = File::open(cargo_manifest_dir.join("4.txt")).unwrap();
assert_eq!(detect_xor(&mut BufReader::new(testinput)).unwrap(), "Now that the party is jumping\n"); assert_eq!(
detect_xor(&mut BufReader::new(testinput)).unwrap(),
"Now that the party is jumping\n"
);
} }
} }

View file

@ -1,6 +1,6 @@
use common::repeating_xor_cipher; use common::repeating_xor_cipher;
use rustc_serialize::hex::ToHex; use rustc_serialize::hex::ToHex;
use std::io::{BufRead, stdin}; use std::io::{stdin, BufRead};
fn main() { fn main() {
env_logger::init(); env_logger::init();
@ -17,7 +17,9 @@ mod tests {
#[test] #[test]
fn challenge5_repeating_xor() { fn challenge5_repeating_xor() {
let plaintext = "Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal".as_bytes(); let plaintext =
"Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal"
.as_bytes();
let ciphertext = repeating_xor_cipher(plaintext, "ICE".as_bytes()); let ciphertext = repeating_xor_cipher(plaintext, "ICE".as_bytes());
assert_eq!(ciphertext.to_hex(), "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f"); assert_eq!(ciphertext.to_hex(), "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a3124333a653e2b2027630c692b20283165286326302e27282f");
} }

View file

@ -2,7 +2,7 @@ use common::break_repeating_xor_cipher;
use log::error; use log::error;
use rustc_serialize::base64::FromBase64; use rustc_serialize::base64::FromBase64;
use std::error::Error; use std::error::Error;
use std::io::{Read, read_to_string, stdin}; use std::io::{read_to_string, stdin, Read};
fn break_xor(input: &mut dyn Read) -> Result<String, Box<dyn Error>> { fn break_xor(input: &mut dyn Read) -> Result<String, Box<dyn Error>> {
let ciphertext = read_to_string(input)?.from_base64()?; let ciphertext = read_to_string(input)?.from_base64()?;
@ -15,23 +15,25 @@ fn main() {
match break_xor(&mut stdin().lock()) { match break_xor(&mut stdin().lock()) {
Ok(s) => println!("{}", s), Ok(s) => println!("{}", s),
Err(e) => error!("{}", e) Err(e) => error!("{}", e),
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
use std::path::Path; use std::path::Path;
use super::*;
#[test] #[test]
fn challenge6_break_repeating_xor() { fn challenge6_break_repeating_xor() {
let cargo_manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let cargo_manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let testinput = File::open(cargo_manifest_dir.join("6.txt")).unwrap(); let testinput = File::open(cargo_manifest_dir.join("6.txt")).unwrap();
let decrypted = break_xor(&mut BufReader::new(testinput)).unwrap(); let decrypted = break_xor(&mut BufReader::new(testinput)).unwrap();
let plaintext = read_to_string(File::open(cargo_manifest_dir.join("6_plaintext.txt")).unwrap()).unwrap(); let plaintext =
read_to_string(File::open(cargo_manifest_dir.join("6_plaintext.txt")).unwrap())
.unwrap();
assert_eq!(decrypted, plaintext); assert_eq!(decrypted, plaintext);
} }
} }