Compare commits

...

5 commits

Author SHA1 Message Date
Janis 76ebacacf2 fixed keygen encryption prompt 2022-05-04 01:15:01 +02:00
noonebtw 27789f94d2 fixed building on windows 2022-01-07 09:30:56 +01:00
NoOneBtw 7e9ad7c793 added osshkeys git dependency 2021-11-17 14:54:04 +01:00
NoOneBtw d3739d3d06 automatically set permissions on unix 2021-11-17 14:42:14 +01:00
NoOneBtw 88d743227a fixed newline when querying user input 2021-11-17 14:19:05 +01:00
5 changed files with 370164 additions and 370228 deletions

View file

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

View file

@ -1,8 +1,9 @@
use std::io::Write;
#[macro_use]
use clap::Parser;
use libduralumin::ed25519::{generate_ed25519_keypair, randomart};
use osshkeys::{error::OsshResult, Key, PublicParts};
use osshkeys::{error::OsshResult, PublicParts};
/// program that generates ed25519 keypairs seeded by a passphrase and an optional ID.
#[derive(Parser)]
@ -16,6 +17,23 @@ 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();
}
}
}
#[allow(dead_code)]
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 +41,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,31 +75,48 @@ 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"
line.to_lowercase() != "n"
};
let fingerprint =
keypair.fingerprint(osshkeys::keys::FingerprintHash::SHA256)?;
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")?;
let randomart =
randomart::RandomArt::from_digest(&fingerprint).render("ED25519 256", "SHA256")?;
println!("RandomArt:\n{}", randomart);
let private_path = opts.file.clone();
let public_path = opts.file.clone() + ".pub";
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)?;
std::fs::write(&private_path, private_key)?;
let public_key = keypair.serialize_publickey()?;
std::fs::write(opts.file + ".pub", public_key)?;
std::fs::write(&public_path, 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(())
}

View file

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

View file

@ -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<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>(
passphrase: S1,
id: Option<S2>,
@ -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::*;

File diff suppressed because it is too large Load diff