108 lines
2.6 KiB
Rust
108 lines
2.6 KiB
Rust
use std::io::Write;
|
|
|
|
use clap::Parser;
|
|
use libduralumin::ed25519::{generate_ed25519_keypair, randomart};
|
|
use osshkeys::{error::OsshResult, Key, PublicParts};
|
|
|
|
/// program that generates ed25519 keypairs seeded by a passphrase and an optional ID.
|
|
#[derive(Parser)]
|
|
#[clap(
|
|
name = "duralumin",
|
|
version = "0.1.0",
|
|
author = "No One <noonebtw@nirgendwo.xyz>"
|
|
)]
|
|
struct Opts {
|
|
#[clap(short, long, default_value = "id_ed25519")]
|
|
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:");
|
|
|
|
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
|
|
} else {
|
|
Some(id)
|
|
}
|
|
};
|
|
|
|
let keypair = generate_ed25519_keypair(&passphrase, id.as_ref())?;
|
|
|
|
print!("Encrypt keypair with passphrase? [Y/n]: ");
|
|
std::io::stdout().flush()?;
|
|
|
|
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)?;
|
|
|
|
println!(
|
|
"Your key fingerprint is: Sha256:{}",
|
|
base64::encode(&fingerprint)
|
|
);
|
|
|
|
let randomart = randomart::RandomArt::from_digest(&fingerprint)
|
|
.render("ED25519 256", "SHA256")?;
|
|
|
|
println!("RandomArt:\n{}", randomart);
|
|
|
|
let private_key = keypair.serialize_openssh(
|
|
encrypt.then(|| passphrase.as_str()),
|
|
osshkeys::cipher::Cipher::Aes256_Ctr,
|
|
)?;
|
|
std::fs::write(&opts.file, private_key)?;
|
|
|
|
let public_key = keypair.serialize_publickey()?;
|
|
std::fs::write(opts.file + ".pub", public_key)?;
|
|
|
|
Ok(())
|
|
}
|