diff --git a/src/set5.rs b/src/set5.rs index dc19384..9e8dca5 100644 --- a/src/set5.rs +++ b/src/set5.rs @@ -428,6 +428,72 @@ pub fn challenge37() -> Option<()> { } pub fn challenge38() -> Option<()> { - println!("[xxxx] Challenge 38: TBD"); + let mut rng = rand::thread_rng(); + + // Client and Server + let n = challenge33::load_large_prime(); + let g = 2_u8.to_biguint()?; + let password = "horse planet carpet country"; + + // Server: x = SHA256(salt|password); v = g**x % n; + let salt: u32 = rng.gen(); + let x = srp::hash_password(salt, &password)?; + let v = g.modpow(&x, &n); + + // C->C: I, A = g**a % n; + let a = rng.gen_biguint_below(&n); + 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); + let b_public = g.modpow(&b, &n); + let u: u128 = rng.gen(); + + // Client: x = SHA256(salt|password); S = B**(a + ux) % n; K = SHA256(S); + 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()); + + // 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 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); + + // S->C + let mac_server = sha1::hmac_sha1(&Bytes(k_server.to_vec()), &salt); + 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()); + // } + + + // "foo".to_string() + //} + + // 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). + + + println!("[xxxx] Challenge 38: offline dictionary attack on SRP"); Some(()) }