diff --git a/src/bin/duralumin-keygen.rs b/src/bin/duralumin-keygen.rs index 96af9a0..cdfb86a 100644 --- a/src/bin/duralumin-keygen.rs +++ b/src/bin/duralumin-keygen.rs @@ -16,6 +16,21 @@ struct Opts { file: String, } +fn fix_newline_ref(line: &mut String) { + if line.ends_with('\n') { + line.pop(); + + if line.ends_with('\r') { + line.pop(); + } + } +} +fn fix_newline(mut line: String) -> String { + fix_newline_ref(&mut line); + + line +} + fn main() -> OsshResult<()> { let opts = Opts::parse(); println!("Generating ed25519 keypair:"); @@ -23,12 +38,24 @@ fn main() -> OsshResult<()> { print!("Enter a passphrase: "); std::io::stdout().flush()?; let passphrase = rpassword::read_password()?; + print!("Re-enter the same passphrase: "); + std::io::stdout().flush()?; + let passphrase2 = rpassword::read_password()?; + + if passphrase != passphrase2 { + println!("passphrases do not match."); + Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "passphrase did not match.", + ))?; + } print!("Enter an optional ID []: "); std::io::stdout().flush()?; let id = { let mut id = String::new(); std::io::stdin().read_line(&mut id)?; + fix_newline_ref(&mut id); if id.is_empty() { None @@ -45,10 +72,15 @@ fn main() -> OsshResult<()> { let encrypt = { let mut line = String::new(); std::io::stdin().read_line(&mut line)?; + fix_newline_ref(&mut line); line.to_lowercase() == "y" }; + if encrypt { + println!("Using passphrase to encrypt key.."); + } + let fingerprint = keypair.fingerprint(osshkeys::keys::FingerprintHash::SHA256)?; @@ -63,7 +95,7 @@ fn main() -> OsshResult<()> { println!("RandomArt:\n{}", randomart); let private_key = keypair.serialize_openssh( - Some(&passphrase), + encrypt.then(|| passphrase.as_str()), osshkeys::cipher::Cipher::Aes256_Ctr, )?; std::fs::write(&opts.file, private_key)?; diff --git a/src/ed25519.rs b/src/ed25519.rs index 0c17f3e..56a312f 100644 --- a/src/ed25519.rs +++ b/src/ed25519.rs @@ -1,113 +1,6 @@ use osshkeys::{error::OsshResult, keys::ed25519::Ed25519KeyPair, KeyPair}; use sha2::{Digest, Sha256}; -#[cfg(all(feature = "base64", feature = "bytes"))] -mod asdf { - use std::io::{Cursor, Read}; - - use bytes::Buf; - - pub struct Ed25519PrivateKey {} - - const OPENSSH_BEGIN: &str = "-----BEGIN OPENSSH PRIVATE KEY-----"; - const OPENSSH_END: &str = "-----END OPENSSH PRIVATE KEY-----"; - const OPENSSH_MAGIC: &str = "openssh-key-v1\0"; - - impl Ed25519PrivateKey { - pub fn parse(text: S) -> Option<()> - where - S: AsRef, - { - let mut lines = text.as_ref().lines(); - - let data = (lines.next() == Some(OPENSSH_BEGIN)) - .then(|| { - let base64_content = lines - .take_while(|&line| line != OPENSSH_END) - .fold(String::new(), |mut acc, line| { - acc.push_str(line); - acc - }); - - base64::decode(&base64_content).ok() - }) - .flatten() - .map(|data| Cursor::new(data)) - .and_then(|mut data| { - let mut magic = vec![0u8; OPENSSH_MAGIC.len()]; - data.read_exact(&mut magic).unwrap(); - - // cypher name - let cypher_len = data.get_u32(); - let mut cypher_name = vec![0u8; cypher_len as usize]; - data.read_exact(&mut cypher_name).unwrap(); - - // kdf name - let kdf_name_len = data.get_u32(); - let mut kdf_name = vec![0u8; kdf_name_len as usize]; - data.read_exact(&mut kdf_name).unwrap(); - - // kdf - let kdf_len = data.get_u32(); - let kdf = (kdf_len > 0).then(|| { - let mut kdf = vec![0u8; kdf_len as usize]; - data.read_exact(&mut kdf).unwrap(); - kdf - }); - - // key_count should always be `1` - let key_count = data.get_u32(); - assert_eq!(key_count, 1); - - // ssh public key - - let pubkey_len = data.get_u32() as usize; - - let keytype_len = data.get_u32() as usize; - let mut keytype = vec![0u8; keytype_len]; - data.read_exact(&mut keytype).unwrap(); - - let pub1_len = data.get_u32() as usize; - let mut pub1 = vec![0u8; pub1_len]; - data.read_exact(&mut pub1).unwrap(); - - let pub2_len = data.get_u32() as usize; - let mut pub2 = vec![0u8; pub2_len]; - data.read_exact(&mut pub2).unwrap(); - - println!("magic: {}", String::from_utf8_lossy(&magic)); - println!( - "cypher: {}", - String::from_utf8_lossy(&cypher_name) - ); - println!("kdf: {}", String::from_utf8_lossy(&kdf_name)); - - println!("keytype: {}", String::from_utf8_lossy(&keytype)); - println!("pub1[{}]: {:?}", pub1_len, &pub1); - println!("pub2[{}]: {:?}", pub2_len, &pub2); - - Some(()) - }); - - Some(()) - } - } - - mod tests { - use super::Ed25519PrivateKey; - - #[test] - fn test_ed25519() { - Ed25519PrivateKey::parse(include_str!("../ed25519")); - } - - #[test] - fn test_ed25519_passphrased() { - Ed25519PrivateKey::parse(include_str!("../ed25519-passphrased")); - } - } -} - pub fn generate_ed25519_keypair( passphrase: S1, id: Option, @@ -132,8 +25,6 @@ where pub mod randomart { use std::fmt::Write; - use osshkeys::error::OsshResult; - const WIDTH: usize = 17; const HEIGHT: usize = 9; const TILES: &[char] = &[ @@ -229,6 +120,7 @@ pub mod randomart { } } + #[cfg(test)] mod tests { use super::*;