From 7a9225ccb08dfac97a3f1a148f09edf5e9d742f1 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Thu, 15 Sep 2022 17:30:29 -0400 Subject: [PATCH] Implement assignment 36. --- src/main.rs | 1 + src/set5.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 63ac4d3..16f65b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -63,4 +63,5 @@ fn main() { set5::challenge34(); set5::challenge35(); set5::challenge36(); + set5::challenge37(); } diff --git a/src/set5.rs b/src/set5.rs index 1f02677..49a1bde 100644 --- a/src/set5.rs +++ b/src/set5.rs @@ -1,6 +1,9 @@ use crate::bytes::Bytes; use crate::rsa; +use crate::sha1; +use crate::sha1::Sha1; use num_bigint::BigUint; +use num_bigint::RandBigInt; use num_bigint::ToBigUint; use rand::Rng; @@ -97,8 +100,8 @@ mod challenge34 { pub fn new(p: BigUint, g: &BigUint) -> Self { let keypair = rsa::Keypair::make(&p, g); Bot { - p: p, - keypair: keypair, + p, + keypair, s: None, key: None, } @@ -315,5 +318,90 @@ pub fn challenge35() { } pub fn challenge36() { - println!("[xxxx] Challenge 36: xxxx"); + let mut rng = rand::thread_rng(); + + // C & S + // Agree on N=[NIST Prime], g=2, k=3, I (email), P (password) + let n = challenge33::load_large_prime(); + let g = 2_u8.to_biguint().unwrap(); + let k = 3_u8.to_biguint().unwrap(); + let _i = Bytes::from_utf8("john1337@wayne.com"); + let p = Bytes::from_utf8("horse planet carpet country"); + + + // We will use SHA1 instead of SHA256 for the whole exercise because I am lazy. + + // S + // Generate salt as random integer + // Generate string xH=SHA256(salt|password) + // Convert xH to integer x somehow (put 0x on hexdigest) + // Generate v=g**x % N + // Save everything but x, xH + let salt: u32 = rng.gen(); + let mut salt_password = salt.to_be_bytes().to_vec(); + salt_password.append(&mut p.0.clone()); + let mut sha1 = Sha1::default(); + let xh = sha1.hash(&Bytes(salt_password)); + let x = BigUint::from_bytes_be(xh.0[0..4].try_into().unwrap()); + let v = g.modpow(&x, &n); + std::mem::drop(xh); + std::mem::drop(x); + std::mem::drop(sha1); + + // C->S + // Send I, A=g**a % N (a la Diffie Hellman) + let a = rng.gen_biguint_below(&n); + let a_public = g.modpow(&a, &n); + + // S->C + // Send salt, B=kv + g**b % N + let b = rng.gen_biguint_below(&n); + let b_public = k.clone() * v.clone() + g.modpow(&b, &n); + + // S, C + // Compute string uH = SHA256(A|B), u = integer of uH + let mut a_b = a_public.to_bytes_be(); + a_b.append(&mut b_public.to_bytes_be()); + let mut sha1 = Sha1::default(); + let uh = sha1.hash(&Bytes(a_b)); + let u = BigUint::from_bytes_be(uh.0[0..4].try_into().unwrap()); + + // C + // Generate string xH=SHA256(salt|password) + // Convert xH to integer x somehow (put 0x on hexdigest) + // Generate S = (B - k * g**x)**(a + u * x) % N + // Generate K = SHA256(S) + let mut salt_password = salt.to_be_bytes().to_vec(); + salt_password.append(&mut p.0.clone()); + let mut sha1 = Sha1::default(); + let xh = sha1.hash(&Bytes(salt_password)); + let x = BigUint::from_bytes_be(xh.0[0..4].try_into().unwrap()); + let s = (b_public - k * g.modpow(&x, &n)).modpow(&(a + &u * x), &n); + let mut sha1 = Sha1::default(); + let k_client = sha1.hash(&Bytes(s.to_bytes_be())); + + // S + // Generate S = (A * v**u) ** b % N + // Generate K = SHA256(S) + let s = (a_public * v.modpow(&u, &n)).modpow(&b, &n); + let mut sha1 = Sha1::default(); + let k_server = sha1.hash(&Bytes(s.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_server = sha1::hmac_sha1(&k_server, &salt); + + // S->C + // Send "OK" if HMAC-SHA256(K, salt) validates + let mac_client = sha1::hmac_sha1(&k_server, &salt); + assert_eq!(mac_server, mac_client, "HMAC verification failed"); + + println!("[okay] Challenge 36: implement secure remote password"); +} + +pub fn challenge37() { + println!("[xxxx] Challenge 37: TBD"); }