Implement challenge 37 break SRP with zero key
parent
a1de52bfd2
commit
f0b75e6cc0
|
@ -64,4 +64,5 @@ fn main() {
|
|||
}
|
||||
set5::challenge36();
|
||||
set5::challenge37();
|
||||
set5::challenge38();
|
||||
}
|
||||
|
|
85
src/set5.rs
85
src/set5.rs
|
@ -350,23 +350,84 @@ pub fn challenge36() -> Option<()> {
|
|||
// I don't have HMAC-SHA256, so I will use HMAC-SHA1 instead.
|
||||
// C->S Send HMAC-SHA256(K, salt)
|
||||
let salt = Bytes(session_keys.salt.to_be_bytes().to_vec());
|
||||
let mac_server = sha1::hmac_sha1(&Bytes(k_server.to_vec()), &salt);
|
||||
|
||||
// S->C Send "OK" if HMAC-SHA256(K, salt) validates
|
||||
let mac_client = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
||||
assert_eq!(mac_server, mac_client, "HMAC verification failed");
|
||||
let mac = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
||||
assert!(server.log_in(email, &mac)?);
|
||||
|
||||
println!("[okay] Challenge 36: implement secure remote password");
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn challenge37() {
|
||||
// Get your SRP working in an actual client-server setting. "Log in" with a
|
||||
// valid password using the protocol.
|
||||
pub fn challenge37() -> Option<()> {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Now log in without your password by having the client send 0 as its "A"
|
||||
// value. What does this to the "S" value that both sides compute?
|
||||
let mut server = srp::Server::default();
|
||||
let email = "john1337@wayne.com";
|
||||
let password = "horse planet carpet country";
|
||||
let parameters = server.register(email, password)?;
|
||||
|
||||
// Now log in without your password by having the client send N, N*2, &c.
|
||||
println!("[xxxx] Challenge 37: TBD");
|
||||
let mut log_in_with_password = || -> Option<bool> {
|
||||
// Get your SRP working in an actual client-server setting. "Log in" with a
|
||||
// valid password using the protocol.
|
||||
let n = ¶meters.n;
|
||||
let g = ¶meters.g;
|
||||
let a = rng.gen_biguint_below(n);
|
||||
let a_public = g.modpow(&a, n);
|
||||
let session_keys = server.exchange(email, &a_public)?;
|
||||
|
||||
// Client
|
||||
let u = srp::compute_u(&a_public, &session_keys.b_public)?;
|
||||
let x = srp::hash_password(session_keys.salt, password)?;
|
||||
let b_public = &session_keys.b_public;
|
||||
let k = ¶meters.k;
|
||||
let s_client = (b_public - ((k * g.modpow(&x, n)) % n)).modpow(&(a + &u * x), n);
|
||||
let k_client = sha256(&s_client.to_bytes_be());
|
||||
|
||||
let salt = Bytes(session_keys.salt.to_be_bytes().to_vec());
|
||||
let mac = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
||||
server.log_in(email, &mac)
|
||||
};
|
||||
|
||||
assert!(log_in_with_password()?);
|
||||
|
||||
let mut log_in_without_password_a_zero = || -> Option<bool> {
|
||||
// Now log in without your password by having the client send 0 as its "A"
|
||||
// value.
|
||||
let a_public = 0_u8.to_biguint()?;
|
||||
let session_keys = server.exchange(email, &a_public)?;
|
||||
|
||||
// What does this to the "S" value that both sides compute? It becomes zero.
|
||||
let s_client: BigUint = 0_u8.to_biguint()?;
|
||||
let k_client = sha256(&s_client.to_bytes_be());
|
||||
|
||||
let salt = Bytes(session_keys.salt.to_be_bytes().to_vec());
|
||||
let mac = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
||||
server.log_in(email, &mac)
|
||||
};
|
||||
|
||||
assert!(log_in_without_password_a_zero()?);
|
||||
|
||||
let mut log_in_without_password_multiple_n = || -> Option<bool> {
|
||||
// Now log in without your password by having the client send N, N*2, &c.
|
||||
let n = ¶meters.n;
|
||||
let a_public = n * 2_u8.to_biguint()?;
|
||||
let session_keys = server.exchange(email, &a_public)?;
|
||||
|
||||
// If A is a multiple of N, the term $(A * v**u) ** b % N$ also becomes zero.
|
||||
let s_client: BigUint = 0_u8.to_biguint()?;
|
||||
let k_client = sha256(&s_client.to_bytes_be());
|
||||
|
||||
let salt = Bytes(session_keys.salt.to_be_bytes().to_vec());
|
||||
let mac = sha1::hmac_sha1(&Bytes(k_client.to_vec()), &salt);
|
||||
server.log_in(email, &mac)
|
||||
};
|
||||
|
||||
assert!(log_in_without_password_multiple_n()?);
|
||||
|
||||
println!("[okay] Challenge 37: break SRP with zero key");
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn challenge38() -> Option<()> {
|
||||
println!("[xxxx] Challenge 38: TBD");
|
||||
Some(())
|
||||
}
|
||||
|
|
15
src/srp.rs
15
src/srp.rs
|
@ -1,4 +1,6 @@
|
|||
use crate::bytes::Bytes;
|
||||
use crate::set5;
|
||||
use crate::sha1;
|
||||
use num_bigint::BigUint;
|
||||
use num_bigint::RandBigInt;
|
||||
use num_bigint::ToBigUint;
|
||||
|
@ -122,4 +124,17 @@ impl Server {
|
|||
let k_server = sha256(&s_server.to_bytes_be());
|
||||
Some(k_server)
|
||||
}
|
||||
|
||||
pub fn log_in(&mut self, email: &str, mac_client: &Bytes) -> Option<bool> {
|
||||
let k = self.get_k(email)?;
|
||||
let password_entry = self.entries.get(email)?;
|
||||
let salt = Bytes(password_entry.salt.to_be_bytes().to_vec());
|
||||
|
||||
// S->C Send "OK" if HMAC-SHA255(K, salt) validates
|
||||
let mac_server = sha1::hmac_sha1(&Bytes(k.to_vec()), &salt);
|
||||
if mac_server == *mac_client {
|
||||
return Some(true);
|
||||
}
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue