diff --git a/ssh-key/src/private.rs b/ssh-key/src/private.rs index 140773d6..52273ee0 100644 --- a/ssh-key/src/private.rs +++ b/ssh-key/src/private.rs @@ -452,6 +452,8 @@ impl PrivateKey { pub fn random(mut rng: impl CryptoRng + RngCore, algorithm: Algorithm) -> Result { let checkint = rng.next_u32(); let key_data = match algorithm { + #[cfg(feature = "dsa")] + Algorithm::Dsa => KeypairData::from(DsaKeypair::random(rng)?), #[cfg(any(feature = "p256", feature = "p384"))] Algorithm::Ecdsa { curve } => KeypairData::from(EcdsaKeypair::random(rng, curve)?), #[cfg(feature = "ed25519")] diff --git a/ssh-key/src/private/dsa.rs b/ssh-key/src/private/dsa.rs index 0e4edde1..34370e04 100644 --- a/ssh-key/src/private/dsa.rs +++ b/ssh-key/src/private/dsa.rs @@ -13,6 +13,9 @@ use crate::Error; #[cfg(feature = "subtle")] use subtle::{Choice, ConstantTimeEq}; +#[cfg(all(feature = "dsa", feature = "rand_core"))] +use rand_core::{CryptoRng, RngCore}; + /// Digital Signature Algorithm (DSA) private key. /// /// Uniformly random integer `x`, such that `0 < x < q`, i.e. `x` is in the @@ -147,6 +150,21 @@ pub struct DsaKeypair { pub private: DsaPrivateKey, } +impl DsaKeypair { + /// Key size. + #[cfg(all(feature = "dsa", feature = "rand_core"))] + #[allow(deprecated)] + pub(crate) const KEY_SIZE: dsa::KeySize = dsa::KeySize::DSA_1024_160; + + /// Generate a random DSA private key. + #[cfg(all(feature = "dsa", feature = "rand_core"))] + #[cfg_attr(docsrs, doc(cfg(all(feature = "dsa", feature = "rand_core"))))] + pub fn random(mut rng: impl CryptoRng + RngCore) -> Result { + let components = dsa::Components::generate(&mut rng, Self::KEY_SIZE); + dsa::SigningKey::generate(&mut rng, components).try_into() + } +} + impl Decode for DsaKeypair { fn decode(reader: &mut impl Reader) -> Result { let public = DsaPublicKey::decode(reader)?;