Compare commits

..

No commits in common. "76ebacacf26d04f544d9ef177598e517bf4210c9" and "6259840c43659c2322ff1da7694d5a558111c5c0" have entirely different histories.

5 changed files with 370228 additions and 370164 deletions

View file

@ -24,9 +24,9 @@ required-features = ["ed25519", "clap", "rpassword", "base64"]
[dependencies] [dependencies]
rand = "0.8.4" rand = "0.8.4"
clap = {version = "3.0.0-beta.5", optional = true, features = ["derive"]} clap = {version = "3.0.0-beta.5", optional = true}
base64 = {version = "0.13.0", optional = true} base64 = {version = "0.13.0", optional = true}
bytes = {version = "1.1.0", optional = true} bytes = {version = "1.1.0", optional = true}
osshkeys = {git = "https://github.com/noonebtw/rust-osshkeys.git", branch = "master", optional = true} osshkeys = {path = "../rust-osshkeys", optional = true}
sha2 = {version = "0.9.8", optional = true} sha2 = {version = "0.9.8", optional = true}
rpassword = {version = "5.0.1", optional = true} rpassword = {version = "5.0.1", optional = true}

View file

@ -1,9 +1,8 @@
use std::io::Write; use std::io::Write;
#[macro_use]
use clap::Parser; use clap::Parser;
use libduralumin::ed25519::{generate_ed25519_keypair, randomart}; use libduralumin::ed25519::{generate_ed25519_keypair, randomart};
use osshkeys::{error::OsshResult, PublicParts}; use osshkeys::{error::OsshResult, Key, PublicParts};
/// program that generates ed25519 keypairs seeded by a passphrase and an optional ID. /// program that generates ed25519 keypairs seeded by a passphrase and an optional ID.
#[derive(Parser)] #[derive(Parser)]
@ -17,23 +16,6 @@ struct Opts {
file: String, file: String,
} }
fn fix_newline_ref(line: &mut String) {
if line.ends_with('\n') {
line.pop();
if line.ends_with('\r') {
line.pop();
}
}
}
#[allow(dead_code)]
fn fix_newline(mut line: String) -> String {
fix_newline_ref(&mut line);
line
}
fn main() -> OsshResult<()> { fn main() -> OsshResult<()> {
let opts = Opts::parse(); let opts = Opts::parse();
println!("Generating ed25519 keypair:"); println!("Generating ed25519 keypair:");
@ -41,24 +23,12 @@ fn main() -> OsshResult<()> {
print!("Enter a passphrase: "); print!("Enter a passphrase: ");
std::io::stdout().flush()?; std::io::stdout().flush()?;
let passphrase = rpassword::read_password()?; 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 []: "); print!("Enter an optional ID []: ");
std::io::stdout().flush()?; std::io::stdout().flush()?;
let id = { let id = {
let mut id = String::new(); let mut id = String::new();
std::io::stdin().read_line(&mut id)?; std::io::stdin().read_line(&mut id)?;
fix_newline_ref(&mut id);
if id.is_empty() { if id.is_empty() {
None None
@ -75,48 +45,31 @@ fn main() -> OsshResult<()> {
let encrypt = { let encrypt = {
let mut line = String::new(); let mut line = String::new();
std::io::stdin().read_line(&mut line)?; std::io::stdin().read_line(&mut line)?;
fix_newline_ref(&mut line);
line.to_lowercase() != "n" line.to_lowercase() == "y"
}; };
if encrypt { let fingerprint =
println!("Using passphrase to encrypt key.."); keypair.fingerprint(osshkeys::keys::FingerprintHash::SHA256)?;
}
let fingerprint = keypair.fingerprint(osshkeys::keys::FingerprintHash::SHA256)?;
println!( println!(
"Your key fingerprint is: Sha256:{}", "Your key fingerprint is: Sha256:{}",
base64::encode(&fingerprint) base64::encode(&fingerprint)
); );
let randomart = let randomart = randomart::RandomArt::from_digest(&fingerprint)
randomart::RandomArt::from_digest(&fingerprint).render("ED25519 256", "SHA256")?; .render("ED25519 256", "SHA256")?;
println!("RandomArt:\n{}", randomart); println!("RandomArt:\n{}", randomart);
let private_path = opts.file.clone();
let public_path = opts.file.clone() + ".pub";
let private_key = keypair.serialize_openssh( let private_key = keypair.serialize_openssh(
encrypt.then(|| passphrase.as_str()), Some(&passphrase),
osshkeys::cipher::Cipher::Aes256_Ctr, osshkeys::cipher::Cipher::Aes256_Ctr,
)?; )?;
std::fs::write(&private_path, private_key)?; std::fs::write(&opts.file, private_key)?;
let public_key = keypair.serialize_publickey()?; let public_key = keypair.serialize_publickey()?;
std::fs::write(&public_path, public_key)?; std::fs::write(opts.file + ".pub", public_key)?;
#[cfg(target_family = "unix")]
use std::fs::Permissions;
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
#[cfg(target_family = "unix")]
std::fs::set_permissions(private_path, Permissions::from_mode(0o0600))?;
#[cfg(target_family = "unix")]
std::fs::set_permissions(public_path, Permissions::from_mode(0o0600))?;
Ok(()) Ok(())
} }

View file

@ -1,4 +1,3 @@
#[macro_use]
use clap::Parser; use clap::Parser;
use libduralumin::passphrase_gen::{PassPhraseGenerator, Words}; use libduralumin::passphrase_gen::{PassPhraseGenerator, Words};
@ -70,8 +69,12 @@ fn main() {
.with_length(opts.words_per_passphrase()); .with_length(opts.words_per_passphrase());
let words = match opts.backend() { let words = match opts.backend() {
Some(Backend::UseAPassPhrase) => Words::from_str(include_str!("../../useapassphrase.txt")), Some(Backend::UseAPassPhrase) => {
Some(Backend::EnglishWords) => Words::from_str(include_str!("../../words_alpha.txt")), Words::from_str(include_str!("../../useapassphrase.txt"))
}
Some(Backend::EnglishWords) => {
Words::from_str(include_str!("../../words_alpha.txt"))
}
None => { None => {
panic!("invalid backend.") panic!("invalid backend.")
} }

View file

@ -1,6 +1,113 @@
use osshkeys::{error::OsshResult, keys::ed25519::Ed25519KeyPair, KeyPair}; use osshkeys::{error::OsshResult, keys::ed25519::Ed25519KeyPair, KeyPair};
use sha2::{Digest, Sha256}; 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<S>(text: S) -> Option<()>
where
S: AsRef<str>,
{
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<S1, S2>( pub fn generate_ed25519_keypair<S1, S2>(
passphrase: S1, passphrase: S1,
id: Option<S2>, id: Option<S2>,
@ -25,6 +132,8 @@ where
pub mod randomart { pub mod randomart {
use std::fmt::Write; use std::fmt::Write;
use osshkeys::error::OsshResult;
const WIDTH: usize = 17; const WIDTH: usize = 17;
const HEIGHT: usize = 9; const HEIGHT: usize = 9;
const TILES: &[char] = &[ const TILES: &[char] = &[
@ -120,7 +229,6 @@ pub mod randomart {
} }
} }
#[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;