Resolve more linter warnings
This commit is contained in:
182
src/set3.rs
182
src/set3.rs
@@ -16,7 +16,7 @@ pub fn challenge17() {
|
||||
// The first function should select at random one of the ten strings
|
||||
let cleartexts = utils::read_base64_lines("data/17.txt");
|
||||
let index: usize = rand::thread_rng().gen_range(0..cleartexts.len());
|
||||
let mut cleartext = Bytes(cleartexts[index].0.to_vec());
|
||||
let mut cleartext = Bytes(cleartexts[index].0.clone());
|
||||
|
||||
// pad the string out to the 16-byte AES block size and
|
||||
cleartext.pad_pkcs7(16);
|
||||
@@ -39,22 +39,29 @@ pub fn challenge17() {
|
||||
|
||||
let attack_block = |previous_block: &Bytes, cipher_block: &Bytes| -> Bytes {
|
||||
// Good explanation: https://robertheaton.com/2013/07/29/padding-oracle-attack/
|
||||
let block_size = cipher_block.len();
|
||||
let mut attack_vector = Bytes::random(block_size);
|
||||
let block_size: u8 = cipher_block
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("block size should be less than 255");
|
||||
let mut attack_vector = Bytes::random(block_size.into());
|
||||
let mut intermittent_result = vec![];
|
||||
|
||||
for pad_byte in 1..=block_size {
|
||||
for pad_byte in 1_u8..=block_size {
|
||||
// preset attack vector so that paddinig is [1], [2, 2], [3, 3, 3], and so on.
|
||||
attack_vector.0[block_size - pad_byte] = pad_byte as u8;
|
||||
for (i, intermittent_byte) in intermittent_result.iter().enumerate().take(pad_byte - 1)
|
||||
let pad_byte_index: usize = (block_size - pad_byte).into();
|
||||
attack_vector.0[pad_byte_index] = pad_byte;
|
||||
for (i, intermittent_byte) in intermittent_result
|
||||
.iter()
|
||||
.enumerate()
|
||||
.take(pad_byte as usize - 1)
|
||||
{
|
||||
attack_vector.0[block_size - 1 - i] = (pad_byte as u8) ^ intermittent_byte;
|
||||
attack_vector.0[block_size as usize - 1 - i] = (pad_byte as u8) ^ intermittent_byte;
|
||||
}
|
||||
|
||||
// guess attack vector so that padding is valid
|
||||
let guess_index = block_size - pad_byte;
|
||||
for guess in 0..=255 {
|
||||
attack_vector.0[guess_index] = guess;
|
||||
attack_vector.0[guess_index as usize] = guess;
|
||||
if decryption_oracle(&attack_vector, cipher_block) {
|
||||
// println!("{guess:#016b}");
|
||||
let c = (guess as u8) ^ (pad_byte as u8);
|
||||
@@ -68,7 +75,7 @@ pub fn challenge17() {
|
||||
let xored: Vec<u8> = Iterator::zip(previous_block.0.iter(), intermittent_result)
|
||||
.map(|z| z.0 ^ z.1)
|
||||
.collect();
|
||||
assert_eq!(xored.len(), block_size);
|
||||
assert_eq!(xored.len(), block_size.into());
|
||||
Bytes(xored)
|
||||
};
|
||||
|
||||
@@ -88,7 +95,7 @@ pub fn challenge17() {
|
||||
}
|
||||
roundtrip.remove_pkcs7(16);
|
||||
let cleartexts = utils::read_base64_lines("data/17.txt");
|
||||
let cleartext = Bytes(cleartexts[cleartext_index].0.to_vec());
|
||||
let cleartext = Bytes(cleartexts[cleartext_index].0.clone());
|
||||
assert_eq!(roundtrip, cleartext);
|
||||
println!("[okay] Challenge 17: {}", roundtrip.to_utf8());
|
||||
}
|
||||
@@ -96,9 +103,10 @@ pub fn challenge17() {
|
||||
pub fn challenge18() {
|
||||
let key = Bytes::from_utf8("YELLOW SUBMARINE");
|
||||
|
||||
let nonce = 1337;
|
||||
let cleartext = Bytes::from_utf8("Let's see if we can get the party started hard my friends.");
|
||||
let cipher = ctr::encrypt(&key, 42351234, &cleartext);
|
||||
let roundtrip = ctr::decrypt(&key, 42351234, &cipher);
|
||||
let cipher = ctr::encrypt(&key, nonce, &cleartext);
|
||||
let roundtrip = ctr::decrypt(&key, nonce, &cipher);
|
||||
assert_eq!(cleartext, roundtrip);
|
||||
|
||||
let cipher = BytesBase64::from_base64(
|
||||
@@ -110,7 +118,7 @@ pub fn challenge18() {
|
||||
println!("[okay] Challenge 18: {cleartext}");
|
||||
}
|
||||
|
||||
pub fn challenge19() {
|
||||
fn challenge19_attack(ciphers: &[Bytes]) -> Vec<RefCell<Vec<u8>>> {
|
||||
fn xor_to_char_set(letters: &Vec<u8>) -> HashMap<u8, RefCell<HashSet<u8>>> {
|
||||
let mut h = HashMap::new();
|
||||
for i in 0..255_u8 {
|
||||
@@ -144,83 +152,83 @@ pub fn challenge19() {
|
||||
letters
|
||||
}
|
||||
|
||||
fn attack(ciphers: &[Bytes]) -> Vec<RefCell<Vec<u8>>> {
|
||||
let ciphers_len = ciphers.len();
|
||||
let deciphered = vec![RefCell::new(vec![]); ciphers_len];
|
||||
let max_cipher_len = ciphers.iter().map(Bytes::len).max().unwrap_or(0);
|
||||
let ciphers_len = ciphers.len();
|
||||
let deciphered = vec![RefCell::new(vec![]); ciphers_len];
|
||||
let max_cipher_len = ciphers.iter().map(Bytes::len).max().unwrap_or(0);
|
||||
|
||||
for byte_index in 0..max_cipher_len {
|
||||
let letters = match byte_index {
|
||||
// chars that work for 10 and 20 found via trial and error
|
||||
10 => ascii_letters(" _-.,;:'"),
|
||||
20 => ascii_letters(" _-.,;:?"),
|
||||
_ => ascii_letters(" _-.,;:"),
|
||||
};
|
||||
let lookup = xor_to_char_set(&letters);
|
||||
for byte_index in 0..max_cipher_len {
|
||||
let letters = match byte_index {
|
||||
// chars that work for 10 and 20 found via trial and error
|
||||
10 => ascii_letters(" _-.,;:'"),
|
||||
20 => ascii_letters(" _-.,;:?"),
|
||||
_ => ascii_letters(" _-.,;:"),
|
||||
};
|
||||
let lookup = xor_to_char_set(&letters);
|
||||
|
||||
let target_bytes: Vec<Option<u8>> = ciphers
|
||||
.iter()
|
||||
.map(|c| {
|
||||
if c.len() > byte_index {
|
||||
Some(c.0[byte_index])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let mut possible_chars: Vec<HashSet<u8>> = ciphers
|
||||
.iter()
|
||||
.map(|_| letters.iter().cloned().collect())
|
||||
.collect();
|
||||
|
||||
for i in 0..ciphers_len {
|
||||
for j in i..ciphers_len {
|
||||
if target_bytes[i] == None || target_bytes[j] == None {
|
||||
continue;
|
||||
}
|
||||
let xored = target_bytes[i].unwrap() ^ target_bytes[j].unwrap();
|
||||
let chars = lookup.get(&xored).unwrap().borrow();
|
||||
possible_chars[i] = possible_chars[i].intersection(&chars).copied().collect();
|
||||
possible_chars[j] = possible_chars[j].intersection(&chars).copied().collect();
|
||||
let target_bytes: Vec<Option<u8>> = ciphers
|
||||
.iter()
|
||||
.map(|c| {
|
||||
if c.len() > byte_index {
|
||||
Some(c.0[byte_index])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let mut possible_chars: Vec<HashSet<u8>> = ciphers
|
||||
.iter()
|
||||
.map(|_| letters.iter().copied().collect())
|
||||
.collect();
|
||||
|
||||
for cipher_index in 0..ciphers_len {
|
||||
if ciphers[cipher_index].len() <= byte_index {
|
||||
for i in 0..ciphers_len {
|
||||
for j in i..ciphers_len {
|
||||
if target_bytes[i] == None || target_bytes[j] == None {
|
||||
continue;
|
||||
}
|
||||
let chars: Vec<u8> = possible_chars[cipher_index].iter().cloned().collect();
|
||||
match chars.len() {
|
||||
0 => {
|
||||
// println!("No chars for {cipher_index} {byte_index}");
|
||||
deciphered[cipher_index].borrow_mut().push(b'?');
|
||||
}
|
||||
1 => {
|
||||
let xored = target_bytes[i].unwrap() ^ target_bytes[j].unwrap();
|
||||
let chars = lookup.get(&xored).unwrap().borrow();
|
||||
possible_chars[i] = possible_chars[i].intersection(&chars).copied().collect();
|
||||
possible_chars[j] = possible_chars[j].intersection(&chars).copied().collect();
|
||||
}
|
||||
}
|
||||
|
||||
for cipher_index in 0..ciphers_len {
|
||||
if ciphers[cipher_index].len() <= byte_index {
|
||||
continue;
|
||||
}
|
||||
let chars: Vec<u8> = possible_chars[cipher_index].iter().copied().collect();
|
||||
match chars.len() {
|
||||
0 => {
|
||||
// println!("No chars for {cipher_index} {byte_index}");
|
||||
deciphered[cipher_index].borrow_mut().push(b'?');
|
||||
}
|
||||
1 => {
|
||||
deciphered[cipher_index]
|
||||
.borrow_mut()
|
||||
.push(u8_lower(chars[0]));
|
||||
}
|
||||
2 => {
|
||||
if u8_lower(chars[0]) == u8_lower(chars[1]) {
|
||||
deciphered[cipher_index]
|
||||
.borrow_mut()
|
||||
.push(u8_lower(chars[0]));
|
||||
}
|
||||
2 => {
|
||||
if u8_lower(chars[0]) == u8_lower(chars[1]) {
|
||||
deciphered[cipher_index]
|
||||
.borrow_mut()
|
||||
.push(u8_lower(chars[0]));
|
||||
} else {
|
||||
// println!("Two {chars:?} {cipher_index} {byte_index}");
|
||||
deciphered[cipher_index].borrow_mut().push(b'^');
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
// println!("Two {chars:?} {cipher_index} {byte_index}");
|
||||
deciphered[cipher_index].borrow_mut().push(b'^');
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// println!("Two {chars:?} {cipher_index} {byte_index}");
|
||||
deciphered[cipher_index].borrow_mut().push(b'^');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deciphered
|
||||
}
|
||||
|
||||
deciphered
|
||||
}
|
||||
|
||||
pub fn challenge19() {
|
||||
fn manual(decrypts: &[RefCell<Vec<u8>>]) {
|
||||
// Add manually guessed letters
|
||||
decrypts[0].borrow_mut()[30] = b'y';
|
||||
@@ -244,15 +252,15 @@ pub fn challenge19() {
|
||||
let key = Bytes::from_utf8("YELLOW SUBMARINE");
|
||||
let encrypt = |plaintext: &Bytes| -> Bytes { ctr::encrypt(&key, 0, plaintext) };
|
||||
let ciphers: Vec<Bytes> = plaintexts.iter().map(encrypt).collect();
|
||||
let decrypts = attack(&ciphers);
|
||||
let decrypts = challenge19_attack(&ciphers);
|
||||
manual(&decrypts);
|
||||
let first_line = Bytes(decrypts[0].borrow().to_vec()).to_utf8();
|
||||
println!("[okay] Challenge 19: {first_line}");
|
||||
}
|
||||
|
||||
pub fn challenge20() {
|
||||
fn attack(ciphers: Vec<Bytes>) -> Vec<Bytes> {
|
||||
let min_cipher_len = ciphers.iter().map(|c| c.len()).min().unwrap_or(0);
|
||||
fn attack(ciphers: &[Bytes]) -> Vec<Bytes> {
|
||||
let min_cipher_len = ciphers.iter().map(Bytes::len).min().unwrap_or(0);
|
||||
let mut key: Vec<u8> = vec![];
|
||||
for byte_index in 0..min_cipher_len {
|
||||
let bytes = Bytes(ciphers.iter().map(|c| c.0[byte_index]).collect());
|
||||
@@ -270,7 +278,7 @@ pub fn challenge20() {
|
||||
let key = Bytes::from_utf8("YELLOW SUBMARINE");
|
||||
let encrypt = |plaintext: &Bytes| -> Bytes { ctr::encrypt(&key, 0, plaintext) };
|
||||
let ciphers: Vec<Bytes> = plaintexts.iter().map(encrypt).collect();
|
||||
let plaintexts = attack(ciphers);
|
||||
let plaintexts = attack(&ciphers);
|
||||
|
||||
println!("[okay] Challenge 20: {}", plaintexts[0].to_utf8());
|
||||
}
|
||||
@@ -278,8 +286,16 @@ pub fn challenge20() {
|
||||
pub fn challenge21() {
|
||||
// Implement the MT19937 Mersenne Twister RNG
|
||||
let expected: Vec<u32> = vec![
|
||||
0xD091BB5C, 0x22AE9EF6, 0xE7E1FAEE, 0xD5C31F79, 0x2082352C, 0xF807B7DF, 0xE9D30005,
|
||||
0x3895AFE1, 0xA1E24BBA, 0x4EE4092B,
|
||||
0xD091_BB5C,
|
||||
0x22AE_9EF6,
|
||||
0xE7E1_FAEE,
|
||||
0xD5C3_1F79,
|
||||
0x2082_352C,
|
||||
0xF807_B7DF,
|
||||
0xE9D3_0005,
|
||||
0x3895_AFE1,
|
||||
0xA1E2_4BBA,
|
||||
0x4EE4_092B,
|
||||
];
|
||||
let mut mt = mt19937::MT19937::new();
|
||||
mt.seed(5489);
|
||||
@@ -326,8 +342,8 @@ pub fn challenge23() {
|
||||
const S: u32 = 7;
|
||||
const T: u32 = 15;
|
||||
const U: u32 = 11;
|
||||
const B: u32 = 0x9D2C5680;
|
||||
const C: u32 = 0xEFC60000;
|
||||
const B: u32 = 0x9D2C_5680;
|
||||
const C: u32 = 0xEFC6_0000;
|
||||
const L: u32 = 18;
|
||||
|
||||
let mut y = x;
|
||||
@@ -339,8 +355,8 @@ pub fn challenge23() {
|
||||
}
|
||||
|
||||
fn untemper(x: u32) -> u32 {
|
||||
const B: u32 = 0x9D2C5680;
|
||||
const C: u32 = 0xEFC60000;
|
||||
const B: u32 = 0x9D2C_5680;
|
||||
const C: u32 = 0xEFC6_0000;
|
||||
let mut y = x;
|
||||
|
||||
// reverse y = y ^ (y >> L); L = 18;
|
||||
|
||||
Reference in New Issue
Block a user