diff --git a/src/main.rs b/src/main.rs index 9bdf3fe..361635f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod pgpcardlist; mod pgpcardsign; mod pgpcarddecrypt; mod piv; +mod pivsign; mod chall; mod challconfig; @@ -44,6 +45,7 @@ fn inner_main() -> CommandError { Box::new(pgpcardsign::CommandImpl), Box::new(pgpcarddecrypt::CommandImpl), Box::new(piv::CommandImpl), + Box::new(pivsign::CommandImpl), Box::new(chall::CommandImpl), Box::new(challconfig::CommandImpl), ]; diff --git a/src/pivsign.rs b/src/pivsign.rs new file mode 100644 index 0000000..1b88d63 --- /dev/null +++ b/src/pivsign.rs @@ -0,0 +1,39 @@ +use clap::{ArgMatches, SubCommand, App, Arg}; +use yubikey::YubiKey; +use yubikey::piv::{SlotId, AlgorithmId}; +use rust_util::util_clap::{Command, CommandError}; + +pub struct CommandImpl; + +impl Command for CommandImpl { + fn name(&self) -> &str { "piv-sign" } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()).about("PIV Sign subcommand") + .arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password")) + // .arg(Arg::with_name("json").long("json").help("JSON output")) + } + + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + warning!("This feature is not complete"); + let pass = sub_arg_matches.value_of("pass"); + let pass = match pass { + Some(p) => p, + None => return simple_error!("Pass must be assigned"), + }; + + let mut yk = YubiKey::open()?; + yk.verify_pin(pass.as_bytes())?; + let raw_in = [1_u8; 256]; + let sign = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature); + match sign { + Ok(sign) => { + let sign_bytes = sign.as_slice(); + success!("Signature HEX: {}", hex::encode(sign_bytes)); + success!("Signature base64: {}", base64::encode(sign_bytes)); + } + Err(e) => return simple_error!("Sign data failed: {}", e), + } + Ok(None) + } +}