diff --git a/src/main.rs b/src/main.rs index 62cfcf0..d5c3fec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod bytes_base64; mod cbc; mod ctr; mod ecb; +mod mt19937; mod parser; mod set1; mod set2; @@ -32,7 +33,8 @@ fn main() { set3::challenge19(); set3::challenge20(); set3::challenge21(); + set3::challenge22(); } else { - set3::challenge21(); + set3::challenge22(); } } diff --git a/src/mt19937.rs b/src/mt19937.rs new file mode 100644 index 0000000..ffa8170 --- /dev/null +++ b/src/mt19937.rs @@ -0,0 +1,80 @@ +use std::num::Wrapping; + +#[derive(Debug)] +pub struct MT19937 { + mt: Vec, + index: usize, +} + +const N: usize = 624; + +impl MT19937 { + pub fn new() -> MT19937 { + let mut mt = MT19937 { + mt: vec![0; N], + index: N + 1, + }; + mt.seed(5489); + mt + } + + pub fn seed(&mut self, seed: u32) { + self.index = N; + const F: u32 = 1812433253; + self.mt[0] = seed; + for i in 1..N { + self.mt[i] = (Wrapping(F) * Wrapping(self.mt[i - 1] ^ (self.mt[i - 1] >> 30)) + + Wrapping(i as u32)) + .0; + } + } + + pub fn extract_number(&mut self) -> u32 { + if self.index >= N { + if self.index > N { + panic!("Generator was never seeded"); + } + self.twist(); + } + + const S: u32 = 7; + const T: u32 = 15; + const U: u32 = 11; + const B: u32 = 0x9D2C5680; + const C: u32 = 0xEFC60000; + const D: u32 = 0xFFFFFFFF; + const L: u32 = 18; + + let mut y = self.mt[self.index]; + y = y ^ ((y >> U) & D); + y = y ^ ((y << S) & B); + y = y ^ ((y << T) & C); + y = y ^ (y >> L); + self.index += 1; + y + } + + fn twist(&mut self) { + const M: usize = 397; + const R: u32 = 31; + const A: u32 = 0x9908B0DF; + const LOWER_MASK: u32 = (1 << R) - 1; // 0x7fffffff + const UPPER_MASK: u32 = !LOWER_MASK; // 0x80000000 + const FIRST_HALF: usize = N - M; + + for i in 0..FIRST_HALF { + let bits = self.mt[i] & UPPER_MASK | self.mt[i + 1] & LOWER_MASK; + self.mt[i] = self.mt[i + M] ^ (bits >> 1) ^ ((bits & 1) * A); + } + + for i in FIRST_HALF..(N - 1) { + let bits = self.mt[i] & UPPER_MASK | self.mt[i + 1] & LOWER_MASK; + self.mt[i] = self.mt[i - FIRST_HALF] ^ (bits >> 1) ^ ((bits & 1) * A); + } + + let i = N - 1; + let bits = self.mt[i] & UPPER_MASK | self.mt[0] & LOWER_MASK; + self.mt[i] = self.mt[M - 1] ^ (bits >> 1) ^ ((bits & 1) * A); + self.index = 0; + } +} diff --git a/src/set3.rs b/src/set3.rs index 840ebbc..5eeebe0 100644 --- a/src/set3.rs +++ b/src/set3.rs @@ -2,6 +2,7 @@ use crate::bytes::Bytes; use crate::bytes_base64::BytesBase64; use crate::cbc; use crate::ctr; +use crate::mt19937; use rand::Rng; use std::cell::RefCell; use std::collections::HashMap; @@ -301,5 +302,20 @@ pub fn challenge20() { } pub fn challenge21() { - println!("[xxxx] Challenge 21: TBD"); + // Implement the MT19937 Mersenne Twister RNG + + let expected: Vec = vec![ + 0xD091BB5C, 0x22AE9EF6, 0xE7E1FAEE, 0xD5C31F79, 0x2082352C, 0xF807B7DF, 0xE9D30005, + 0x3895AFE1, 0xA1E24BBA, 0x4EE4092B, + ]; + let mut mt = mt19937::MT19937::new(); + mt.seed(5489); + for i in 0..expected.len() { + assert_eq!(mt.extract_number(), expected[i]); + } + println!("[okay] Challenge 21: Implemented MT19937"); +} + +pub fn challenge22() { + println!("[xxxx] Challenge 22: TBD!"); }