From 9e568ac97c514fec659325b171fcbb4686f7be81 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Wed, 31 Aug 2022 19:30:34 -0400 Subject: [PATCH] Implement challenge 33 Diffie-Hellman --- Cargo.toml | 3 ++- data/33.txt | 8 +++++++ src/bytes.rs | 17 +------------- src/main.rs | 2 ++ src/rsa.rs | 12 ++++++++++ src/set3.rs | 2 +- src/set5.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 data/33.txt create mode 100644 src/rsa.rs diff --git a/Cargo.toml b/Cargo.toml index 9558d32..d43773a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] openssl = ">= 0.10.38" -rand = ">= 0.8.5" \ No newline at end of file +rand = ">= 0.8.5" +num-bigint = { version = ">= 0.4", features = ["rand"] } diff --git a/data/33.txt b/data/33.txt new file mode 100644 index 0000000..ce83d44 --- /dev/null +++ b/data/33.txt @@ -0,0 +1,8 @@ +ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024 +e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd +3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec +6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f +24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361 +c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552 +bb9ed529077096966d670c354e4abc9804f1746c08ca237327fff +fffffffffffff diff --git a/src/bytes.rs b/src/bytes.rs index f58dd7a..96b522e 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -1,15 +1,10 @@ -#![allow(dead_code)] use rand::Rng; use std::fmt::Write; -#[derive(PartialEq, PartialOrd, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Debug)] pub struct Bytes(pub Vec); impl Bytes { - pub fn empty() -> Bytes { - Bytes(vec![]) - } - pub fn from_utf8(s: &str) -> Bytes { Bytes(s.as_bytes().to_vec()) } @@ -62,16 +57,6 @@ impl Bytes { r } - pub fn is_ascii(&self) -> bool { - let Bytes(v) = self; - for &c in v.iter() { - if !(32..=127).contains(&c) { - return false; - } - } - true - } - pub fn ascii_score(&self) -> u32 { let Bytes(v) = self; let mut r = 0; diff --git a/src/main.rs b/src/main.rs index 3db33ce..f46cdf7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod md4; mod mt19937; mod mtcipher; mod parser; +mod rsa; mod set1; mod set2; mod set3; @@ -59,4 +60,5 @@ fn main() { set4::challenge32(); } set5::challenge33(); + set5::challenge34(); } diff --git a/src/rsa.rs b/src/rsa.rs new file mode 100644 index 0000000..95c336e --- /dev/null +++ b/src/rsa.rs @@ -0,0 +1,12 @@ +pub fn expmod(base: u32, exp: u32, m: u32) -> u32 { + if exp == 0 { + return 1; + } + + if exp % 2 == 0 { + let s = expmod(base, exp / 2, m); + (s * s) % m + } else { + (expmod(base, exp - 1, m) * base) % m + } +} diff --git a/src/set3.rs b/src/set3.rs index 7115e51..8fab179 100644 --- a/src/set3.rs +++ b/src/set3.rs @@ -186,7 +186,7 @@ mod challenge19 { for i in 0..ciphers_len { for j in i..ciphers_len { - if target_bytes[i] == None || target_bytes[j] == None { + if target_bytes[i].is_none() || target_bytes[j].is_none() { continue; } let xored = target_bytes[i].unwrap() ^ target_bytes[j].unwrap(); diff --git a/src/set5.rs b/src/set5.rs index 8b796d0..4b4ce21 100644 --- a/src/set5.rs +++ b/src/set5.rs @@ -1,3 +1,67 @@ +use crate::rsa; +use num_bigint::{BigUint, RandBigInt, ToBigUint}; +use rand::Rng; +use std::fs; + pub fn challenge33() { - println!("[xxxx] Challenge 33: now we talking!"); + #![allow(non_snake_case)] + + fn simple_diffie_hellman() { + let mut rng = rand::thread_rng(); + + // Set a variable "p" to 37 and "g" to 5. + let p: u32 = 37; + let g: u32 = 5; + + // Generate "a", a random number mod 37. Now generate "A", which is "g" raised to the "a" + // power mode 37 --- A = (g**a) % p. + let a: u32 = rng.gen::() % p; + let A = rsa::expmod(g, a, p); + + // Do the same for "b" and "B". + let b: u32 = rng.gen::() % p; + let B = rsa::expmod(g, b, p); + + // "A" and "B" are public keys. Generate a session key with them; set "s" to "B" raised to + // the "a" power mod 37 --- s = (B**a) % p. + let s = rsa::expmod(B, a, p); + + // Do the same with A**b, check that you come up with the same "s". + let s_ = rsa::expmod(A, b, p); + + assert_eq!(s, s_, "crypto is broken"); + // To turn "s" into a key, you can just hash it to create 128 bits of key material (or + // SHA256 it to create a key for encrypting and a key for a MAC). + } + + fn serious_diffie_hellman() { + let mut rng = rand::thread_rng(); + + let s = fs::read_to_string("data/33.txt").expect("run from git root dir"); + let b: Vec = s + .chars() + .filter(|c| *c != '\n') + .map(|c| c.to_digit(16).unwrap().try_into().unwrap()) + .collect(); + let p = BigUint::from_radix_be(&b, 16).unwrap(); + let g = 2_u8.to_biguint().unwrap(); + + let a = rng.gen_biguint_below(&p); + let A = g.modpow(&a, &p); + + let b = rng.gen_biguint_below(&p); + let B = g.modpow(&b, &p); + + let s = B.modpow(&a, &p); + let s_ = A.modpow(&b, &p); + assert_eq!(s, s_, "crypto is broken"); + } + + simple_diffie_hellman(); + serious_diffie_hellman(); + println!("[okay] Challenge 33: implemented Diffie-Hellman"); +} + +pub fn challenge34() { + println!("[xxxx] Challenge 34: tbd"); }