Implement challenge 33 Diffie-Hellman

This commit is contained in:
Felix Martin 2022-08-31 19:30:34 -04:00
parent ddafb43934
commit 9e568ac97c
7 changed files with 91 additions and 19 deletions

View File

@ -8,3 +8,4 @@ edition = "2021"
[dependencies] [dependencies]
openssl = ">= 0.10.38" openssl = ">= 0.10.38"
rand = ">= 0.8.5" rand = ">= 0.8.5"
num-bigint = { version = ">= 0.4", features = ["rand"] }

8
data/33.txt Normal file
View File

@ -0,0 +1,8 @@
ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024
e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd
3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec
6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f
24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361
c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552
bb9ed529077096966d670c354e4abc9804f1746c08ca237327fff
fffffffffffff

View File

@ -1,15 +1,10 @@
#![allow(dead_code)]
use rand::Rng; use rand::Rng;
use std::fmt::Write; use std::fmt::Write;
#[derive(PartialEq, PartialOrd, Debug)] #[derive(PartialEq, Eq, PartialOrd, Debug)]
pub struct Bytes(pub Vec<u8>); pub struct Bytes(pub Vec<u8>);
impl Bytes { impl Bytes {
pub fn empty() -> Bytes {
Bytes(vec![])
}
pub fn from_utf8(s: &str) -> Bytes { pub fn from_utf8(s: &str) -> Bytes {
Bytes(s.as_bytes().to_vec()) Bytes(s.as_bytes().to_vec())
} }
@ -62,16 +57,6 @@ impl Bytes {
r 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 { pub fn ascii_score(&self) -> u32 {
let Bytes(v) = self; let Bytes(v) = self;
let mut r = 0; let mut r = 0;

View File

@ -14,6 +14,7 @@ mod md4;
mod mt19937; mod mt19937;
mod mtcipher; mod mtcipher;
mod parser; mod parser;
mod rsa;
mod set1; mod set1;
mod set2; mod set2;
mod set3; mod set3;
@ -59,4 +60,5 @@ fn main() {
set4::challenge32(); set4::challenge32();
} }
set5::challenge33(); set5::challenge33();
set5::challenge34();
} }

12
src/rsa.rs Normal file
View File

@ -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
}
}

View File

@ -186,7 +186,7 @@ mod challenge19 {
for i in 0..ciphers_len { for i in 0..ciphers_len {
for j in i..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; continue;
} }
let xored = target_bytes[i].unwrap() ^ target_bytes[j].unwrap(); let xored = target_bytes[i].unwrap() ^ target_bytes[j].unwrap();

View File

@ -1,3 +1,67 @@
use crate::rsa;
use num_bigint::{BigUint, RandBigInt, ToBigUint};
use rand::Rng;
use std::fs;
pub fn challenge33() { 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::<u32>() % p;
let A = rsa::expmod(g, a, p);
// Do the same for "b" and "B".
let b: u32 = rng.gen::<u32>() % 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<u8> = 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");
} }