Implement DSA sign and verify to get started with challenge 43
This commit is contained in:
105
src/dsa.rs
Normal file
105
src/dsa.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use crate::bytes::Bytes;
|
||||
use crate::rsa;
|
||||
use crate::sha1;
|
||||
use openssl::bn::BigNum;
|
||||
use openssl::bn::BigNumContext;
|
||||
use openssl::error::ErrorStack;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DsaParameters {
|
||||
pub p: BigNum,
|
||||
pub q: BigNum,
|
||||
pub g: BigNum,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DsaKeys {
|
||||
pub x: BigNum,
|
||||
pub y: BigNum,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DsaSig {
|
||||
pub r: BigNum,
|
||||
pub s: BigNum,
|
||||
}
|
||||
|
||||
impl DsaParameters {
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
Ok(Self {
|
||||
p: BigNum::from_hex_str("800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1")?,
|
||||
q: BigNum::from_hex_str("f4f47f05794b256174bba6e9b396a7707e563c5b")?,
|
||||
g: BigNum::from_hex_str("5958c9d3898b224b12672c0b98e06c60df923cb8bc999d119458fef538b8fa4046c8db53039db620c094c9fa077ef389b5322a559946a71903f990f1f7e0e025e2d7f7cf494aff1a0470f5b64c36b625a097f1651fe775323556fe00b3608c887892878480e99041be601a62166ca6894bdd41a7054ec89f756ba9fc95302291")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DsaKeys {
|
||||
pub fn new(params: &DsaParameters) -> Result<Self, ErrorStack> {
|
||||
let mut ctx = BigNumContext::new()?;
|
||||
let mut x = BigNum::new()?;
|
||||
let mut y = BigNum::new()?;
|
||||
// Choose an integer x randomly from { 1 … q − 1 }
|
||||
params.q.rand_range(&mut x)?;
|
||||
// Compute y := g^x mod p
|
||||
y.mod_exp(¶ms.g, &x, ¶ms.p, &mut ctx)?;
|
||||
Ok(Self { x: x, y: y })
|
||||
}
|
||||
|
||||
pub fn sign(&self, params: &DsaParameters, msg: &Bytes) -> Result<DsaSig, ErrorStack> {
|
||||
let mut ctx = BigNumContext::new()?;
|
||||
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(¶ms.g, &k, ¶ms.p, &mut ctx)?;
|
||||
r = &r % ¶ms.q;
|
||||
}
|
||||
|
||||
// Compute s := (k^(−1) * ( H ( m ) + x r ) ) mod q.
|
||||
let s = &(&rsa::invmod(&k, ¶ms.q)? * &(&h(msg)? + &(&self.x * &r))) % ¶ms.q;
|
||||
|
||||
// In the unlikely case that s=0, crash.
|
||||
assert!(s != zero, "s is zero");
|
||||
|
||||
Ok(DsaSig { r, s })
|
||||
}
|
||||
|
||||
pub fn verify(
|
||||
&self,
|
||||
params: &DsaParameters,
|
||||
msg: &Bytes,
|
||||
sig: &DsaSig,
|
||||
) -> Result<bool, ErrorStack> {
|
||||
let mut ctx = BigNumContext::new()?;
|
||||
let zero = BigNum::from_u32(0)?;
|
||||
|
||||
// Verify that 0 < r < q and 0 < s < q
|
||||
if !(zero < sig.r && sig.r < params.q && zero < sig.s && sig.s < params.q) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// Compute w := s^(−1) mod q
|
||||
let w = rsa::invmod(&sig.s, ¶ms.q)?;
|
||||
let u1 = &(&h(&msg)? * &w) % ¶ms.q;
|
||||
let u2 = &(&sig.r * &w) % ¶ms.q;
|
||||
|
||||
// v := ((g^u1 * y^u2) % p) % q)
|
||||
let mut v1 = BigNum::new()?;
|
||||
v1.mod_exp(¶ms.g, &u1, ¶ms.p, &mut ctx)?;
|
||||
let mut v2 = BigNum::new()?;
|
||||
v2.mod_exp(&self.y, &u2, ¶ms.p, &mut ctx)?;
|
||||
let v = &(&(&v1 * &v2) % ¶ms.p) % ¶ms.q;
|
||||
|
||||
// The signature is valid if and only if v = r
|
||||
Ok(v == sig.r)
|
||||
}
|
||||
}
|
||||
|
||||
fn h(message: &Bytes) -> Result<BigNum, ErrorStack> {
|
||||
let mut s1 = sha1::Sha1::default();
|
||||
BigNum::from_slice(&(s1.hash(message).0))
|
||||
}
|
||||
11
src/main.rs
11
src/main.rs
@@ -8,6 +8,7 @@ mod bytes;
|
||||
mod bytes_base64;
|
||||
mod cbc;
|
||||
mod ctr;
|
||||
mod dsa;
|
||||
mod ecb;
|
||||
mod md4;
|
||||
mod mt19937;
|
||||
@@ -62,12 +63,12 @@ fn main() {
|
||||
set5::challenge33();
|
||||
set5::challenge34();
|
||||
set5::challenge35();
|
||||
set5::challenge36().unwrap_or_else(|| println!("[fail] challenge 36"));
|
||||
set5::challenge37().unwrap_or_else(|| println!("[fail] challenge 37"));
|
||||
set5::challenge38().unwrap_or_else(|| println!("[fail] challenge 38"));
|
||||
set5::challenge39().unwrap_or_else(|| println!("[fail] challenge 39"));
|
||||
set5::challenge40().unwrap_or_else(|| println!("[fail] challenge 40"));
|
||||
}
|
||||
set5::challenge36().unwrap_or_else(|| println!("[fail] challenge 36"));
|
||||
set5::challenge37().unwrap_or_else(|| println!("[fail] challenge 37"));
|
||||
set5::challenge38().unwrap_or_else(|| println!("[fail] challenge 38"));
|
||||
set5::challenge39().unwrap_or_else(|| println!("[fail] challenge 39"));
|
||||
set5::challenge40().unwrap_or_else(|| println!("[fail] challenge 40"));
|
||||
set6::challenge41().unwrap_or_else(|| println!("[fail] challenge 41"));
|
||||
set6::challenge42().unwrap_or_else(|| println!("[fail] challenge 42"));
|
||||
set6::challenge43().unwrap_or_else(|| println!("[fail] challenge 43"));
|
||||
|
||||
@@ -583,6 +583,6 @@ pub fn challenge40() -> Option<()> {
|
||||
// let c = rsa::rsa_padding_remove_pkcs1(&c, n_0.num_bytes()).ok()?;
|
||||
assert_eq!(c, m, "cube root implementation did not work");
|
||||
|
||||
println!("[okay] Challenge 40: implement an E=3 RSA Broadcast attack");
|
||||
println!("[okay] Challenge 40: implement an e=3 RSA Broadcast attack");
|
||||
Some(())
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::bytes::Bytes;
|
||||
use crate::dsa;
|
||||
use crate::rsa;
|
||||
use num_bigint::BigUint;
|
||||
use openssl::bn::BigNum;
|
||||
@@ -96,5 +98,12 @@ pub fn challenge42() -> Option<()> {
|
||||
|
||||
pub fn challenge43() -> Option<()> {
|
||||
println!("[xxxx] Challenge 43: TBD");
|
||||
let msg = Bytes::from_utf8("hello, world!");
|
||||
let params = dsa::DsaParameters::new().ok()?;
|
||||
let keys = dsa::DsaKeys::new(¶ms).ok()?;
|
||||
let s = keys.sign(¶ms, &msg).ok()?;
|
||||
let r = keys.verify(¶ms, &msg, &s).ok()?;
|
||||
assert!(r, "verify failed unexpectedly");
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user