DSA support!

This commit is contained in:
2018-12-08 10:59:14 -06:00
parent 160618cdd7
commit 62cb276888
11 changed files with 1409 additions and 23 deletions

87
src/dsa/public.rs Normal file
View File

@@ -0,0 +1,87 @@
use cryptonum::unsigned::*;
use cryptonum::signed::ModInv;
use digest::Digest;
use dsa::params::*;
use dsa::rfc6979::DSASignature;
use num::BigInt;
use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr};
use std::cmp::min;
use utils::TranslateNums;
pub trait DSAPublicKey<Params,L,N> {
/// Generate a new public key given the parameters and public value.
fn new(params: Params, y: L) -> Self;
/// Verify the given signature against the given message, using the
/// appropriate hash function.
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<N>) -> bool
where Hash: Digest;
}
pub struct DSAPubKey<Params,L> {
pub(crate) params: Params,
pub(crate) y: L
}
macro_rules! pubkey_impls {
($ptype: ident, $ltype: ident, $ntype: ident, $dbl: ident, $bdbl: ident) => {
impl DSAPublicKey<$ptype,$ltype,$ntype> for DSAPubKey<$ptype,$ltype>
{
fn new(params: $ptype, y: $ltype) -> DSAPubKey<$ptype,$ltype>
{
DSAPubKey{ params, y }
}
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
where Hash: Digest
{
if sig.r >= self.params.q {
return false;
}
if sig.s >= self.params.q {
return false;
}
// w = (s')^-1 mod q;
if let Some(w) = sig.s.modinv(&self.params.q) {
// z = the leftmost min(N, outlen) bits of Hash(M').
let mut digest_bytes = <Hash>::digest(m).to_vec();
let len = min(digest_bytes.len(), $ptype::n_size() / 8);
digest_bytes.truncate(len);
let z = $ntype::from_bytes(&digest_bytes);
// u1 = (zw) mod q
let qdbl = $dbl::from(&self.params.q);
let u1 = $ltype::from( (&z * &w) % &qdbl );
// u2 = (rw) mod q
let u2 = $ltype::from( (&sig.r * &w) % &qdbl );
// v = (((g)^u1(y)^u2) mod p) mod q
let v_1 = self.params.g.modexp(&u1, &self.params.p);
let v_2 = self.y.modexp(&u2, &self.params.p);
let bigp = $bdbl::from(&self.params.p);
let v_first_mod = (v_1 * v_2) % bigp;
let v = $ltype::from(v_first_mod) % $ltype::from(&self.params.q);
// if v = r, then the signature is verified
return $ntype::from(v) == sig.r
}
false
}
}
impl ToASN1 for DSAPubKey<$ptype,$ltype> {
type Error = ASN1EncodeErr;
fn to_asn1_class(&self, c: ASN1Class)
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
{
let uinty = self.y.to_num();
let inty = BigInt::from(uinty);
let yblock = ASN1Block::Integer(c, 0, inty);
Ok(vec![yblock])
}
}
};
}
pubkey_impls!(L1024N160, U1024, U192, U384, U2048);
pubkey_impls!(L2048N224, U2048, U256, U512, U4096);
pubkey_impls!(L2048N256, U2048, U256, U512, U4096);
pubkey_impls!(L3072N256, U3072, U256, U512, U6144);