Finish challenge 38 SRP dictionary attack
This commit is contained in:
@@ -61,8 +61,9 @@ fn main() {
|
|||||||
set5::challenge33();
|
set5::challenge33();
|
||||||
set5::challenge34();
|
set5::challenge34();
|
||||||
set5::challenge35();
|
set5::challenge35();
|
||||||
}
|
|
||||||
set5::challenge36();
|
set5::challenge36();
|
||||||
|
}
|
||||||
set5::challenge37();
|
set5::challenge37();
|
||||||
set5::challenge38();
|
set5::challenge38();
|
||||||
|
set5::challenge39();
|
||||||
}
|
}
|
||||||
|
|||||||
71
src/set5.rs
71
src/set5.rs
@@ -433,7 +433,7 @@ pub fn challenge38() -> Option<()> {
|
|||||||
// Client and Server
|
// Client and Server
|
||||||
let n = challenge33::load_large_prime();
|
let n = challenge33::load_large_prime();
|
||||||
let g = 2_u8.to_biguint()?;
|
let g = 2_u8.to_biguint()?;
|
||||||
let password = "horse planet carpet country";
|
let password = "bar";
|
||||||
|
|
||||||
// Server: x = SHA256(salt|password); v = g**x % n;
|
// Server: x = SHA256(salt|password); v = g**x % n;
|
||||||
let salt: u32 = rng.gen();
|
let salt: u32 = rng.gen();
|
||||||
@@ -445,7 +445,8 @@ pub fn challenge38() -> Option<()> {
|
|||||||
let a_public = g.modpow(&a, &n);
|
let a_public = g.modpow(&a, &n);
|
||||||
|
|
||||||
// S->C: salt, B = g**b % n, u = 128 bit random number
|
// 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 b_public = g.modpow(&b, &n);
|
||||||
let u: u128 = rng.gen();
|
let u: u128 = rng.gen();
|
||||||
|
|
||||||
@@ -455,45 +456,59 @@ pub fn challenge38() -> Option<()> {
|
|||||||
let k_client = sha256(&s_client.to_bytes_be());
|
let k_client = sha256(&s_client.to_bytes_be());
|
||||||
|
|
||||||
// Server: S = (A * v ** u)**b % n; K = SHA256(S);
|
// 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());
|
let k_server = sha256(&s_server.to_bytes_be());
|
||||||
|
|
||||||
assert_eq!(k_client, k_server);
|
assert_eq!(k_client, k_server);
|
||||||
|
|
||||||
// C->S
|
// C->S
|
||||||
// Send HMAC-SHA256(K, salt)
|
// Send HMAC-SHA256(K, salt)
|
||||||
let salt = Bytes(salt.to_be_bytes().to_vec());
|
let salt_bytes = Bytes(salt.to_be_bytes().to_vec());
|
||||||
let mac_client = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
let mac_client = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt_bytes);
|
||||||
|
|
||||||
// S->C
|
// 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");
|
assert_eq!(mac_server, mac_client, "HMAC verification failed");
|
||||||
|
|
||||||
//fn crack_password(mac_client: &Bytes, salt: u32, B: &BigUint, u: BigUint) -> Option<String> {
|
fn crack_password(
|
||||||
// let dict = ["foo", "bar", "lol"];
|
mac_client: &Bytes,
|
||||||
// for password in dict {
|
salt: u32,
|
||||||
// let x = srp::hash_password(salt, &password)?;
|
a_public: &BigUint,
|
||||||
// let s_client = b_public.modpow(&(a + &u * x), &n);
|
u: u128,
|
||||||
// let k_client = sha256(&s_client.to_bytes_be());
|
) -> Option<String> {
|
||||||
// }
|
// 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:
|
let cracked_password = crack_password(&mac_client, salt, &a_public, u);
|
||||||
//
|
match cracked_password {
|
||||||
// Note that in this protocol, the server's "B" parameter doesn't depend on the password (it's
|
Some(p) if p == password => {
|
||||||
// just a Diffie Hellman public key).
|
println!("[okay] Challenge 38: offline dictionary attack on SRP");
|
||||||
//
|
}
|
||||||
// Make sure the protocol works given a valid password.
|
_ => println!("[FAIL] Challenge 38: offline dictionary attack on SRP"),
|
||||||
//
|
};
|
||||||
// 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(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn challenge39() {
|
||||||
|
println!("[xxxx] Challenge 39: Implement RSA");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user