Move cryptopals tests to a module in tests/

This commit is contained in:
Eryn Wells 2018-04-08 08:16:45 -07:00
parent 0c8ff1686e
commit a9d87b8048
3 changed files with 63 additions and 57 deletions

View file

@ -119,13 +119,4 @@ mod tests {
let output: String = input.chars().hex_decoded().base64_encoded().collect(); let output: String = input.chars().hex_decoded().base64_encoded().collect();
assert_eq!(output, ex_output); assert_eq!(output, ex_output);
} }
#[test]
fn cryptopals() {
println!("");
let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
let ex_output = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
let output: String = input.chars().hex_decoded().base64_encoded().collect();
assert_eq!(output, ex_output);
}
} }

View file

@ -1,30 +1,28 @@
use std::iter; use std::iter;
pub type FixedXOR<T, U> = iter::Map<iter::Zip<T, U>, fn((u8, u8)) -> u8>; pub type FixedByteXOR<T, U> = iter::Map<iter::Zip<T, U>, fn((u8, u8)) -> u8>;
pub type SingleByteXOR<T> = FixedXOR<T, iter::Repeat<u8>>; pub type SingleByteXOR<T> = FixedByteXOR<T, iter::Repeat<u8>>;
pub trait FixedXORable<T, U> { pub trait FixedXOR<T, U> {
fn fixed_xor(self, other: U) -> FixedXOR<T, U>; fn fixed_xor(self, other: U) -> FixedByteXOR<T, U>;
} }
impl<'a, 'b, T, U> FixedXORable<T, U> for T impl<'a, 'b, T, U> FixedXOR<T, U> for T
where T: iter::Iterator<Item=u8> + 'a, where T: iter::Iterator<Item=u8> + 'a,
U: iter::Iterator<Item=u8> + 'b U: iter::Iterator<Item=u8> + 'b
{ {
fn fixed_xor(self, other: U) -> FixedXOR<T, U> { fn fixed_xor(self, other: U) -> FixedByteXOR<T, U> {
fn xor(tup: (u8, u8)) -> u8 { tup.0 ^ tup.1 } fn xor(tup: (u8, u8)) -> u8 { tup.0 ^ tup.1 }
self.zip(other).map(xor) self.zip(other).map(xor)
} }
} }
pub trait SingleByteXORable<T> { pub trait ByteXOR<T> {
fn single_byte_xor(self, byte: u8) -> SingleByteXOR<T>; fn byte_xor(self, byte: u8) -> SingleByteXOR<T>;
} }
impl<'a, T> SingleByteXORable<T> for T impl<'a, T> ByteXOR<T> for T where T: iter::Iterator<Item=u8> + 'a {
where T: FixedXORable<T, iter::Repeat<u8>> fn byte_xor(self, byte: u8) -> SingleByteXOR<T> {
{
fn single_byte_xor(self, byte: u8) -> SingleByteXOR<T> {
self.fixed_xor(iter::repeat(byte)) self.fixed_xor(iter::repeat(byte))
} }
} }
@ -35,41 +33,5 @@ mod tests {
use letter_frequency::LetterFreq; use letter_frequency::LetterFreq;
use hex::{HexDecodable, HexEncodable}; use hex::{HexDecodable, HexEncodable};
use std::f32; use std::f32;
use std::ascii::AsciiExt;
#[test]
fn cryptopals() {
println!();
let a = "1c0111001f010100061a024b53535009181c";
let b = "686974207468652062756c6c277320657965";
let ex_output = "746865206b696420646f6e277420706c6179";
let output: String = a.chars().hex_decoded()
.fixed_xor(b.chars().hex_decoded())
.hex_encoded().collect();
assert_eq!(output, ex_output);
}
#[test]
fn cryptopals13() {
let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
let mut best_key = 0u8;
let mut best_score = f32::INFINITY;
let mut best_output: Option<String> = None;
for key in 32u8..127 {
let possible_output = input.chars().hex_decoded()
.single_byte_xor(key)
.map(char::from)
.collect::<String>();
let score = possible_output.chi2_freqs("en");
println!("{}: {:?} -> {}", key, possible_output, score);
if !score.is_nan() && score < best_score {
best_score = score;
best_output = Some(possible_output);
best_key = key;
}
}
let best_output = best_output.expect("expected output");
println!("{}: {:?} -> {}", best_key, best_output, best_score);
assert!(best_output.to_lowercase().contains("bacon"));
}
} }

53
tests/cryptopals.rs Normal file
View file

@ -0,0 +1,53 @@
// cryptopals.rs
// Eryn Wells <eryn@erynwells.me>
extern crate cryptopals;
use std::f32;
use cryptopals::b64::Base64Encodable;
use cryptopals::hex::{HexDecodable, HexEncodable};
use cryptopals::letter_frequency::LetterFreq;
use cryptopals::xor::{FixedXOR, ByteXOR};
#[test]
fn s1c1() {
let input = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
let ex_output = "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";
let output: String = input.chars().hex_decoded().base64_encoded().collect();
assert_eq!(output, ex_output);
}
#[test]
fn s1c2() {
let a = "1c0111001f010100061a024b53535009181c";
let b = "686974207468652062756c6c277320657965";
let ex_output = "746865206b696420646f6e277420706c6179";
let output: String = a.chars().hex_decoded()
.fixed_xor(b.chars().hex_decoded())
.hex_encoded().collect();
assert_eq!(output, ex_output);
}
#[test]
fn s1c3() {
let input = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
let mut best_key = 0u8;
let mut best_score = f32::INFINITY;
let mut best_output: Option<String> = None;
for key in 32u8..127 {
let possible_output = input.chars().hex_decoded()
.byte_xor(key)
.map(char::from)
.collect::<String>();
let score = possible_output.chi2_freqs("en");
println!("{}: {:?} -> {}", key, possible_output, score);
if !score.is_nan() && score < best_score {
best_score = score;
best_output = Some(possible_output);
best_key = key;
}
}
let best_output = best_output.expect("expected output");
println!("{}: {:?} -> {}", best_key, best_output, best_score);
assert!(best_output.to_lowercase().contains("bacon"));
}