From 22b4fcbd94195ff7f64b173cb8aa144f3fc67a65 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Thu, 4 Apr 2019 20:02:41 -0700 Subject: [PATCH] Farm off the SSH DSA support into its own module. --- src/ssh/dsa.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ssh/mod.rs | 79 ++---------------------------------------------- 2 files changed, 84 insertions(+), 76 deletions(-) create mode 100644 src/ssh/dsa.rs diff --git a/src/ssh/dsa.rs b/src/ssh/dsa.rs new file mode 100644 index 0000000..ceb7c1b --- /dev/null +++ b/src/ssh/dsa.rs @@ -0,0 +1,81 @@ +use cryptonum::unsigned::*; +use dsa::{DSAKeyPair,DSAParameters,DSAPubKey,DSAPublicKey,DSAPrivKey,DSAPrivateKey,L1024N160}; +use std::io::{Read,Write}; +use ssh::errors::{SSHKeyParseError,SSHKeyRenderError}; +use ssh::frame::*; +use ssh::SSHKey; + +impl SSHKey for DSAKeyPair { + fn parse_ssh_public_info(inp: &mut I) -> Result + { + let pubkey_type = parse_openssh_string(inp)?; + if pubkey_type != "ssh-dss" { + return Err(SSHKeyParseError::UnknownKeyType(pubkey_type)); + } + let pubp = parse_openssh_number(inp)?; + let pubq = parse_openssh_number(inp)?; + let pubg = parse_openssh_number(inp)?; + let pubparams = L1024N160::new(pubp, pubg, pubq); + let puby: U1024 = parse_openssh_number(inp)?; + for _ in inp.bytes() { return Err(SSHKeyParseError::UnknownTrailingData); } + Ok(DSAPubKey::::new(pubparams.clone(), puby.clone())) + } + + fn parse_ssh_private_info(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError> + { + let check1 = parse_openssh_u32(inp)?; + let check2 = parse_openssh_u32(inp)?; + if check1 != check2 { + return Err(SSHKeyParseError::PrivateKeyCorruption); + } + let privkey_type = parse_openssh_string(inp)?; + if privkey_type != "ssh-dss" { + return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-dss".to_string(), privkey_type)); + } + let privp = parse_openssh_number(inp)?; + let privq = parse_openssh_number(inp)?; + let privg = parse_openssh_number(inp)?; + let privparams = L1024N160::new(privp, privg, privq); + let _ = parse_openssh_buffer(inp)?; // a copy of y we don't need + let privx = parse_openssh_number(inp)?; + + let privkey = DSAPrivKey::::new(privparams, privx); + let comment = parse_openssh_string(inp)?; + for (idx,byte) in inp.bytes().enumerate() { + if ((idx+1) as u8) != byte? { + return Err(SSHKeyParseError::InvalidPadding); + } + } + + Ok((privkey,comment)) + } + + fn render_ssh_public_info(&self, out: &mut O) -> Result<(),SSHKeyRenderError> + { + render_openssh_string(out, "ssh-dss")?; + render_openssh_number(out, &self.public.params.p)?; + render_openssh_number(out, &self.public.params.q)?; + render_openssh_number(out, &self.public.params.g)?; + render_openssh_number(out, &self.public.y) + } + + fn render_ssh_private_info(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError> + { + render_openssh_u32(out, 0xDEADBEEF)?; // FIXME: Any reason for this to be random? + render_openssh_u32(out, 0xDEADBEEF)?; // ditto + render_openssh_string(out, "ssh-dss")?; + render_openssh_number(out, &self.private.params.p)?; + render_openssh_number(out, &self.private.params.q)?; + render_openssh_number(out, &self.private.params.g)?; + render_openssh_number(out, &self.public.y)?; + render_openssh_number(out, &self.private.x)?; + render_openssh_string(out, comment)?; + // add some padding (not quite sure why) + let mut i = comment.len(); + while (i % 16) != 0 { + out.write(&[(i - comment.len() + 1) as u8])?; + i += 1; + } + Ok(()) + } +} diff --git a/src/ssh/mod.rs b/src/ssh/mod.rs index ab5fca5..5787676 100644 --- a/src/ssh/mod.rs +++ b/src/ssh/mod.rs @@ -1,10 +1,9 @@ +mod dsa; mod errors; mod frame; pub use self::errors::{SSHKeyParseError,SSHKeyRenderError}; -use cryptonum::unsigned::*; -use dsa::{DSAKeyPair,DSAParameters,DSAPubKey,DSAPublicKey,DSAPrivKey,DSAPrivateKey,L1024N160}; use self::frame::*; use std::fs::File; use std::io::{Cursor,Read,Write}; @@ -100,81 +99,9 @@ pub fn write_ssh_keyfile(path: P, x: &KP, comment: &str) -> Result<(),SSHK } -impl SSHKey for DSAKeyPair { - fn parse_ssh_public_info(inp: &mut I) -> Result - { - let pubkey_type = parse_openssh_string(inp)?; - if pubkey_type != "ssh-dss" { - return Err(SSHKeyParseError::UnknownKeyType(pubkey_type)); - } - let pubp = parse_openssh_number(inp)?; - let pubq = parse_openssh_number(inp)?; - let pubg = parse_openssh_number(inp)?; - let pubparams = L1024N160::new(pubp, pubg, pubq); - let puby: U1024 = parse_openssh_number(inp)?; - for _ in inp.bytes() { return Err(SSHKeyParseError::UnknownTrailingData); } - Ok(DSAPubKey::::new(pubparams.clone(), puby.clone())) - } - - fn parse_ssh_private_info(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError> - { - let check1 = parse_openssh_u32(inp)?; - let check2 = parse_openssh_u32(inp)?; - if check1 != check2 { - return Err(SSHKeyParseError::PrivateKeyCorruption); - } - let privkey_type = parse_openssh_string(inp)?; - if privkey_type != "ssh-dss" { - return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-dss".to_string(), privkey_type)); - } - let privp = parse_openssh_number(inp)?; - let privq = parse_openssh_number(inp)?; - let privg = parse_openssh_number(inp)?; - let privparams = L1024N160::new(privp, privg, privq); - let _ = parse_openssh_buffer(inp)?; // a copy of y we don't need - let privx = parse_openssh_number(inp)?; - - let privkey = DSAPrivKey::::new(privparams, privx); - let comment = parse_openssh_string(inp)?; - for (idx,byte) in inp.bytes().enumerate() { - if ((idx+1) as u8) != byte? { - return Err(SSHKeyParseError::InvalidPadding); - } - } - - Ok((privkey,comment)) - } - - fn render_ssh_public_info(&self, out: &mut O) -> Result<(),SSHKeyRenderError> - { - render_openssh_string(out, "ssh-dss")?; - render_openssh_number(out, &self.public.params.p)?; - render_openssh_number(out, &self.public.params.q)?; - render_openssh_number(out, &self.public.params.g)?; - render_openssh_number(out, &self.public.y) - } - - fn render_ssh_private_info(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError> - { - render_openssh_u32(out, 0xDEADBEEF)?; // FIXME: Any reason for this to be random? - render_openssh_u32(out, 0xDEADBEEF)?; // ditto - render_openssh_string(out, "ssh-dss")?; - render_openssh_number(out, &self.private.params.p)?; - render_openssh_number(out, &self.private.params.q)?; - render_openssh_number(out, &self.private.params.g)?; - render_openssh_number(out, &self.public.y)?; - render_openssh_number(out, &self.private.x)?; - render_openssh_string(out, comment)?; - // add some padding (not quite sure why) - let mut i = comment.len(); - while (i % 16) != 0 { - out.write(&[(i - comment.len() + 1) as u8])?; - i += 1; - } - Ok(()) - } -} +#[cfg(test)] +use dsa::{DSAKeyPair,DSAPublicKey,DSAPrivateKey,L1024N160}; #[cfg(test)] use sha2::Sha256;