Pull out some common bits in private rendering.
This commit is contained in:
@@ -63,23 +63,13 @@ impl SSHKey for DSAKeyPair<L1024N160> {
|
|||||||
render_openssh_number(out, &self.public.y)
|
render_openssh_number(out, &self.public.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_ssh_private_info<O: Write>(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError>
|
fn render_ssh_private_info<O: Write>(&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_string(out, "ssh-dss")?;
|
||||||
render_openssh_number(out, &self.private.params.p)?;
|
render_openssh_number(out, &self.private.params.p)?;
|
||||||
render_openssh_number(out, &self.private.params.q)?;
|
render_openssh_number(out, &self.private.params.q)?;
|
||||||
render_openssh_number(out, &self.private.params.g)?;
|
render_openssh_number(out, &self.private.params.g)?;
|
||||||
render_openssh_number(out, &self.public.y)?;
|
render_openssh_number(out, &self.public.y)?;
|
||||||
render_openssh_number(out, &self.private.x)?;
|
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(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
78
src/ssh/ecdsa.rs
Normal file
78
src/ssh/ecdsa.rs
Normal file
@@ -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<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
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<I: Read>(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<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-ecdsa")?;
|
||||||
|
panic!("render public info")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_private_info<O: Write>(&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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ pub trait SSHKey: Sized + KeyPair {
|
|||||||
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>;
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>;
|
||||||
|
|
||||||
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>;
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>;
|
||||||
fn render_ssh_private_info<O: Write>(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError>;
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_ssh<KP: SSHKey>(x: &str) -> Result<(KP, String),SSHKeyParseError>
|
pub fn decode_ssh<KP: SSHKey>(x: &str) -> Result<(KP, String),SSHKeyParseError>
|
||||||
@@ -114,8 +114,20 @@ pub fn encode_ssh<KP: SSHKey>(x: &KP, comment: &str) -> Result<String,SSHKeyRend
|
|||||||
let mut privkeybin = Vec::with_capacity(8192);
|
let mut privkeybin = Vec::with_capacity(8192);
|
||||||
let mut binary = Vec::with_capacity(16384);
|
let mut binary = Vec::with_capacity(16384);
|
||||||
|
|
||||||
|
// create the public key bits
|
||||||
x.render_ssh_public_info(&mut pubkeybin)?;
|
x.render_ssh_public_info(&mut pubkeybin)?;
|
||||||
x.render_ssh_private_info(&mut privkeybin, comment)?;
|
// create the private key bits
|
||||||
|
render_openssh_u32(&mut privkeybin, 0xDEADBEEF)?; // FIXME: Any reason for this to be random?
|
||||||
|
render_openssh_u32(&mut privkeybin, 0xDEADBEEF)?; // ditto
|
||||||
|
x.render_ssh_private_info(&mut privkeybin)?;
|
||||||
|
render_openssh_string(&mut privkeybin, comment)?;
|
||||||
|
// add some padding (not quite sure why)
|
||||||
|
let mut i = comment.len();
|
||||||
|
while (i % 16) != 0 {
|
||||||
|
privkeybin.write(&[(i - comment.len() + 1) as u8])?;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
// render a bunch of the framing stuff
|
||||||
render_openssh_header(&mut binary)?;
|
render_openssh_header(&mut binary)?;
|
||||||
render_openssh_string(&mut binary, "none")?; // ciphername
|
render_openssh_string(&mut binary, "none")?; // ciphername
|
||||||
render_openssh_string(&mut binary, "none")?; // kdfname
|
render_openssh_string(&mut binary, "none")?; // kdfname
|
||||||
@@ -148,7 +160,7 @@ use sha2::Sha256;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
fn read_dsa_examples() {
|
fn dsa_examples() {
|
||||||
let test_files = ["dsa1024-1", "dsa1024-2", "dsa1024-3"];
|
let test_files = ["dsa1024-1", "dsa1024-2", "dsa1024-3"];
|
||||||
|
|
||||||
for file in test_files.iter() {
|
for file in test_files.iter() {
|
||||||
@@ -204,7 +216,7 @@ fn read_dsa_examples() {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
fn read_rsa_examples() {
|
fn rsa_examples() {
|
||||||
let test_files = ["rsa1024-1", "rsa1024-2", "rsa1024-3",
|
let test_files = ["rsa1024-1", "rsa1024-2", "rsa1024-3",
|
||||||
"rsa2048-1", "rsa2048-2", "rsa2048-3",
|
"rsa2048-1", "rsa2048-2", "rsa2048-3",
|
||||||
"rsa3072-1", "rsa3072-2", "rsa3072-3",
|
"rsa3072-1", "rsa3072-2", "rsa3072-3",
|
||||||
|
|||||||
@@ -153,10 +153,8 @@ impl SSHKey for RSAPair {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_ssh_private_info<O: Write>(&self, out: &mut O, comment: &str) -> Result<(),SSHKeyRenderError>
|
fn render_ssh_private_info<O: Write>(&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")?;
|
render_openssh_string(out, "ssh-rsa")?;
|
||||||
match self {
|
match self {
|
||||||
RSAPair::R512(pbl,prv) => {
|
RSAPair::R512(pbl,prv) => {
|
||||||
@@ -198,14 +196,6 @@ impl SSHKey for RSAPair {
|
|||||||
/* iqmp */ render_openssh_buffer(out, &vec![])?;
|
/* iqmp */ render_openssh_buffer(out, &vec![])?;
|
||||||
/* p */ render_openssh_buffer(out, &vec![])?;
|
/* p */ render_openssh_buffer(out, &vec![])?;
|
||||||
/* q */ 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user