diff --git a/src/dsa/mod.rs b/src/dsa/mod.rs index a44e4a3..03ecf52 100644 --- a/src/dsa/mod.rs +++ b/src/dsa/mod.rs @@ -2,7 +2,7 @@ mod errors; mod params; mod private; mod public; -mod rfc6979; +pub mod rfc6979; #[cfg(test)] mod tests; diff --git a/src/dsa/rfc6979.rs b/src/dsa/rfc6979.rs index 7b3fd92..c81ef20 100644 --- a/src/dsa/rfc6979.rs +++ b/src/dsa/rfc6979.rs @@ -6,6 +6,7 @@ use num::BigInt; use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr}; use simple_asn1::{FromASN1,ToASN1}; use utils::TranslateNums; +use std::ops::{Shr,Sub}; #[derive(Debug,PartialEq)] pub struct DSASignature @@ -26,9 +27,8 @@ impl DSASignature pub struct KIterator where H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, - N: Clone + Encoder + From + PartialOrd, - Hmac: Mac, - U512: From + N: Clone + Decoder + Encoder + From + PartialOrd + Shr, + Hmac: Mac { hmac_k: Hmac, V: Vec, @@ -39,9 +39,8 @@ pub struct KIterator impl KIterator where H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, - N: Clone + Encoder + From + PartialOrd, - Hmac: Mac, - U512: From + N: Clone + Decoder + Encoder + From + PartialOrd + Shr + Sub, + Hmac: Mac { pub fn new(h1: &[u8], qlen: usize, q: &N, x: &N) -> KIterator { @@ -129,9 +128,8 @@ impl KIterator impl Iterator for KIterator where H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, - N: Clone + CryptoNum + Encoder + From + PartialOrd, - Hmac: Mac, - U512: From + N: Clone + CryptoNum + Decoder + Encoder + From + PartialOrd + Shr, + Hmac: Mac { type Item = N; @@ -184,26 +182,28 @@ impl Iterator for KIterator } } -pub fn bits2int>(x: &[u8], qlen: usize) -> X +pub fn bits2int(x: &[u8], qlen: usize) -> X + where + X: Decoder + Shr { - let mut value = U512::from_bytes(x); - let vlen = x.len() * 8; - if vlen > qlen { - value >>= vlen - qlen; + if qlen < (x.len() * 8) { + let mut fixed_x = Vec::from(x); + let qlen_bytes = (qlen + 7) / 8; + let rounded_qlen = qlen_bytes * 8; + fixed_x.resize(qlen_bytes, 0); + X::from_bytes(&fixed_x) >> (rounded_qlen - qlen) + } else { + X::from_bytes(x) } - - X::from(value) } fn bits2octets(x: &[u8], q: &X, qlen: usize) -> Vec where - X: Clone + From, - U512: From + X: Clone + Decoder + Encoder + PartialOrd + Sub + Shr { - let z1: U512 = bits2int(x, qlen); - let qbig = U512::from(q.clone()); - let res = if z1 > qbig { z1 - qbig } else { z1 }; + let z1: X = bits2int(x, qlen); + let res = if &z1 > q { z1 - q.clone() } else { z1 }; int2octets(&res, qlen) } @@ -311,8 +311,9 @@ impl ToASN1 for DSASignature #[cfg(test)] mod tests { use cryptonum::unsigned::U192; - use sha2::Sha256; + use sha2::{Sha224,Sha256,Sha384,Sha512}; use super::*; + use testing::*; const QBYTES: [u8; 21] = [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x08, 0xA2, 0xE0, 0xCC, @@ -362,4 +363,81 @@ mod tests { } } } + + use cryptonum::unsigned::*; + + macro_rules! k_generator_tests { + ($testname: ident, $hash: ident, $fname: expr) => { + #[test] + fn $testname() { + let fname = build_test_path("rfc6979", $fname); + run_test(fname.to_string(), 7, |case| { + let (negq, qbytes) = case.get("q").unwrap(); + let (negl, lbytes) = case.get("l").unwrap(); + let (negx, xbytes) = case.get("x").unwrap(); + let (negh, h1) = case.get("h").unwrap(); + let (negk, kbytes) = case.get("k").unwrap(); + let (negy, ybytes) = case.get("y").unwrap(); + let (negz, zbytes) = case.get("z").unwrap(); + + assert!(!negq && !negl && !negx && !negh && + !negk && !negy && !negz); + let qlen = usize::from(U192::from_bytes(lbytes)); + assert!(qlen >= 160); assert!(qlen <= 521); + + if qlen < 192 { + let q = U192::from_bytes(qbytes); + let x = U192::from_bytes(xbytes); + let k = U192::from_bytes(kbytes); + let y = U192::from_bytes(ybytes); + let z = U192::from_bytes(zbytes); + + let mut kiter = KIterator::<$hash,U192>::new(h1,qlen,&q,&x); + assert_eq!(Some(k), kiter.next(), "first value test"); + assert_eq!(Some(y), kiter.next(), "second value test"); + assert_eq!(Some(z), kiter.next(), "third value test"); + } else if qlen < 256 { + let q = U256::from_bytes(qbytes); + let x = U256::from_bytes(xbytes); + let k = U256::from_bytes(kbytes); + let y = U256::from_bytes(ybytes); + let z = U256::from_bytes(zbytes); + + let mut kiter = KIterator::<$hash,U256>::new(h1,qlen,&q,&x); + assert_eq!(Some(k), kiter.next(), "first value test"); + assert_eq!(Some(y), kiter.next(), "second value test"); + assert_eq!(Some(z), kiter.next(), "third value test"); + } else if qlen < 512 { + let q = U512::from_bytes(qbytes); + let x = U512::from_bytes(xbytes); + let k = U512::from_bytes(kbytes); + let y = U512::from_bytes(ybytes); + let z = U512::from_bytes(zbytes); + + let mut kiter = KIterator::<$hash,U512>::new(h1,qlen,&q,&x); + assert_eq!(Some(k), kiter.next(), "first value test"); + assert_eq!(Some(y), kiter.next(), "second value test"); + assert_eq!(Some(z), kiter.next(), "third value test"); + } else { + let q = U576::from_bytes(qbytes); + let x = U576::from_bytes(xbytes); + let k = U576::from_bytes(kbytes); + let y = U576::from_bytes(ybytes); + let z = U576::from_bytes(zbytes); + + let mut kiter = KIterator::<$hash,U576>::new(h1,qlen,&q,&x); + assert_eq!(Some(k), kiter.next(), "first value test"); + assert_eq!(Some(y), kiter.next(), "second value test"); + assert_eq!(Some(z), kiter.next(), "third value test"); + } + }); + } + }; + } + + k_generator_tests!(kgen_sha224, Sha224, "SHA224"); + k_generator_tests!(kgen_sha256, Sha256, "SHA256"); + k_generator_tests!(kgen_sha384, Sha384, "SHA384"); + k_generator_tests!(kgen_sha512, Sha512, "SHA512"); + } \ No newline at end of file