Solve challenge 45 DSA parameter tampering

This commit is contained in:
2023-01-14 10:37:37 -05:00
parent 47976540d5
commit 70cecb0d9e
3 changed files with 68 additions and 8 deletions

View File

@@ -59,13 +59,14 @@ impl DsaKeys {
let mut k = BigNum::new()?;
let mut r = BigNum::from_u32(0)?;
let zero = BigNum::from_u32(0)?;
while r == zero {
// Choose an integer k randomly from { 1 … q 1 }
params.q.rand_range(&mut k)?;
// Compute r := (g^k mod p) mod q. In the unlikely case that r=0, start again.
r.mod_exp(&params.g, &k, &params.p, &mut ctx)?;
r = &r % &params.q;
}
// Choose an integer k randomly from { 1 … q 1 }
params.q.rand_range(&mut k)?;
// Compute r := (g^k mod p) mod q.
r.mod_exp(&params.g, &k, &params.p, &mut ctx)?;
r = &r % &params.q;
// In the unlikely case that r=0, crash.
assert!(r != zero, "r is zero");
// Compute s := (k^(1) * ( H ( m ) + x r ) ) mod q.
let s = &(&rsa::invmod(&k, &params.q)? * &(&h(msg)? + &(&self.x * &r))) % &params.q;

View File

@@ -75,4 +75,5 @@ fn main() {
set6::challenge43().unwrap_or_else(|| println!("[fail] challenge 43"));
set6::challenge44().unwrap_or_else(|| println!("[fail] challenge 44"));
set6::challenge45().unwrap_or_else(|| println!("[fail] challenge 45"));
set6::challenge46().unwrap_or_else(|| println!("[fail] challenge 46"));
}

View File

@@ -282,6 +282,64 @@ pub fn challenge44() -> Option<()> {
}
pub fn challenge45() -> Option<()> {
println!("[xxxx] Challenge 45: DSA parameter tampering");
// Part 1: 0 mod p
//
// Use the parameters from the previous exercise, but substitute 0 for "g". Generate a
// signature. You will notice something bad.
//
// Observation:
//
// - If g=0, because of r := (g^k mod p) mod q, it follows r=0.
// - When verifying, v := ((g^u1 * y^u2) % p) % q).
// - Therefore, v=0, and v == r is always true for any signature.
//
// Our implementation catches this case, both for signing and verifying.
// Part 2: 1 mod p
let mut params = dsa::DsaParameters::new().ok()?;
fn generate_magic_signature(
params: &mut dsa::DsaParameters,
) -> Result<dsa::DsaSig, ErrorStack> {
let mut ctx = BigNumContext::new()?;
//Now, try (p+1) as "g". With this "g", you can generate a magic signature s, r for any DSA
//public key that will validate against any string.
params.g = &params.p + &BigNum::from_u32(1)?;
// For arbitrary z:
// r = ((y**z) % p) % q
let mut r = BigNum::from_u32(0)?;
let z = BigNum::from_u32(1337)?;
r.mod_exp(&params.g, &z, &params.p, &mut ctx)?;
r = &r % &params.q;
// r
// s = --- % q
// z
let s = &rsa::invmod(&z, &params.q)? * &r;
// k doesn't matter
let k = BigNum::from_u32(0)?;
Ok(dsa::DsaSig { r, s, k })
}
let sig = generate_magic_signature(&mut params).ok()?;
let keys = dsa::DsaKeys::new(&params).ok()?;
let msg = Bytes::from_utf8("Hello, world");
let result = keys.verify(&params, &msg, &sig).ok()?;
assert!(result, "verify failed unexpectedly");
let msg = Bytes::from_utf8("Goodbye, world");
let result = keys.verify(&params, &msg, &sig).ok()?;
assert!(result, "verify failed unexpectedly");
println!("[okay] Challenge 45: DSA parameter tampering");
Some(())
}
pub fn challenge46() -> Option<()> {
println!("[xxxx] Challenge 46: RSA parity oracle");
None
}