Commit 9bdb348f authored by Thomas Gatzweiler's avatar Thomas Gatzweiler
Browse files

Add comments and better error handling

parent 1806e5ac
......@@ -2,8 +2,10 @@ extern crate ssh;
use std::io::prelude::*;
use std::fs::File;
use ssh::public_key;
pub fn main() {
let keypair = (ssh::key::ED25519.generate_key_pair)(None);
let keypair = (public_key::ED25519.generate_key_pair)(None);
let mut buffer = File::create("key.pub").unwrap();
keypair.export(&mut buffer);
}
use key::{KeyPair, CryptoSystem};
use std::io::{self, Read, Write};
use rand::{self, Rng};
use crypto::ed25519;
pub static ED25519: CryptoSystem = CryptoSystem {
id: "ed25519",
generate_key_pair: Ed25519KeyPair::generate,
import: Ed25519KeyPair::import,
read_public: Ed25519KeyPair::read_public
};
struct Ed25519KeyPair {
private: Option<[u8;64]>,
public: [u8;32],
}
impl Ed25519KeyPair {
fn generate(_: Option<u32>) -> Box<KeyPair> {
let mut seed = [0u8;32];
let mut rng = rand::thread_rng();
rng.fill_bytes(&mut seed);
let (private, public) = ed25519::keypair(&seed);
Box::new(Ed25519KeyPair {
private: Some(private),
public: public
})
}
fn import(mut r: &mut Read) -> io::Result<Box<KeyPair>> {
use packet::ReadPacketExt;
let id = r.read_utf8()?;
assert_eq!(id, "ssh-ed25519");
let pub_len = r.read_uint32()?;
assert_eq!(pub_len, 32);
let mut public = [0u8;32];
r.read_exact(&mut public)?;
let priv_len = r.read_uint32()?;
assert_eq!(priv_len, 64);
let mut private = [0u8;64];
r.read_exact(&mut private)?;
Ok(Box::new(Ed25519KeyPair {
public: public,
private: Some(private)
}))
}
fn read_public(mut r: &mut Read) -> io::Result<Box<KeyPair>> {
use packet::ReadPacketExt;
let len = r.read_uint32()?;
assert_eq!(len, 32);
let mut public = [0u8;32];
r.read_exact(&mut public)?;
Ok(Box::new(Ed25519KeyPair {
private: None,
public: public
}))
}
}
impl KeyPair for Ed25519KeyPair {
fn system(&self) -> &'static CryptoSystem { &ED25519 }
fn has_private(&self) -> bool {
self.private.is_some()
}
fn verify(&self, data: &[u8], signature: &[u8]) -> Result<bool, ()> {
Ok(ed25519::verify(data, &self.public, signature))
}
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, ()> {
if let Some(private_key) = self.private {
let signature = ed25519::signature(data, &private_key);
Ok(signature.to_vec())
}
else {
Err(())
}
}
fn write_public(&self, w: &mut Write) -> io::Result<()> {
use packet::WritePacketExt;
w.write_string("ssh-ed25519")?;
w.write_bytes(&self.public)
}
fn export(&self, w: &mut Write) -> io::Result<()> {
use packet::WritePacketExt;
w.write_string("ssh-ed25519")?;
w.write_bytes(&self.public)?;
if let Some(private_key) = self.private {
w.write_bytes(&private_key)?;
}
Ok(())
}
}
use std::io::{self, Read, Write};
//mod rsa;
mod ed25519;
//pub use self::rsa::RSA;
pub use self::ed25519::ED25519;
pub trait KeyPair {
fn system(&self) -> &'static CryptoSystem;
fn has_private(&self) -> bool;
fn verify(&self, data: &[u8], signature: &[u8]) -> Result<bool, ()>;
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, ()>;
fn write_public(&self, w: &mut Write) -> io::Result<()>;
fn export(&self, w: &mut Write) -> io::Result<()>;
}
pub struct CryptoSystem {
pub id: &'static str,
pub generate_key_pair: fn(bits: Option<u32>) -> Box<KeyPair>,
pub import: fn(r: &mut Read) -> io::Result<Box<KeyPair>>,
pub read_public: fn(r: &mut Read) -> io::Result<Box<KeyPair>>
}
use key::{Key, PublicKey, PrivateKey, KeyPair, CryptoSystem};
use std::io::{Read, Write, Result};
pub static RSA: CryptoSystem = CryptoSystem {
id: "rsa",
generate_key_pair: generate_key_pair,
};
pub fn generate_key_pair(size: u32) -> KeyPair {
let public = Box::new(RsaPublicKey::new());
let private = Box::new(RsaPrivateKey::new());
(public, private)
}
pub struct RsaPublicKey {}
impl RsaPublicKey {
pub fn new() -> RsaPublicKey {
RsaPublicKey {}
}
}
impl Key for RsaPublicKey {
fn system(&self) -> &'static CryptoSystem {
&RSA
}
fn read(&self, r: &mut Read) -> Result<Box<Self>> {
Err(::std::io::Error::new(::std::io::ErrorKind::Other, ""))
}
fn write(&self, w: &mut Write) -> Result<()> {
Ok(())
}
}
impl PublicKey for RsaPublicKey {
fn encrypt(&self, data: &[u8]) -> Vec<u8> {
Vec::new()
}
}
pub struct RsaPrivateKey {
}
impl RsaPrivateKey {
pub fn new() -> RsaPrivateKey {
RsaPrivateKey { }
}
}
impl PrivateKey for RsaPrivateKey {
fn sign(&self, data: &[u8]) -> Vec<u8> {
Vec::new()
}
}
impl Key for RsaPrivateKey {
fn system(&self) -> &'static CryptoSystem {
&RSA
}
fn read(&self, r: &mut Read) -> Result<Box<Self>> {
Err(::std::io::Error::new(::std::io::ErrorKind::Other, ""))
}
fn write(&self, w: &mut Write) -> Result<()> {
Ok(())
}
}
......@@ -12,7 +12,7 @@ mod message;
mod session;
mod key_exchange;
pub mod key;
pub mod public_key;
pub mod server;
pub use self::server::{Server, ServerConfig};
extern crate ssh;
extern crate rand;
use rand::Rng;
use std::io::Cursor;
use ssh::key::{self, CryptoSystem, KeyPair};
fn test_export_import(keypair: &Box<KeyPair>) -> Box<KeyPair> {
let mut buffer = Vec::new();
keypair.export(&mut buffer).unwrap();
(keypair.system().import)(&mut Cursor::new(buffer)).unwrap()
}
fn test_crypto_system(system: &CryptoSystem, key_size: Option<u32>) {
let keypair = (system.generate_key_pair)(key_size);
let keypair2 = test_export_import(&keypair);
let mut buffer = [0;4096];
let mut rng = rand::thread_rng();
rng.fill_bytes(&mut buffer);
let signature = keypair.sign(&buffer).unwrap();
let verified = keypair2.verify(&buffer, signature.as_slice()).unwrap();
assert!(verified)
}
#[test]
fn test_ed25519() { test_crypto_system(&key::ED25519, None); }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment