Clean up and lay groundwork for challange 32

This commit is contained in:
2022-08-28 15:53:23 -04:00
parent 75d4b97524
commit f50197e480
6 changed files with 111 additions and 92 deletions

View File

@@ -1,6 +1,4 @@
use std::path::Path;
use std::fs;
use std::{thread, time};
use crate::{bytes::Bytes, cbc, ctr, ecb, md4, parser, sha1, utils};
pub fn challenge25() {
@@ -301,12 +299,29 @@ pub fn challenge30() {
println!("[okay] Challenge 30: implemented and extended MD4 successfully");
}
pub fn challenge31() {
fn insecure_compare(a: &[u8], b: &[u8]) -> bool {
mod challenge31 {
use std::fs;
use crate::{bytes::Bytes, sha1};
use std::path::Path;
use std::{thread, time};
pub fn verify(file: &Path, signature: &[u8], delay: u64) -> bool {
// Have the server generate an HMAC key, and then verify that the "signature" on incoming
// requests is valid for "file", using the "==" operator to compare the valid MAC for a
// file with the "signature" parameter (in other words, verify the HMAC the way any normal
// programmer would verify it).
let key = Bytes::from_utf8("sosecretbb");
let contents = fs::read_to_string(file);
assert!(contents.is_ok(), "Could not read: {}", file.display());
let contents = Bytes(contents.unwrap().as_bytes().to_vec());
insecure_compare(&sha1::hmac_sha1(&key, &contents).0, signature, delay)
}
fn insecure_compare(a: &[u8], b: &[u8], delay: u64) -> bool {
// Write a function, call it "insecure_compare", that implements the == operation by doing
// byte-at-a-time comparisons with early exit (ie, return false at the first non-matching
// byte).
let delay = time::Duration::from_millis(8);
let delay = time::Duration::from_millis(delay);
if a.len() != b.len() {
return false;
}
@@ -320,19 +335,7 @@ pub fn challenge31() {
true
}
fn verify(file: &Path, signature: &[u8]) -> bool {
// Have the server generate an HMAC key, and then verify that the "signature" on incoming
// requests is valid for "file", using the "==" operator to compare the valid MAC for a
// file with the "signature" parameter (in other words, verify the HMAC the way any normal
// programmer would verify it).
let key = Bytes::from_utf8("sosecretbb");
let contents = fs::read_to_string(file);
assert!(contents.is_ok(), "Could not read: {}", file.display());
let contents = Bytes(contents.unwrap().as_bytes().to_vec());
insecure_compare(&sha1::hmac_sha1(&key, &contents).0, signature)
}
fn attack(file: &Path) -> Bytes {
pub fn attack(file: &Path, delay: u64) -> Bytes {
const BLOCK_SIZE: usize = 20;
let mut sig = vec![0x0; BLOCK_SIZE];
for i in 0..BLOCK_SIZE {
@@ -340,7 +343,7 @@ pub fn challenge31() {
for c in 0_u8..=255_u8 {
let now = time::Instant::now();
sig[i] = c;
verify(file, &sig);
verify(file, &sig, delay);
let elapsed = now.elapsed().as_micros();
if elapsed > max_tuple.0 {
max_tuple = (elapsed, c);
@@ -350,17 +353,29 @@ pub fn challenge31() {
}
Bytes(sig)
}
}
pub fn challenge31() {
let key = Bytes::from_utf8("YELLOW SUBMARINE");
let message = Bytes::from_utf8("Attact at dawn after tomorrow when it's cold inside.");
assert_eq!(sha1::hmac_sha1(&key, &message), Bytes::from_hex("8232f3d05afb6bce7e09fe764885cc158e435e36"));
let path = Path::new("data/12.txt");
let expected_sig = Bytes::from_hex("62f4527ea6cb716d0ad1ca0fc69135a49bc2d138");
assert!(verify(path, &expected_sig.0), "Invalid signature");
assert!(challenge31::verify(path, &expected_sig.0, 0), "Invalid signature");
let signature = attack(path);
assert_eq!(expected_sig.0, signature.0, "Recovery of HMAC-SHA1 failed");
// Don't do attack because it interrupts the flow of the other challenges by taking long.
// let signature = challenge31::attack(path, 20);
// assert_eq!(expected_sig, signature, "Recovery of HMAC-SHA1 failed");
println!("[okay] Challenge 31: recoverd HMAC-SHA1 via timing attack");
println!("[okay] Challenge 31: recovered HMAC-SHA1 via timing attack");
}
pub fn challenge32() {
const DELAY: u64 = 1;
let path = Path::new("data/12.txt");
let expected_sig = Bytes::from_hex("62f4527ea6cb716d0ad1ca0fc69135a49bc2d138");
assert!(challenge31::attack(path, DELAY) != expected_sig, "Recovery was unexpectedly successful");
println!("[xxxx] Challenge 32: recovered HMAC-SHA1 with slightly less artificial timing leak");
}