Implement recovery of DSA x
This commit is contained in:
11
src/dsa.rs
11
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<BigNum, ErrorStack> {
|
||||
// (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<BigNum, ErrorStack> {
|
||||
let mut s1 = sha1::Sha1::default();
|
||||
BigNum::from_slice(&(s1.hash(message).0))
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user