Implement challenge 35

This commit is contained in:
2022-09-03 08:59:16 -04:00
parent ad3a292e0e
commit 49d590ea44
2 changed files with 93 additions and 14 deletions

View File

@@ -61,4 +61,6 @@ fn main() {
}
set5::challenge33();
set5::challenge34();
set5::challenge35();
set5::challenge36();
}

View File

@@ -1,7 +1,6 @@
use crate::bytes::Bytes;
use crate::cbc;
use crate::rsa;
use crate::sha1::Sha1;
use num_bigint::BigUint;
use num_bigint::ToBigUint;
use rand::Rng;
@@ -155,6 +154,19 @@ mod challenge34 {
message
}
}
pub fn decrypt_with_s(cipher: &Bytes, s: &BigUint) -> Bytes {
const BLOCK_SIZE: usize = 16;
let mut sha1 = Sha1::default();
let key = Bytes(sha1.hash(&Bytes(s.to_bytes_be())).0[0..16].to_vec());
let cipher_len = cipher.len();
let iv = Bytes(cipher.0[(cipher_len - BLOCK_SIZE)..cipher_len].to_vec());
let cipher = Bytes(cipher.0[0..cipher_len - BLOCK_SIZE].to_vec());
let mut message = cbc::decrypt(&key, &iv, &cipher);
message.remove_pkcs7(BLOCK_SIZE);
message
}
}
pub fn challenge34() {
@@ -220,23 +232,88 @@ pub fn challenge34() {
}
fn attack(cipher: &Bytes) -> Bytes {
const BLOCK_SIZE: usize = 16;
// Do the DH math on this quickly to see what that does to the predictability of the key.
// Math: with p = A; s = (A ** b) % p becomes (p ** b) % p = 0 => s = 0
// With p = A; s = (A ** b) % p becomes (p ** b) % p = 0 => s = 0
let s = 0_u8.to_biguint().unwrap();
let mut sha1 = Sha1::default();
let key = Bytes(sha1.hash(&Bytes(s.to_bytes_be())).0[0..16].to_vec());
let cipher_len = cipher.len();
let iv = Bytes(cipher.0[(cipher_len - BLOCK_SIZE)..cipher_len].to_vec());
let cipher = Bytes(cipher.0[0..cipher_len - BLOCK_SIZE].to_vec());
let mut message = cbc::decrypt(&key, &iv, &cipher);
message.remove_pkcs7(BLOCK_SIZE);
message
challenge34::decrypt_with_s(cipher, &s)
}
echo();
echo_mitm();
println!("[okay] Challenge 34: implement MITM key-fixing attack on DH");
}
pub fn challenge35() {
fn echo(message: &Bytes, g: &BigUint, p: &BigUint) -> (Bytes, Bytes) {
let mut a = challenge34::Bot::new(p.clone(), &g);
let mut b = challenge34::Bot::new(p.clone(), &g);
a.exchange_keys(&b.exchange_keys(&a.get_public_key()));
assert_eq!(a.s, b.s, "crypto is broken");
let cipher_a = a.encrypt(&message);
let message_b = b.decrypt(&cipher_a);
let cipher_b = b.encrypt(&message_b);
let roundtrip = a.decrypt(&cipher_b);
assert_eq!(*message, roundtrip, "we broke it fam");
(cipher_a, cipher_b)
}
fn attack_g1(cipher: &Bytes) -> Bytes {
// A = (g ** a) % p, g = 1 -> A = 1
// s = (A ** b) % p, A = 1 -> s = 1
let s = 1_u8.to_biguint().unwrap();
challenge34::decrypt_with_s(cipher, &s)
}
fn attack_g_is_p(cipher: &Bytes) -> Bytes {
// A = (g ** a) % p, g = p -> A = 0
// s = (A ** b) % p, A = 0 -> s = 0
let s = 0_u8.to_biguint().unwrap();
challenge34::decrypt_with_s(cipher, &s)
}
fn attack_g_is_p_minus_one(cipher: &Bytes, p: &BigUint) -> Bytes {
// A = (g ** a) % p, g = p - 1 -> A = 1 | (p - 1)
// s = (A ** b) % p, A = 1 | (p - 1) -> s = 1 | (p - 1)
let s1 = 1_u8.to_biguint().unwrap();
let s2 = p - 1_u8.to_biguint().unwrap();
let m1 = challenge34::decrypt_with_s(cipher, &s1);
let m2 = challenge34::decrypt_with_s(cipher, &s2);
match m1.ascii_score().cmp(&m2.ascii_score()) {
std::cmp::Ordering::Greater => m1,
std::cmp::Ordering::Less => m2,
std::cmp::Ordering::Equal => panic!("how can they be equal?"),
}
}
// Do the MITM attack again, but play with "g". Write attacks for each.
let m = Bytes::from_utf8("Quick to the point, to the point, no faking");
let p = challenge33::load_large_prime();
let g = 2_u8.to_biguint().unwrap();
echo(&m, &g, &p);
// g = 1
let g = 1_u8.to_biguint().unwrap();
let (c1, c2) = echo(&m, &g, &p);
assert_eq!(attack_g1(&c1), m, "failed to attack g = 1");
assert_eq!(attack_g1(&c2), m, "failed to attack g = 1");
// g = p
let g = p.clone();
let (c1, c2) = echo(&m, &g, &p);
assert_eq!(attack_g_is_p(&c1), m, "failed to attack g = p");
assert_eq!(attack_g_is_p(&c2), m, "failed to attack g = p");
// g = p - 1
let g = p.clone() - 1_u8.to_biguint().unwrap();
let (c1, c2) = echo(&m, &g, &p);
assert_eq!(attack_g_is_p_minus_one(&c1, &p), m, "failed g = p - 1");
assert_eq!(attack_g_is_p_minus_one(&c2, &p), m, "failed g = p - 1");
println!("[okay] Challenge 35: implement MITM with malicious g attack on DH");
}
pub fn challenge36() {
println!("[xxxx] Challenge 36: xxxx");
}