Resolve more linter warnings

This commit is contained in:
2022-08-27 14:47:56 -04:00
parent 0951a6ab3e
commit bac75acd2c
14 changed files with 175 additions and 172 deletions

View File

@@ -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;