From 1eba2d1709b98f8e5ae95750b6297d3427b7eae9 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Tue, 16 Apr 2019 13:19:26 -0700 Subject: [PATCH] Pull out some common bits in private rendering. --- src/ssh/dsa.rs | 14 ++------- src/ssh/ecdsa.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ssh/mod.rs | 20 ++++++++++--- src/ssh/rsa.rs | 12 +------- 4 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 src/ssh/ecdsa.rs diff --git a/src/ssh/dsa.rs b/src/ssh/dsa.rs index 99ed967..39d873f 100644 --- a/src/ssh/dsa.rs +++ b/src/ssh/dsa.rs @@ -63,23 +63,13 @@ impl SSHKey for DSAKeyPair { render_openssh_number(out, &self.public.y) } - fn render_ssh_private_info(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError> + fn render_ssh_private_info(&self, out: &mut O) -> 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(()) + render_openssh_number(out, &self.private.x) } } diff --git a/src/ssh/ecdsa.rs b/src/ssh/ecdsa.rs new file mode 100644 index 0000000..a113eaa --- /dev/null +++ b/src/ssh/ecdsa.rs @@ -0,0 +1,78 @@ +use cryptonum::unsigned::*; +use ecdsa::{ECDSAPair,ECDSAPublic,ECCPublicKey,ECDSAPrivate,ECCPrivateKey}; +use std::io::{Read,Write}; +use ssh::errors::{SSHKeyParseError,SSHKeyRenderError}; +use ssh::frame::*; +use ssh::SSHKey; + +impl SSHKey for ECDSAPair { + fn valid_keytype(s: &str) -> bool { + (s == "ssh-ecdsa") || (s == "ecdsa") || (s == "ecdsa-sha2-nistp256") || + (s == "ecdsa-sha2-nistp384") || (s == "ecdsa-sha2-nistp521") + } + + fn parse_ssh_public_info(inp: &mut I) -> Result + { + let pubkey_type = parse_openssh_string(inp)?; + if !Self::valid_keytype(&pubkey_type) { + return Err(SSHKeyParseError::UnknownKeyType(pubkey_type)); + } + // this peaks a little under the cover a bit (it'd be nice to pretend + // that we didn't know the number format was the same as the buffer + // one), but we need to infer what kind of key this is, and this appears + // to be the easiest / fastest way. + let mut ebuf = parse_openssh_buffer(inp)?; + let mut ibuf = parse_openssh_buffer(inp)?; + + while ebuf[0] == 0 { ebuf.remove(0); } + while ibuf[0] == 0 { ibuf.remove(0); } + + println!("ebuf: {:?}", ebuf); + println!("ibuf: {:?}", ibuf); + panic!("parse public info") + } + + 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 !Self::valid_keytype(&privkey_type) { + return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-rsa".to_string(), privkey_type)); + } + + let comment = parse_openssh_string(inp)?; + for (idx,byte) in inp.bytes().enumerate() { + if ((idx+1) as u8) != byte? { + return Err(SSHKeyParseError::InvalidPadding); + } + } + + panic!("parse private_info") + } + + fn render_ssh_public_info(&self, out: &mut O) -> Result<(),SSHKeyRenderError> + { + render_openssh_string(out, "ssh-ecdsa")?; + panic!("render public info") + } + + 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-ecdsa")?; + panic!("render private info"); + 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 2220d7c..4d15bc7 100644 --- a/src/ssh/mod.rs +++ b/src/ssh/mod.rs @@ -19,7 +19,7 @@ pub trait SSHKey: Sized + KeyPair { fn parse_ssh_private_info(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>; fn render_ssh_public_info(&self, out: &mut O) -> Result<(),SSHKeyRenderError>; - fn render_ssh_private_info(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError>; + fn render_ssh_private_info(&self, out: &mut O) -> Result<(),SSHKeyRenderError>; } pub fn decode_ssh(x: &str) -> Result<(KP, String),SSHKeyParseError> @@ -114,8 +114,20 @@ pub fn encode_ssh(x: &KP, comment: &str) -> Result(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError> + fn render_ssh_private_info(&self, out: &mut O) -> 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-rsa")?; match self { RSAPair::R512(pbl,prv) => { @@ -198,14 +196,6 @@ impl SSHKey for RSAPair { /* iqmp */ render_openssh_buffer(out, &vec![])?; /* p */ render_openssh_buffer(out, &vec![])?; /* q */ render_openssh_buffer(out, &vec![])?; - - 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(()) } } \ No newline at end of file