diff --git a/src/main.rs b/src/main.rs index 4962ca6..ef22466 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,8 +61,9 @@ fn main() { set5::challenge33(); set5::challenge34(); set5::challenge35(); + set5::challenge36(); } - set5::challenge36(); set5::challenge37(); set5::challenge38(); + set5::challenge39(); } diff --git a/src/set5.rs b/src/set5.rs index 9e8dca5..c5d70b9 100644 --- a/src/set5.rs +++ b/src/set5.rs @@ -433,7 +433,7 @@ pub fn challenge38() -> Option<()> { // Client and Server let n = challenge33::load_large_prime(); let g = 2_u8.to_biguint()?; - let password = "horse planet carpet country"; + let password = "bar"; // Server: x = SHA256(salt|password); v = g**x % n; let salt: u32 = rng.gen(); @@ -445,7 +445,8 @@ pub fn challenge38() -> Option<()> { let a_public = g.modpow(&a, &n); // S->C: salt, B = g**b % n, u = 128 bit random number - let b = rng.gen_biguint_below(&n); + // Pose as the server and use arbitrary values for b, B, u, and salt. + let b = 11_u8.to_biguint()?; let b_public = g.modpow(&b, &n); let u: u128 = rng.gen(); @@ -455,45 +456,59 @@ pub fn challenge38() -> Option<()> { let k_client = sha256(&s_client.to_bytes_be()); // Server: S = (A * v ** u)**b % n; K = SHA256(S); - let s_server = (a_public * v.modpow(&u.to_biguint()?, &n)).modpow(&b, &n); + let s_server = (&a_public * v.modpow(&u.to_biguint()?, &n)).modpow(&b, &n); let k_server = sha256(&s_server.to_bytes_be()); assert_eq!(k_client, k_server); // C->S // Send HMAC-SHA256(K, salt) - let salt = Bytes(salt.to_be_bytes().to_vec()); - let mac_client = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt); + let salt_bytes = Bytes(salt.to_be_bytes().to_vec()); + let mac_client = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt_bytes); // S->C - let mac_server = sha1::hmac_sha1(&Bytes(k_server.to_vec()), &salt); + let mac_server = sha1::hmac_sha1(&Bytes(k_server.to_vec()), &salt_bytes); assert_eq!(mac_server, mac_client, "HMAC verification failed"); - //fn crack_password(mac_client: &Bytes, salt: u32, B: &BigUint, u: BigUint) -> Option { - // let dict = ["foo", "bar", "lol"]; - // for password in dict { - // let x = srp::hash_password(salt, &password)?; - // let s_client = b_public.modpow(&(a + &u * x), &n); - // let k_client = sha256(&s_client.to_bytes_be()); - // } + fn crack_password( + mac_client: &Bytes, + salt: u32, + a_public: &BigUint, + u: u128, + ) -> Option { + // Now, run the protocol as a MITM attacker: pose as the server and use arbitrary values + // for b, B, u, and salt. Crack the password from A's HMAC-SHA256(K, salt). + let dict = ["foo", "bar", "lol"]; + let g = 2_u8.to_biguint()?; + let n = challenge33::load_large_prime(); + let b = 11_u8.to_biguint()?; + let salt_bytes = Bytes(salt.to_be_bytes().to_vec()); + for password in dict { + let x = srp::hash_password(salt, &password)?; + let v = g.modpow(&x, &n); + let s_attack = (a_public * v.modpow(&u.to_biguint()?, &n)).modpow(&b, &n); + let k_attack = sha256(&s_attack.to_bytes_be()); + let mac_attack = sha1::hmac_sha1(&Bytes(k_attack.to_vec()), &salt_bytes); + if mac_attack == *mac_client { + return Some(password.to_owned()); + } + } - // "foo".to_string() - //} + None + } - // TASK: - // - // Note that in this protocol, the server's "B" parameter doesn't depend on the password (it's - // just a Diffie Hellman public key). - // - // Make sure the protocol works given a valid password. - // - // Now, run the protocol as a MITM attacker: pose as the server and use arbitrary values for b, - // B, u, and salt. - // - // Crack the password from A's HMAC-SHA256(K, salt). + let cracked_password = crack_password(&mac_client, salt, &a_public, u); + match cracked_password { + Some(p) if p == password => { + println!("[okay] Challenge 38: offline dictionary attack on SRP"); + } + _ => println!("[FAIL] Challenge 38: offline dictionary attack on SRP"), + }; - - println!("[xxxx] Challenge 38: offline dictionary attack on SRP"); Some(()) } + +pub fn challenge39() { + println!("[xxxx] Challenge 39: Implement RSA"); +}