diff --git a/src/ecdsa/mod.rs b/src/ecdsa/mod.rs index bd01804..0c924e3 100644 --- a/src/ecdsa/mod.rs +++ b/src/ecdsa/mod.rs @@ -1,2 +1,3 @@ pub mod curve; -pub mod point; \ No newline at end of file +pub mod point; +pub mod private; \ No newline at end of file diff --git a/src/ecdsa/private.rs b/src/ecdsa/private.rs new file mode 100644 index 0000000..f7a264d --- /dev/null +++ b/src/ecdsa/private.rs @@ -0,0 +1,84 @@ +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::point::{ECCPoint,Point}; +use hmac::{Hmac,Mac}; + +pub struct ECCPrivate { + d: Curve::Unsigned +} + +impl ECCPrivate +{ + pub fn new(d: U192) -> ECCPrivate + { + ECCPrivate{ d } + } + + + pub fn sign(&self, m: &[u8]) -> DSASignature + where + Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, + Hmac: Mac + { + // This algorithm is per RFC 6979, which has a nice, relatively + // straightforward description of how to do DSA signing. + // + // 1. H(m) is transformed into an integer modulo q using the bits2int + // transform and an extra modular reduction: + // + // h = bits2int(H(m)) mod q + // + // As was noted in the description of bits2octets, the extra + // modular reduction is no more than a conditional subtraction. + // + let h1 = ::digest(m); + let size = ::size(); + let h0: U192 = bits2int(&h1, size); + 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 + // of the remainder of this document will revolve around the + // 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(), &::b()) { + // 3. A value r (modulo q) is computed from k and the key + // parameters: + // * For DSA ... + // * For ECDSA ... + // + // If r turns out to be zero, a new k should be selected and r + // computed again (this is an utterly improbable occurrence). + let g = Point::::default(); + let ki = I192::new(false, k.clone()); + let kg = g.scale(&ki); + let n = P192::n(); + let ni = I192::from(&n); + let ri = &kg.x % ∋ + if ri.is_zero() { + continue; + } + if ri.is_negative() { + continue; + } + let r = U192::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 = U192::from(hxr * U448::from(kinv)); + let s = base % n; + return DSASignature{ r, s }; + } + } + panic!("The world is broken; couldn't find a k in sign()."); + } +} \ No newline at end of file