feat: add ssh agnet(not yet work)

This commit is contained in:
2022-04-26 00:44:34 +08:00
parent bae59b745e
commit d7ae185264
3 changed files with 73 additions and 0 deletions

50
src/cmd_sshagent.rs Normal file
View File

@@ -0,0 +1,50 @@
use clap::{App, Arg, ArgMatches, SubCommand};
use openpgp_card::{KeyType, OpenPgp};
use openpgp_card::crypto_data::PublicKeyMaterial;
use rust_util::util_clap::{Command, CommandError};
pub struct CommandImpl;
impl Command for CommandImpl {
fn name(&self) -> &str { "ssh-agent" }
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("SSH-Agent subcommand")
// .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin"))
// .arg(Arg::with_name("in").short("i").long("in").takes_value(true).help("File in"))
.arg(Arg::with_name("pgp").long("pgp").help("Use PGP"))
.arg(Arg::with_name("sock-file").long("sock-file").default_value("connect.ssh").help("Sock file, usage SSH_AUTH_SOCK=sock-file ssh ..."))
}
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let use_pgp = sub_arg_matches.is_present("pgp");
let sock_file = sub_arg_matches.value_of("sock-file").unwrap();
information!("Sock file: {}", sock_file);
if use_pgp {
let mut card = crate::pgpcardutil::get_card()?;
let mut pgp = OpenPgp::new(&mut card);
let mut trans = opt_result!(pgp.transaction(), "Open card failed: {}");
let serial = trans.application_related_data()
.map(|d| d.application_id().map(|i| i.serial()))
.unwrap_or_else(|_| Ok(0)).unwrap_or_else(|_| 0);
let serial = hex::encode(serial.to_be_bytes());
let public_key = opt_result!(trans.public_key(KeyType::Signing), "Cannot find signing key: {}");
let rsa_public_key = match public_key {
PublicKeyMaterial::E(_) => return simple_error!("Not supports ec key"),
PublicKeyMaterial::R(rsa_public_key) => rsa_public_key,
_ => return simple_error!("Unknown key type"),
};
let e = rsa_public_key.v();
let n = rsa_public_key.n();
let comment = format!("pgp-card:{}", serial);
let ssh_string = crate::sshutil::generate_ssh_string(e, n, &comment);
information!("{}", ssh_string);
}
information!("card-cli ssh-agent...");
Ok(None)
}
}

View File

@@ -4,6 +4,7 @@ extern crate rust_util;
use clap::{App, AppSettings, ArgMatches};
use rust_util::util_clap::{Command, CommandError};
mod sshutil;
mod fido;
mod digest;
mod rsautil;
@@ -26,6 +27,7 @@ mod cmd_pivdecrypt;
mod cmd_pivgenerate;
mod cmd_chall;
mod cmd_challconfig;
mod cmd_sshagent;
pub struct DefaultCommandImpl;
@@ -64,6 +66,7 @@ fn inner_main() -> CommandError {
Box::new(cmd_pivgenerate::CommandImpl),
Box::new(cmd_u2fregister::CommandImpl),
Box::new(cmd_u2fsign::CommandImpl),
Box::new(cmd_sshagent::CommandImpl),
];
let mut app = App::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION"))

20
src/sshutil.rs Normal file
View File

@@ -0,0 +1,20 @@
pub fn with_sign(mut vec: Vec<u8>) -> Vec<u8> {
if vec.len() > 0 && vec[0] >= 128 {
vec.insert(0, 0x00);
}
vec
}
pub fn generate_ssh_string(e: &[u8], n: &[u8], comment: &str) -> String {
let mut ssh_key = vec![];
let ssh_rsa_bytes = "ssh-rsa".as_bytes();
ssh_key.extend_from_slice(&(ssh_rsa_bytes.len() as u32).to_be_bytes()[..]);
ssh_key.extend_from_slice(ssh_rsa_bytes);
let e = with_sign(e.to_vec());
ssh_key.extend_from_slice(&(e.len() as u32).to_be_bytes()[..]);
ssh_key.extend_from_slice(&e);
let n = with_sign(n.to_vec());
ssh_key.extend_from_slice(&(n.len() as u32).to_be_bytes()[..]);
ssh_key.extend_from_slice(&n);
format!("ssh-rsa {} {}", base64::encode(&ssh_key), comment)
}