From 98ad4c7712f717129fab316b65035b380b73d103 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Sat, 6 Aug 2022 11:24:58 -0400 Subject: [PATCH] Finish challenge 23. --- src/main.rs | 5 +-- src/set3.rs | 98 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/main.rs b/src/main.rs index d9fc37a..69ec6ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod set2; mod set3; fn main() { - const RUN_ALL: bool = false; + const RUN_ALL: bool = true; if RUN_ALL { set1::challenge1(); set1::challenge2(); @@ -35,7 +35,8 @@ fn main() { set3::challenge21(); set3::challenge22(); set3::challenge23(); + set3::challenge24(); } else { - set3::challenge23(); + set3::challenge24(); } } diff --git a/src/set3.rs b/src/set3.rs index a3843f1..2148b7f 100644 --- a/src/set3.rs +++ b/src/set3.rs @@ -304,7 +304,6 @@ pub fn challenge20() { pub fn challenge21() { // Implement the MT19937 Mersenne Twister RNG - let expected: Vec = vec![ 0xD091BB5C, 0x22AE9EF6, 0xE7E1FAEE, 0xD5C31F79, 0x2082352C, 0xF807B7DF, 0xE9D30005, 0x3895AFE1, 0xA1E24BBA, 0x4EE4092B, @@ -314,7 +313,7 @@ pub fn challenge21() { for i in 0..expected.len() { assert_eq!(mt.extract_number(), expected[i]); } - println!("[okay] Challenge 21: Implemented MT19937"); + println!("[okay] Challenge 21: implemented MT19937"); } pub fn challenge22() { @@ -355,64 +354,78 @@ pub fn challenge22() { let found_seed = find_seed(rngout); assert_eq!(seed, found_seed.unwrap()); - println!("[done] Challenge 22: cracked MT19937 seed."); + println!("[okay] Challenge 22: cracked MT19937 seed"); } pub fn challenge23() { - fn temper(x: u32) -> u32 { + fn _temper(x: u32) -> u32 { const S: u32 = 7; - // const T: u32 = 15; - // const U: u32 = 11; + const T: u32 = 15; + const U: u32 = 11; const B: u32 = 0x9D2C5680; - // const C: u32 = 0xEFC60000; - // const L: u32 = 18; + const C: u32 = 0xEFC60000; + const L: u32 = 18; let mut y = x; - // y = y ^ (y >> U); + y = y ^ (y >> U); y = y ^ ((y << S) & B); - // y = y ^ ((y << T) & C); - // y = y ^ (y >> L); + y = y ^ ((y << T) & C); + y = y ^ (y >> L); y } fn untemper(x: u32) -> u32 { - //const S: u32 = 7; - //const T: u32 = 15; - //const B: u32 = 0x9D2C5680; - //const C: u32 = 0xEFC60000; - const M: u32 = 32; - + const B: u32 = 0x9D2C5680; + const C: u32 = 0xEFC60000; let mut y = x; // reverse y = y ^ (y >> L); L = 18; - // const UPPER_18_BITS: u32 = u32::MAX << (M - 18); - // const LOWER_14_BITS: u32 = u32::MAX >> 18; - // let mut o = y & UPPER_18_BITS; // upper 18 bits are correct - // o |= ((o & UPPER_18_BITS) >> 18) ^ (y & LOWER_14_BITS); // all 32 bits are correct - // y = o; + const UPPER_18_BITS: u32 = u32::MAX << 14; + const LOWER_14_BITS: u32 = u32::MAX >> 18; + let mut o = y & UPPER_18_BITS; // upper 18 bits are correct + o |= ((o & UPPER_18_BITS) >> 18) ^ (y & LOWER_14_BITS); // all 32 bits are correct + y = o; - // reverse y = y ^ ((y << T) & C); + // reverse y = y ^ ((y << T) & C); T = 15; + const LOWER_15_BITS: u32 = u32::MAX >> 17; + const MID_15_BITS: u32 = LOWER_15_BITS << 15; + const UPPER_2_BITS: u32 = u32::MAX << 30; + let mut o = y & LOWER_15_BITS; // lower 15 bits are correct + o |= ((o << 15) & C) ^ (y & MID_15_BITS); // lower 30 bits are correct + o |= (((o << 15) & C) & UPPER_2_BITS) ^ (y & UPPER_2_BITS); // all 32 bits are correct + y = o; - // reverse y = y ^ ((y << S) & B); + // reverse y = y ^ ((y << S) & B); S = 7 + const LOWER_7_BITS: u32 = u32::MAX >> 25; + const SECOND_7_BITS: u32 = LOWER_7_BITS << 7; + const THIRD_7_BITS: u32 = SECOND_7_BITS << 7; + const FOURTH_7_BITS: u32 = THIRD_7_BITS << 7; + const UPPER_4_BITS: u32 = u32::MAX << 28; + let mut o = y & LOWER_7_BITS; // lower 7 bits are correct + o |= ((o << 7) & B) ^ (y & SECOND_7_BITS); // lower 14 bits are correct + o |= (((o << 7) & B) & THIRD_7_BITS) ^ (y & THIRD_7_BITS); // lower 21 bits are correct + o |= (((o << 7) & B) & FOURTH_7_BITS) ^ (y & FOURTH_7_BITS); // lower 28 bits are correct + o |= (((o << 7) & B) & UPPER_4_BITS) ^ (y & UPPER_4_BITS); // all 32 bits are correct + y = o; // reverse y = y ^ (y >> U); U = 11; - // const UPPER_11_BITS: u32 = u32::MAX << (M - 11); - // const SECOND_11_BITS: u32 = UPPER_11_BITS >> 11; - // const LOWER_10_BITS: u32 = u32::MAX >> (M - 10); - // let mut o = y & UPPER_11_BITS; // upper 11 bits are correct - // o |= ((o & UPPER_11_BITS) >> 11) ^ (y & SECOND_11_BITS); // upper 22 bits are correct - // o |= ((o & SECOND_11_BITS) >> 11) ^ (y & LOWER_10_BITS); // all 32 bits are correct - // y = o; + const UPPER_11_BITS: u32 = u32::MAX << 21; + const SECOND_11_BITS: u32 = UPPER_11_BITS >> 11; + const LOWER_10_BITS: u32 = u32::MAX >> 22; + let mut o = y & UPPER_11_BITS; // upper 11 bits are correct + o |= ((o & UPPER_11_BITS) >> 11) ^ (y & SECOND_11_BITS); // upper 22 bits are correct + o |= ((o & SECOND_11_BITS) >> 11) ^ (y & LOWER_10_BITS); // all 32 bits are correct + y = o; y } - let a: u32 = 0x12345678; - let b = temper(a); - let c = untemper(b); - println!("{:#010x} -> {:#010x} -> {:#010x}", a, b, c); + // untemper test code + // let a: u32 = 0x12345678; + // let b = _temper(a); + // let c = untemper(b); + // println!("{:#010x} -> {:#010x} -> {:#010x}", a, b, c); - /* // Once you have "untemper" working, create a new MT19937 generator, tap it for 624 outputs, let mut mt = mt19937::MT19937::new(); let seed: u32 = rand::thread_rng().gen::(); @@ -425,8 +438,15 @@ pub fn challenge23() { // and splice that state into a new instance of the MT19937 generator. let mut spliced_mt = mt19937::MT19937::new(); spliced_mt.splice(outputs); - println!("{} {}", mt.extract_number(), spliced_mt.extract_number()); - */ - println!("[xxxx] Challenge 23: wip"); + // The new "spliced" generator should predict the values of the original. + for _ in 0..2000 { + assert_eq!(mt.extract_number(), spliced_mt.extract_number()); + } + + println!("[okay] Challenge 23: MT19937 RNG successfully cloned from output"); +} + +pub fn challenge24() { + println!("[xxxx] Challenge 24: xxx"); }