From 2912c72a0797d310e9aa02c0de1c633d3c400534 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Sun, 26 May 2019 16:59:43 -0700 Subject: [PATCH] Add a bunch of DSA documentation. --- src/dsa/mod.rs | 21 +++++++++++++++++++++ src/dsa/params.rs | 17 ++++++++++++++++- src/dsa/private.rs | 4 ++++ src/dsa/public.rs | 4 ++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/dsa/mod.rs b/src/dsa/mod.rs index 94de91f..20620c1 100644 --- a/src/dsa/mod.rs +++ b/src/dsa/mod.rs @@ -2,6 +2,11 @@ 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; @@ -15,6 +20,12 @@ 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

, @@ -32,10 +43,20 @@ impl KeyPair for DSAKeyPair

} } +/// A trait that's useful to indicate that the given key pair can be +/// generated at runtime, if necessary. Note, once again (I never get +/// tired of this): You should probably only use this for testing or, +/// for legacy protocols, because you probably shouldn't be using DSA +/// in new systems. pub trait DSAKeyGeneration { type Params; + /// 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). fn generate(params: &Self::Params, rng: &mut G) -> Self; } diff --git a/src/dsa/params.rs b/src/dsa/params.rs index 107cae8..9018438 100644 --- a/src/dsa/params.rs +++ b/src/dsa/params.rs @@ -6,16 +6,30 @@ use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr}; use rand::Rng; use utils::TranslateNums; +/// A trait that describes what a set of DSA parameters must support in +/// order to be used by the rest of the system. pub trait DSAParameters : ToASN1 { + /// The fixed-width, unsigned type of values in L. type L; + /// The fixed-width, unsigned type of values in N. type N; + /// Given a `p`, `g`, and `q`, generate a new structure that includes + /// this information. Optionally, do any cross-checks needed. fn new(p: Self::L, g: Self::L, q: Self::N) -> Self; + /// Generate a new set of DSA parameters given the provided random + /// number generator. Just as with key generation, this should be a + /// cryptographically-strong random number generator. If it's not, + /// you may be writing compromisable code. fn generate(rng: &mut G) -> Self; + /// Return the size of values of N in bits. fn n_size() -> usize; + /// Return the size of values of L in bits. fn l_size() -> usize; - + /// Return the size of `q` in this particular instance of the parameters. + /// (Should be the same as `n_size()`, and the default implementation + /// simply uses `n_size(), but included for convenience) fn n_bits(&self) -> usize { Self::n_size() } @@ -23,6 +37,7 @@ pub trait DSAParameters : ToASN1 macro_rules! generate_parameters { ($name: ident, $ltype: ident, $ntype: ident, $l: expr, $n: expr) => { + /// DSA parameters to the given L and N, with the values given in bits. #[derive(Clone,PartialEq)] pub struct $name { pub p: $ltype, diff --git a/src/dsa/private.rs b/src/dsa/private.rs index cc7400e..7f00317 100644 --- a/src/dsa/private.rs +++ b/src/dsa/private.rs @@ -5,12 +5,16 @@ use dsa::params::*; use dsa::rfc6979::*; use hmac::{Hmac,Mac}; +/// A DSA private key, parameterized by its DSA parameters (so that you don't +/// accidentally pass the wrong key to the wrong routine). pub struct DSAPrivateKey { pub(crate) params: Params, pub(crate) x: Params::N } +/// A generic DSA private key enum, which masks which kind of DSA key (1024, +/// 2048 with the small `n`, 2048 with the normal `n`, or 3072) you're using. pub enum DSAPrivate { DSA1024Private(DSAPrivateKey), DSA2048SmallPrivate(DSAPrivateKey), diff --git a/src/dsa/public.rs b/src/dsa/public.rs index afcc418..d696f54 100644 --- a/src/dsa/public.rs +++ b/src/dsa/public.rs @@ -7,11 +7,15 @@ use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,ToASN1}; use std::cmp::min; use utils::TranslateNums; +/// A DSA public key, parameterized by its DSA parameters (so that you don't +/// accidentally pass the wrong thing to the wrong function). pub struct DSAPublicKey { pub(crate) params: Params, pub(crate) y: Params::L } +/// An enumeration that hides exactly which parameters you're using. Use at +/// your own risk, as the types won't save you. pub enum DSAPublic { DSAPublicL1024N160(DSAPublicKey), DSAPublicL2048N224(DSAPublicKey),