//! If you want to use this module to generate keys, which you really //! really shouldn't, there are two ways to do so, depending on whether //! you've previously agreed on a set of DSA parameters for this key //! pair. If you haven't, you can generate the parameters using a good //! random number generator. //! //! ```rust //! extern crate sha2; //! //! use simple_crypto::dsa::{DSAKeyPair,DSAParameters,L2048N256}; //! use sha2::Sha224; //! //! // Generate a set of DSA parameters, assuming you don't have //! // them already //! let mut rng = rand::rngs::OsRng::new().unwrap(); //! let params = L2048N256::generate(&mut rng); //! //! // Given those parameters, you can generate a key pair like so: //! let kp = DSAKeyPair::::generate(¶ms, &mut rng); //! // Keeping in mind that you can re-use the parameters across multiple //! // keys, and that their secrecy isn't paramout for the security of the //! // algorithm. //! //! // Now that you have this key pair, you can sign and verify messages //! // using it. For example, to sign the vector [0,1,2,3,4] with SHA224 //! // and then verify that signature, we would write: //! let msg = vec![0,1,2,3,4]; //! let sig = kp.private.sign::(&msg); //! assert!( kp.public.verify::(&msg, &sig) ); //! ``` mod errors; mod params; mod private; mod public; /// Support for RFC6979 signing, which provides a secure way to generate /// signatures without the use of a random number generator. This is used /// in DSA signing as well as in ECDSA signing, but appears here because /// ... well, because it was written for DSA first, both historically /// (I think) and by me. pub mod rfc6979; #[cfg(test)] mod tests; pub use self::params::*; pub use self::private::*; pub use self::public::*; use cryptonum::unsigned::*; use rand::Rng; use rand::distributions::Standard; use super::KeyPair; /// A DSA key pair, for use in signing and signature verification. Note /// that you probably shouldn't be using DSA any more; ECDSA or ED25519 /// are probably better options. /// /// DSA key pairs are parameterized by their DSA parameters, so that /// you can't accidentally use them in the wrong place. pub struct DSAKeyPair { pub private: DSAPrivateKey

, pub public: DSAPublicKey

} impl KeyPair for DSAKeyPair

{ type Private = DSAPrivateKey

; type Public = DSAPublicKey

; fn new(public: DSAPublicKey

, private: DSAPrivateKey

) -> DSAKeyPair

{ DSAKeyPair{ private, public } } } macro_rules! generate_dsa_pair { ($ptype: ident, $ltype: ident, $ntype: ident, $nbig: ident) => { impl DSAKeyPair<$ptype> { /// Generate a DSA key pair using the given parameters and random /// number generator. Please make sure that the RNG you're using /// is suitable for key generators (look for the term "cryptographic" /// or "crypto strong" in its documentation, or see if it matches /// any of the NIST-suggested RNG algorithms). pub fn generate(params: &$ptype, rng: &mut G) -> Self { // 1. N = len(q); L = len(p); let n = $ptype::n_size(); // 2. If the (L,N) pair is invalid, then return an ERROR indicator, // Invalid_x, and Invalid_y. // 3. requested_security_strength = the security strength associated // with the (L, N) pair; see SP 800-57. // 4. Obtain a string of N+64 returned_bits from an RBG with a security // strength of requested_security_strength or more. If an ERROR // indication is returned, then return an ERROR indication, // Invalid_x, and Invalid_y. let returned_bits: Vec = rng.sample_iter(&Standard).take( (n + 64) / 8 ).collect(); // 5. Convert returned_bits to the (non-negative) integer c. let c = $nbig::from_bytes(&returned_bits); // 6. x = (c mod (q-1)) + 1. let one = $nbig::from(1 as u64); let qbig = $nbig::from(¶ms.q); let x = $ntype::from( (&c % (&qbig - &one)) + &one ); // 7. y = g^x mod p let y = params.g.modexp(&$ltype::from(&x), ¶ms.p); // 8. Return SUCCESS, x, and y. let private = DSAPrivateKey::<$ptype>::new(params.clone(), x); let public = DSAPublicKey::<$ptype>::new(params.clone(), y); DSAKeyPair { private, public } } } }; } generate_dsa_pair!(L1024N160, U1024, U192, U256); generate_dsa_pair!(L2048N224, U2048, U256, U384); generate_dsa_pair!(L2048N256, U2048, U256, U384); generate_dsa_pair!(L3072N256, U3072, U256, U384);