Move cryptopals tests to a module in tests/
This commit is contained in:
parent
0c8ff1686e
commit
a9d87b8048
3 changed files with 63 additions and 57 deletions
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
58
src/xor.rs
58
src/xor.rs
|
@ -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
53
tests/cryptopals.rs
Normal 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"));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue