diff --git a/src/ecdsa/private.rs b/src/ecdsa/private.rs index a863a3d..5337ccc 100644 --- a/src/ecdsa/private.rs +++ b/src/ecdsa/private.rs @@ -2,7 +2,7 @@ use cryptonum::signed::*; use cryptonum::unsigned::*; use digest::{BlockInput,Digest,Input,FixedOutput,Reset}; use dsa::rfc6979::{DSASignature,KIterator,bits2int}; -use ecdsa::curve::{EllipticCurve,P192}; +use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521}; use ecdsa::point::{ECCPoint,Point}; use hmac::{Hmac,Mac}; @@ -10,14 +10,30 @@ pub struct ECCPrivate { d: Curve::Unsigned } -impl ECCPrivate +pub trait ECCPrivateKey { + type Unsigned; + + fn new(d: Self::Unsigned) -> Self; + fn sign(&self, m: &[u8]) -> DSASignature + where + Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, + Hmac: Mac; +} + +macro_rules! generate_privates { - pub fn new(d: U192) -> ECCPrivate + ($curve: ident, $base: ident, $sig: ident, $dbl: ident, $quad: ident) => { + +impl ECCPrivateKey for ECCPrivate<$curve> +{ + type Unsigned = $base; + + fn new(d: $base) -> ECCPrivate<$curve> { ECCPrivate{ d } } - pub fn sign(&self, m: &[u8]) -> DSASignature + fn sign(&self, m: &[u8]) -> DSASignature<$base> where Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, Hmac: Mac @@ -34,12 +50,10 @@ impl ECCPrivate // modular reduction is no more than a conditional subtraction. // let h1 = ::digest(m); - let size = ::size(); - println!("h1: {:?}", h1); - let h0: U192 = bits2int(&h1, size); - println!("h0: {:X}", h0); - let h = h0 % ::n(); - println!("h: {:X}", h); + let size = <$curve>::size(); + let h0: $base = bits2int(&h1, size); + let n = <$curve>::n(); + let h = h0 % &n; // 2. A random value modulo q, dubbed k, is generated. That value // shall not be 0; hence, it lies in the [1, q-1] range. Most @@ -47,7 +61,7 @@ impl ECCPrivate // process used to generate k. In plain DSA or ECDSA, k should // be selected through a random selection that chooses a value // among the q-1 possible values with uniform probability. - for k in KIterator::::new(&h1, size, &::n(), &self.d) { + for k in KIterator::::new(&h1, size, &n, &self.d) { // 3. A value r (modulo q) is computed from k and the key // parameters: // * For DSA ... @@ -55,12 +69,10 @@ impl ECCPrivate // // If r turns out to be zero, a new k should be selected and r // computed again (this is an utterly improbable occurrence). - println!("k: {:X}", k); - let g = Point::::default(); - let ki = I192::new(false, k.clone()); + let g = Point::<$curve>::default(); + let ki = $sig::new(false, k.clone()); let kg = g.scale(&ki); - let n = P192::n(); - let ni = I192::from(&n); + let ni = $sig::from(&n); let ri = &kg.x % ∋ if ri.is_zero() { continue; @@ -68,78 +80,80 @@ impl ECCPrivate if ri.is_negative() { continue; } - let r = U192::from(ri); + let r = $base::from(ri); // 4. The value s (modulo q) is computed: // // s = (h+x*r)/k mod q // // The pair (r, s) is the signature. if let Some(kinv) = k.modinv(&n) { - let xr = &self.d * &r; - let hxr = U384::from(&h) + xr; - let base = hxr * U448::from(kinv); - let s = U192::from(base % U896::from(n)); + let mut hxr = &self.d * &r; + hxr += $dbl::from(&h); + let base = hxr * $dbl::from(kinv); + let s = $base::from(base % $quad::from(n)); return DSASignature{ r, s }; } } panic!("The world is broken; couldn't find a k in sign()."); } } + } +} + +generate_privates!(P192, U192, I192, U384, U768); +generate_privates!(P224, U256, I256, U512, U1024); +generate_privates!(P256, U256, I256, U512, U1024); +generate_privates!(P384, U384, I384, U768, U1536); +generate_privates!(P521, U576, I576, U1152, U2304); + +/************* TESTING ********************************************************/ #[cfg(test)] -mod tests { - use sha2::{Sha224,Sha256,Sha384,Sha512}; - use super::*; - use testing::*; +use sha2::{Sha224,Sha256,Sha384,Sha512}; +#[cfg(test)] +use testing::*; - #[test] - fn p192_sign() { - let fname = build_test_path("ecc/sign","P192"); - run_test(fname.to_string(), 9, |case| { - let (negd, dbytes) = case.get("d").unwrap(); - let (negk, kbytes) = case.get("k").unwrap(); - let (negx, xbytes) = case.get("x").unwrap(); - let (negy, ybytes) = case.get("y").unwrap(); - let (negm, mbytes) = case.get("m").unwrap(); - let (negh, hbytes) = case.get("h").unwrap(); - let (negr, rbytes) = case.get("r").unwrap(); - let (negs, sbytes) = case.get("s").unwrap(); +macro_rules! generate_tests { + ($name: ident, $curve: ident, $base: ident) => { + #[test] + fn $name() { + let fname = build_test_path("ecc/sign",stringify!($curve)); + run_test(fname.to_string(), 9, |case| { + let (negd, dbytes) = case.get("d").unwrap(); + let (negk, _bytes) = case.get("k").unwrap(); + let (negx, xbytes) = case.get("x").unwrap(); + let (negy, ybytes) = case.get("y").unwrap(); + let (negm, mbytes) = case.get("m").unwrap(); + let (negh, hbytes) = case.get("h").unwrap(); + let (negr, rbytes) = case.get("r").unwrap(); + let (negs, sbytes) = case.get("s").unwrap(); - assert!(!negd && !negk && !negx && !negy && - !negm && !negh && !negr && !negs); - let d = U192::from_bytes(dbytes); - let _ = U192::from_bytes(xbytes); - let _ = U192::from_bytes(ybytes); - let h = U192::from_bytes(hbytes); - let r = U192::from_bytes(rbytes); - let s = U192::from_bytes(sbytes); + assert!(!negd && !negk && !negx && !negy && + !negm && !negh && !negr && !negs); + let d = $base::from_bytes(dbytes); + let _ = $base::from_bytes(xbytes); + let _ = $base::from_bytes(ybytes); + let h = $base::from_bytes(hbytes); + let r = $base::from_bytes(rbytes); + let s = $base::from_bytes(sbytes); - { - let (negn, nbytes) = case.get("n").unwrap(); - println!("nbytes<{}>: {:?}", usize::from(h.clone()), nbytes); - println!("hash<224>: {:?}", Sha224::digest(mbytes)); - println!("hash<256>: {:?}", Sha256::digest(mbytes)); - println!("hash<384>: {:?}", Sha384::digest(mbytes)); - println!("hash<512>: {:?}", Sha512::digest(mbytes)); - println!("kbytes: {:?}", kbytes); - let k = U192::from_bytes(kbytes); - println!("k: {:X}", k); - println!("target r: {:X}", r); - println!("target s: {:X}", s); - } + let private = ECCPrivate::<$curve>::new(d); + let sig = match usize::from(h) { + 224 => private.sign::(mbytes), + 256 => private.sign::(mbytes), + 384 => private.sign::(mbytes), + 512 => private.sign::(mbytes), + x => panic!("Unknown hash algorithm {}", x) + }; + assert_eq!(r, sig.r, "r signature check"); + assert_eq!(s, sig.s, "s signature check"); + }); + } + }; +} - let private = ECCPrivate::new(d); - let sig = match usize::from(h) { - 224 => private.sign::(mbytes), - 256 => private.sign::(mbytes), - 384 => private.sign::(mbytes), - 512 => private.sign::(mbytes), - x => panic!("Unknown hash algorithm {}", x) - }; - println!("my r: {:X}", sig.r); - println!("my s: {:X}", sig.s); - assert_eq!(r, sig.r, "r signature check"); - assert_eq!(s, sig.s, "s signature check"); - }); - } -} \ No newline at end of file +generate_tests!(p192_sign, P192, U192); +generate_tests!(p224_sign, P224, U256); +generate_tests!(p256_sign, P256, U256); +generate_tests!(p384_sign, P384, U384); +generate_tests!(p521_sign, P521, U576); \ No newline at end of file