diff --git a/src/dsa.rs b/src/dsa.rs index 3ea730c..1e8c232 100644 --- a/src/dsa.rs +++ b/src/dsa.rs @@ -22,6 +22,7 @@ pub struct DsaKeys { pub struct DsaSig { pub r: BigNum, pub s: BigNum, + pub k: BigNum, } impl DsaParameters { @@ -65,7 +66,7 @@ impl DsaKeys { // In the unlikely case that s=0, crash. assert!(s != zero, "s is zero"); - Ok(DsaSig { r, s }) + Ok(DsaSig { r, s, k }) } pub fn verify( @@ -99,6 +100,14 @@ impl DsaKeys { } } +pub fn recover_x(params: &DsaParameters, msg: &Bytes, sig: &DsaSig) -> Result { + // (s * k) - H(msg) + // x = ---------------- mod q + // r + let x = &(&rsa::invmod(&sig.r, ¶ms.q)? * &(&(&sig.s * &sig.k) - &h(msg)?)) % ¶ms.q; + Ok(x) +} + fn h(message: &Bytes) -> Result { let mut s1 = sha1::Sha1::default(); BigNum::from_slice(&(s1.hash(message).0)) diff --git a/src/set6.rs b/src/set6.rs index be7952d..8925524 100644 --- a/src/set6.rs +++ b/src/set6.rs @@ -101,9 +101,12 @@ pub fn challenge43() -> Option<()> { 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"); + let sig = keys.sign(¶ms, &msg).ok()?; + let result = keys.verify(¶ms, &msg, &sig).ok()?; + assert!(result, "verify failed unexpectedly"); + + let recovered_x = dsa::recover_x(¶ms, &msg, &sig).ok()?; + assert_eq!(recovered_x, keys.x, "DSA recovery failed"); Some(()) }