programatically generate keys
diff --git a/Cargo.toml b/Cargo.toml
index 5b6406e..2e40d9e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,18 +20,8 @@
 name = "tuf"
 path = "./src/lib.rs"
 
-[[bin]]
-name = "tuf"
-path = "./src/bin/tuf.rs"
-doc = false
-required-features = [ "cli" ]
-
-[features]
-cli = [ "clap" ]
-
 [dependencies]
 chrono = { version = "0.4", features = [ "serde" ] }
-clap = { version = "2", optional = true }
 data-encoding = "2.0.0-rc.1"
 derp = "0.0.4"
 hyper = "0.10"
diff --git a/src/bin/tuf.rs b/src/bin/tuf.rs
deleted file mode 100644
index f5a267d..0000000
--- a/src/bin/tuf.rs
+++ /dev/null
@@ -1,132 +0,0 @@
-extern crate clap;
-extern crate ring;
-
-use clap::{App, AppSettings, SubCommand, Arg, ArgMatches};
-use ring::rand::SystemRandom;
-use ring::signature::Ed25519KeyPair;
-use std::io::{self, Read, Write};
-use std::process::{Command, Stdio};
-
-fn main() {
-    let matches = parser().get_matches();
-
-    match run_main(matches) {
-        Ok(()) => std::process::exit(0),
-        Err(e) => {
-            writeln!(&mut io::stderr(), "{:?}", e).unwrap();
-            ::std::process::exit(1);
-        }
-    }
-}
-
-fn run_main(matches: ArgMatches) -> Result<(), String> {
-    if let Some(matches) = matches.subcommand_matches("keygen") {
-        let typ = matches.value_of("type").unwrap();
-        keygen(typ)
-    } else {
-        unreachable!() // because of AppSettings::SubcommandRequiredElseHelp
-    }
-}
-
-fn parser<'a, 'b>() -> App<'a, 'b> {
-    App::new("tuf")
-        .version(env!("CARGO_PKG_VERSION"))
-        .about("CLI tool for managing TUF repositories")
-        .settings(&[AppSettings::SubcommandRequiredElseHelp])
-        .subcommand(
-            SubCommand::with_name("keygen")
-                .about(
-                    "Generate private keys and print them as PKCS#8v2 DER to STDOUT",
-                )
-                .arg(
-                    Arg::with_name("type")
-                        .takes_value(true)
-                        .default_value("ed25519")
-                        .possible_values(&["ed25519", "rsa-2048", "rsa-4096"])
-                        .help(
-                            "The type of key to generate. \
-                      Note: rsa-XXX requires `openssl` to be on the PATH.",
-                        ),
-                ),
-        )
-}
-
-fn keygen(typ: &str) -> Result<(), String> {
-    let der = match typ {
-        "ed25519" => {
-            Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())
-                .map_err(|e| format!("Failed to generate key: {:?}", e))?
-                .to_vec()
-        }
-        "rsa-2048" => rsa_gen(2048)?,
-        "rsa-4096" => rsa_gen(4096)?,
-        _ => unreachable!(),
-    };
-
-    io::stdout().write(&der).map(|_| ()).map_err(|e| {
-        format!("Failed to write to STDOUT: {:?}", e)
-    })
-}
-
-fn rsa_gen(size: u32) -> Result<Vec<u8>, String> {
-    let gen = Command::new("openssl")
-        .args(
-            &[
-                "genpkey",
-                "-algorithm",
-                "RSA",
-                "-pkeyopt",
-                &format!("rsa_keygen_bits:{}", size),
-                "-pkeyopt",
-                "rsa_keygen_pubexp:65537",
-                "-outform",
-                "der",
-            ],
-        )
-        .stdout(Stdio::piped())
-        .spawn()
-        .map_err(|e| format!("{:?}", e))?;
-
-    let mut pk8 = Command::new("openssl")
-        .args(
-            &[
-                "pkcs8",
-                "-inform",
-                "der",
-                "-topk8",
-                "-nocrypt",
-                "-outform",
-                "der",
-            ],
-        )
-        .stdin(Stdio::piped())
-        .spawn()
-        .map_err(|e| format!("{:?}", e))?;
-
-    match pk8.stdin {
-        Some(ref mut stdin) => {
-            for byte in gen.stdout.ok_or("Failed to get stdout handle")?.bytes() {
-                stdin
-                    .write(&[byte.map_err(|e| format!("Couldn't read byte: {:?}", e))?])
-                    .map_err(|e| format!("Failed to write to stdin: {:?}", e))?;
-            }
-        }
-        None => return Err("Failed to get stdin".into()),
-    };
-
-    let out = pk8.wait_with_output().map_err(|e| {
-        format!("Failed to get stdout: {:?}", e)
-    })?;
-
-    Ok(out.stdout)
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-
-    #[test]
-    fn test_clap() {
-        let _ = parser();
-    }
-}
diff --git a/src/crypto.rs b/src/crypto.rs
index 2ea2b48..dfece0f 100644
--- a/src/crypto.rs
+++ b/src/crypto.rs
@@ -10,11 +10,12 @@
                       RSA_PSS_SHA512};
 use serde::de::{Deserialize, Deserializer, Error as DeserializeError};
 use serde::ser::{Serialize, Serializer, Error as SerializeError};
