summaryrefslogtreecommitdiffstats
path: root/src/bin/timing_attack.rs
blob: e6137dd628b01e75c081e0fb1a1e17e977e4b646 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use rand::RngCore;
use serde_derive::Deserialize;

#[derive(Deserialize)]
struct Info {
    file: String,
    signature: String,
}

fn gen_key() -> Vec<u8> {
    let mut key = [0u8; 16];
    rand::thread_rng().fill_bytes(&mut key);
    key.to_vec()
}

fn insecure_compare(a: &[u8], b: &[u8], delay: u64) -> bool {
    if a.len() != b.len() {
        return false;
    }

    for i in 0..a.len() {
        if a[i] != b[i] {
            return false;
        }
        std::thread::sleep(std::time::Duration::from_millis(delay));
    }

    true
}

fn index(
    info: actix_web::Query<Info>,
    key: &[u8],
    delay: u64,
) -> actix_web::Result<String> {
    let hmac = matasano::sha1_hmac(&info.file.clone().into_bytes(), key);
    if insecure_compare(
        &hex::decode(info.signature.clone()).unwrap(),
        &hmac[..],
        delay,
    ) {
        Ok("ok".to_string())
    } else {
        Err(actix_web::error::ErrorBadRequest("hmac failed"))
    }
}

fn main() {
    let sys = actix::System::new("timing_attack");

    let key = gen_key();
    println!("{}", hex::encode(&key));

    let delay: u64 = std::env::args().nth(1).unwrap().parse().unwrap();

    actix_web::server::HttpServer::new(move || {
        let key = key.clone();
        let delay = delay.clone();
        actix_web::App::new().resource("/", move |r| {
            r.method(actix_web::http::Method::GET)
                .with(move |info| index(info, &key, delay))
        })
    })
    .bind("127.0.0.1:9000")
    .unwrap()
    .start();

    let _ = sys.run();
}