SRP Mad!

Perform SRP with the server to negotiate a session key; the server will give you back the flag for free (encrypted with the session key)! The only snag is that you don't know the password.

Maybe there's another way to decrypt the flag?

The server source code can be expanded below.

Outputs

Server source code async fn main(req: Request, env: Env, ctx: Context) -> Result { let router = Router::new(); router .post_async("/srp", |mut req, _ctx| async move { #[derive(Deserialize, Serialize)] struct Srp { A: String, } let srp: Srp = req.json().await?; let (key, B) = { let A = match BigUint::from_str_radix(&srp.A, 16) { Ok(a) => a, Err(_) => return Response::error("Bad A encoding", 400), }; if A.is_zero() { return Response::error("Bad A, cannot be zero", 400) } let V = BigUint::from_bytes_le(&rand::thread_rng().gen::<[u8; 32]>()); let G = BigUint::from_str("5").unwrap(); let N = BigUint::from_str_radix( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16 ).unwrap(); let mut h = Sha256::new(); h.update(G.to_bytes_le()); h.update(N.to_bytes_le()); let k = BigUint::from_bytes_le(&h.finalize().to_vec()); let b = BigUint::from_bytes_le(&rand::thread_rng().gen::<[u8; 32]>()); let B = ((k * V.clone()) + G.modpow(&b, &N)).modpow(&BigUint::one(), &N); let mut h = Sha256::new(); h.update(A.to_bytes_le()); h.update(B.to_bytes_le()); let u = BigUint::from_bytes_le(&h.finalize().to_vec()); let S = (A * V.modpow(&u, &N)).modpow(&b, &N); let mut h = Sha256::new(); h.update(S.to_bytes_le()); (h.finalize().to_vec(), B) }; let mut h = Sha256::new(); h.update(&key); let session_key_proof = h.finalize().to_vec(); let key = Key::::from_slice(&key); let cipher = Aes256Gcm::new(&key); let nonce = Aes256Gcm::generate_nonce(&mut OsRng); let ciphertext = cipher.encrypt(&nonce, FLAG).unwrap(); #[derive(Deserialize, Serialize)] struct Reply { B: String, session_key_proof: String, enc_flag: String, iv: String, } let reply = Reply { B: URL_SAFE.encode(B.to_bytes_le()), session_key_proof: URL_SAFE.encode(session_key_proof), enc_flag: URL_SAFE.encode(ciphertext), iv: URL_SAFE.encode(nonce), }; Response::from_json(&reply) }) .run(req, env).await }