+use std::cmp::Ordering;
 use std::collections::HashMap;
 use std::fmt::{self, Debug, Display};
 use std::hash;
-use std::io::Read;
-use std::cmp::Ordering;
+use std::io::{Read, Write};
+use std::process::{Command, Stdio};
 use std::str::FromStr;
 use std::sync::Arc;
 use untrusted::Input;
@@ -338,6 +339,20 @@
 }
 
 impl PrivateKey {
+    /// Generate a new `PrivateKey`.
+    ///
+    /// Note: For RSA keys, `openssl` needs to the on the `$PATH`.
+    pub fn new(key_type: KeyType) -> Result<Vec<u8>> {
+        match key_type {
+            KeyType::Ed25519 => {
+                Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())
+                    .map(|bytes| bytes.to_vec())
+                    .map_err(|_| Error::Opaque("Failed to generate Ed25519 key".into()))
+            },
+            KeyType::Rsa => Self::rsa_gen(),
+        }
+    }
+
     /// Create a private key from PKCS#8v2 DER bytes.
     ///
     /// # Generating Keys
@@ -501,6 +516,48 @@
         })
     }
 
+    fn rsa_gen() -> Result<Vec<u8>> {
+        let gen = Command::new("openssl")
+            .args(
+                &[
+                    "genpkey",
+                    "-algorithm",
+                    "RSA",
+                    "-pkeyopt",
+                    "rsa_keygen_bits:4096",
+                    "-pkeyopt",
+                    "rsa_keygen_pubexp:65537",
+                    "-outform",
+                    "der",
+                ],
+            )
+            .output()?;
+
+        let mut pk8 = Command::new("openssl")
+            .args(
+                &[
+                    "pkcs8",
+                    "-inform",
+                    "der",
+                    "-topk8",
+                    "-nocrypt",
+                    "-outform",
+                    "der",
+                ],
+            )
+            .stdin(Stdio::piped())
+            .stdout(Stdio::piped())
+            .spawn()?;
+
+        match pk8.stdin {
+            Some(ref mut stdin) => stdin.write_all(&gen.stdout)?,
+            None => return Err(Error::Opaque("openssl has no stdin".into())),
+        };
+
+        Ok(pk8.wait_with_output()?.stdout)
+    }
+
+
     /// Return the public component of the key.
     pub fn public(&self) -> &PublicKey {
         &self.public
@@ -512,7 +569,6 @@
     }
 }
 
-
 /// A structure containing information about a public key.
 #[derive(Clone, Debug)]
 pub struct PublicKey {
@@ -953,4 +1009,17 @@
         let decoded: Signature = json::from_value(encoded).unwrap();
         assert_eq!(decoded, sig);
     }
+
+    #[test]
+    #[cfg(not(windows))]
+    fn new_rsa_key() {
+        let bytes = PrivateKey::new(KeyType::Rsa).unwrap();
+        let _ = PrivateKey::from_pkcs8(&bytes, SignatureScheme::RsaSsaPssSha256).unwrap();
+    }
+
+    #[test]
+    fn new_ed25519_key() {
+        let bytes = PrivateKey::new(KeyType::Ed25519).unwrap();
+        let _ = PrivateKey::from_pkcs8(&bytes, SignatureScheme::Ed25519).unwrap();
+    }
 }