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 bytes_base64;
|
||||||
mod cbc;
|
mod cbc;
|
||||||
mod ctr;
|
mod ctr;
|
||||||
|
mod dsa;
|
||||||
mod ecb;
|
mod ecb;
|
||||||
mod md4;
|
mod md4;
|
||||||
mod mt19937;
|
mod mt19937;
|
||||||
@@ -62,12 +63,12 @@ fn main() {
|
|||||||
set5::challenge33();
|
set5::challenge33();
|
||||||
set5::challenge34();
|
set5::challenge34();
|
||||||
set5::challenge35();
|
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::challenge41().unwrap_or_else(|| println!("[fail] challenge 41"));
|
||||||
set6::challenge42().unwrap_or_else(|| println!("[fail] challenge 42"));
|
set6::challenge42().unwrap_or_else(|| println!("[fail] challenge 42"));
|
||||||
set6::challenge43().unwrap_or_else(|| println!("[fail] challenge 43"));
|
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()?;
|
// let c = rsa::rsa_padding_remove_pkcs1(&c, n_0.num_bytes()).ok()?;
|
||||||
assert_eq!(c, m, "cube root implementation did not work");
|
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(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::bytes::Bytes;
|
||||||
|
use crate::dsa;
|
||||||
use crate::rsa;
|
use crate::rsa;
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
use openssl::bn::BigNum;
|
use openssl::bn::BigNum;
|
||||||
@@ -96,5 +98,12 @@ pub fn challenge42() -> Option<()> {
|
|||||||
|
|
||||||
pub fn challenge43() -> Option<()> {
|
pub fn challenge43() -> Option<()> {
|
||||||
println!("[xxxx] Challenge 43: TBD");
|
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(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user