feat: updates
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
use crate::hmacutil;
|
||||
use crate::{cmdutil, hmacutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -17,12 +16,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("sha256").short("2").long("sha256").help("Output SHA256"))
|
||||
.arg(Arg::with_name("sha384").short("3").long("sha384").help("Output SHA384"))
|
||||
.arg(Arg::with_name("sha512").short("5").long("sha512").help("Output SHA512"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let challenge_bytes = hmacutil::get_challenge_bytes(sub_arg_matches)?;
|
||||
let hmac_result = hmacutil::compute_yubikey_hmac(&challenge_bytes)?;
|
||||
|
||||
@@ -2,10 +2,9 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
use crate::ecdsautil::EcdsaAlgorithm;
|
||||
use crate::{argsutil, ecdsautil};
|
||||
use crate::{argsutil, cmdutil, ecdsautil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -19,12 +18,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("file").short("f").long("file").takes_value(true).help("Input file"))
|
||||
.arg(Arg::with_name("input").short("i").long("input").takes_value(true).help("Input"))
|
||||
.arg(Arg::with_name("hash-hex").short("x").long("hash-hex").takes_value(true).help("Hash"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let hash_bytes = argsutil::get_sha256_digest_or_hash(sub_arg_matches)?;
|
||||
let public_key = if let Some(public_key_hex) = sub_arg_matches.value_of("public-key-hex") {
|
||||
|
||||
@@ -10,7 +10,7 @@ use x509_parser::nom::AsBytes;
|
||||
use yubikey::{Key, YubiKey};
|
||||
use yubikey::piv::{sign_data, SlotId};
|
||||
|
||||
use crate::{argsutil, pinutil, pivutil};
|
||||
use crate::{argsutil, cmdutil, pinutil, pivutil};
|
||||
use crate::digest::sha256_bytes;
|
||||
use crate::signfile::{CERTIFICATES_SEARCH_URL, HASH_ALGORITHM_SHA256, SIGNATURE_ALGORITHM_SHA256_WITH_ECDSA, SignFileRequest, SIMPLE_SIG_SCHEMA, SimpleSignFile, SimpleSignFileSignature};
|
||||
use crate::util::base64_encode;
|
||||
@@ -40,10 +40,9 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV sign(with SHA256) subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot")
|
||||
.takes_value(true).required(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("file").short("f").long("file").takes_value(true).required(true).help("Input file"))
|
||||
.arg(Arg::with_name("filename").short("n").long("filename").takes_value(true).help("Filename"))
|
||||
.arg(Arg::with_name("sign-file").short("S").long("sign-file").takes_value(false).help("Sign file"))
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::hmacutil;
|
||||
use crate::{cmdutil, hmacutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -21,14 +20,11 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("Ciphertext"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let ciphertext = sub_arg_matches.value_of("ciphertext").unwrap();
|
||||
let plaintext = hmacutil::hmac_decrypt_to_string(ciphertext)?;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::hmacutil;
|
||||
use crate::{cmdutil, hmacutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -21,14 +20,11 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("Plaintext"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let plaintext = sub_arg_matches.value_of("plaintext").unwrap();
|
||||
let hmac_encrypt_ciphertext = hmacutil::hmac_encrypt_from_string(plaintext)?;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
|
||||
use crate::hmacutil;
|
||||
use crate::{cmdutil, hmacutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -19,12 +19,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("sha256").short("2").long("sha256").help("Output SHA256"))
|
||||
.arg(Arg::with_name("sha384").short("3").long("sha384").help("Output SHA256"))
|
||||
.arg(Arg::with_name("sha512").short("5").long("sha512").help("Output SHA256"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let variable = sub_arg_matches.is_present("variable");
|
||||
let secret_bytes = get_secret_bytes(sub_arg_matches)?;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::keychain::{KeychainKey, KeychainKeyValue};
|
||||
use crate::{ecdsautil, hmacutil};
|
||||
use crate::{cmdutil, ecdsautil, hmacutil};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -27,16 +26,13 @@ impl Command for CommandImpl {
|
||||
.long("with-hmac-encrypt")
|
||||
.help("With HMAC encrypt"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("keychain-name")
|
||||
.long("keychain-name")
|
||||
.takes_value(true)
|
||||
.help("Key chain name"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_keychain_name_arg())
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let with_hmac_encrypt = sub_arg_matches.is_present("with-hmac-encrypt");
|
||||
let key_type = sub_arg_matches.value_of("type").unwrap().to_lowercase();
|
||||
let keychain_name = sub_arg_matches.value_of("keychain-name");
|
||||
@@ -48,11 +44,6 @@ impl Command for CommandImpl {
|
||||
}
|
||||
}
|
||||
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
|
||||
let (pkcs8_base64, secret_key_pem, public_key_pem, jwk_ec_key) = match key_type.as_str() {
|
||||
"p256" => ecdsautil::generate_p256_keypair()?,
|
||||
"p384" => ecdsautil::generate_p384_keypair()?,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::cmdutil;
|
||||
use crate::keychain::{KeychainKey, KeychainKeyValue};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use clap::{App, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
@@ -13,12 +14,7 @@ impl Command for CommandImpl {
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name())
|
||||
.about("Export software keypair from keychain")
|
||||
.arg(
|
||||
Arg::with_name("keychain-name")
|
||||
.long("keychain-name")
|
||||
.takes_value(true)
|
||||
.help("Key chain name"),
|
||||
)
|
||||
.arg(cmdutil::build_keychain_name_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::keychain::KeychainKey;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use crate::cmdutil;
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -12,12 +13,7 @@ impl Command for CommandImpl {
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name())
|
||||
.about("Import software keypair to keychain")
|
||||
.arg(
|
||||
Arg::with_name("keychain-name")
|
||||
.long("keychain-name")
|
||||
.takes_value(true)
|
||||
.help("Key chain name"),
|
||||
)
|
||||
.arg(cmdutil::build_keychain_name_arg())
|
||||
.arg(
|
||||
Arg::with_name("import-key-value")
|
||||
.long("import-key-value")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use clap::{App, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use yubikey::YubiKey;
|
||||
use crate::cmdutil;
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -12,12 +12,11 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("YubiKey list")
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ use std::collections::BTreeMap;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
use crate::cmdutil;
|
||||
use crate::ecdsautil::parse_ecdsa_r_and_s;
|
||||
use crate::util::try_decode;
|
||||
|
||||
@@ -25,14 +24,11 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("ECDSA signature"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("in").short("i").long("in").takes_value(true).help("File input, *.pgp or *.asc"))
|
||||
.arg(Arg::with_name("detail").long("detail").help("Detail output"))
|
||||
.arg(Arg::with_name("verbose").long("verbose").help("Verbose output"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
// .arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use bech32::{ToBase32, Variant};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use clap::{App, ArgMatches, SubCommand};
|
||||
use openpgp_card::algorithm::{Algo, Curve};
|
||||
use openpgp_card::crypto_data::{EccType, PublicKeyMaterial};
|
||||
use openpgp_card::{KeyType, OpenPgp};
|
||||
use openpgp_card_pcsc::PcscBackend;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
use crate::cmdutil;
|
||||
|
||||
const AGE_PUBLIC_KEY_PREFIX: &str = "age";
|
||||
|
||||
@@ -17,12 +17,11 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("OpenPGP Card encryption key to age address")
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let cards = opt_result!(PcscBackend::cards(None), "Failed to list OpenPGP cards: {}");
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use openpgp_card::crypto_data::Cryptogram;
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
|
||||
use crate::{pgpcardutil, pinutil};
|
||||
use crate::{cmdutil, pgpcardutil, pinutil};
|
||||
use crate::util::{base64_encode, read_stdin, try_decode};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -36,12 +36,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("ciphertext").short("c").long("ciphertext").takes_value(true).help("Cipher text (HEX or Base64)"))
|
||||
.arg(Arg::with_name("stdin").long("stdin").help("Standard input (Ciphertext)"))
|
||||
.arg(Arg::with_name("algo").long("algo").takes_value(true).help("Algo: RSA, X25519/ECDH"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let pin_opt = sub_arg_matches.value_of("pass").or_else(|| sub_arg_matches.value_of("pin"));
|
||||
let pin_opt = pinutil::get_pin(pin_opt);
|
||||
|
||||
@@ -4,8 +4,7 @@ use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use openpgp_card::{KeyType, OpenPgp};
|
||||
use openpgp_card_pcsc::PcscBackend;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
use crate::cmdutil;
|
||||
use crate::pkiutil::openpgp_card_public_key_pem as public_key_pem;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -16,13 +15,13 @@ impl Command for CommandImpl {
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("OpenPGP Card list subcommand")
|
||||
.arg(Arg::with_name("detail").long("detail").help("Detail output"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let detail_output = sub_arg_matches.is_present("detail");
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
|
||||
let mut jsons = vec![];
|
||||
let cards = opt_result!(PcscBackend::cards(None), "Failed to list OpenPGP cards: {}");
|
||||
|
||||
@@ -5,11 +5,11 @@ use std::io::{ErrorKind, Read};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use digest::Digest;
|
||||
use openpgp_card::crypto_data::Hash;
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use sha2::{Sha256, Sha384, Sha512};
|
||||
|
||||
use crate::{pgpcardutil, pinutil};
|
||||
use crate::{cmdutil, pgpcardutil, pinutil};
|
||||
use crate::util::base64_encode;
|
||||
|
||||
const BUFF_SIZE: usize = 512 * 1024;
|
||||
@@ -49,12 +49,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("use-sha384").long("use-sha384").help("Use SHA384 for file in"))
|
||||
.arg(Arg::with_name("use-sha512").long("use-sha512").help("Use SHA512 for file in"))
|
||||
.arg(Arg::with_name("algo").long("algo").takes_value(true).help("Algorithm, rsa, ecdsa, eddsa"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let pin_opt = sub_arg_matches.value_of("pass").or_else(|| sub_arg_matches.value_of("pin"));
|
||||
let pin_opt = pinutil::get_pin(pin_opt);
|
||||
|
||||
@@ -2,11 +2,10 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use yubikey::piv::AlgorithmId;
|
||||
use yubikey::YubiKey;
|
||||
|
||||
use crate::{pinutil, pivutil};
|
||||
use crate::{cmdutil, pinutil, pivutil};
|
||||
use crate::util::{read_stdin, try_decode};
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -16,17 +15,16 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV decrypt(RSA) subcommand")
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("ciphertext").long("ciphertext").short("c").takes_value(true).help("Encrypted data (HEX or Base64)"))
|
||||
.arg(Arg::with_name("stdin").long("stdin").help("Standard input (Ciphertext)"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let slot = opt_value_result!(sub_arg_matches.value_of("slot"), "--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e");
|
||||
|
||||
|
||||
@@ -4,11 +4,10 @@ use std::fs;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rand::rngs::OsRng;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use yubikey::{PinPolicy, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, decrypt_data, metadata};
|
||||
|
||||
use crate::{ecdhutil, pinutil, pivutil};
|
||||
use crate::{cmdutil, ecdhutil, pinutil, pivutil};
|
||||
use crate::pivutil::get_algorithm_id;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -18,9 +17,9 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV ECDH subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ..."))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(Arg::with_name("public-256").long("public-256").help("Public key (P-256)"))
|
||||
.arg(Arg::with_name("public-384").long("public-384").help("Public key (P-384)"))
|
||||
.arg(Arg::with_name("private").long("private").help("Private key(PIV)"))
|
||||
@@ -28,12 +27,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("public-key").long("public-key").takes_value(true).help("Public key"))
|
||||
.arg(Arg::with_name("public-key-file").long("public-key-file").takes_value(true).help("Public key"))
|
||||
.arg(Arg::with_name("public-key-point-hex").long("public-key-point-hex").takes_value(true).help("Public key point hex"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let public256 = sub_arg_matches.is_present("public-256");
|
||||
let public384 = sub_arg_matches.is_present("public-384");
|
||||
|
||||
@@ -2,13 +2,12 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use x509_parser::nom::AsBytes;
|
||||
use yubikey::piv::{metadata, sign_data, AlgorithmId, ManagementAlgorithmId};
|
||||
use yubikey::YubiKey;
|
||||
|
||||
use crate::util::base64_encode;
|
||||
use crate::{argsutil, pivutil};
|
||||
use crate::{argsutil, cmdutil, pivutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -17,19 +16,18 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV EC sign(with SHA256) subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("algorithm").short("a").long("algorithm").takes_value(true).help("Algorithm, p256 or p384"))
|
||||
.arg(Arg::with_name("file").short("f").long("file").takes_value(true).help("Input file"))
|
||||
.arg(Arg::with_name("input").short("i").long("input").takes_value(true).help("Input"))
|
||||
.arg(Arg::with_name("hash-hex").short("x").long("hash-hex").takes_value(true).help("Hash"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use yubikey::{PinPolicy, piv, TouchPolicy, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, SlotId};
|
||||
|
||||
use crate::pinutil;
|
||||
use crate::{cmdutil, pinutil};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -13,15 +12,12 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV generate subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("force").long("force").help("Force generate"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
// .arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
|
||||
warning!("This feature is not works");
|
||||
let pin_opt = sub_arg_matches.value_of("pin");
|
||||
let pin_opt = pinutil::get_pin(pin_opt);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use clap::{App, ArgMatches, SubCommand};
|
||||
use p256::pkcs8::der::Encode;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
@@ -9,7 +9,7 @@ use x509_parser::parse_x509_certificate;
|
||||
use yubikey::{Key, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, metadata};
|
||||
|
||||
use crate::pivutil;
|
||||
use crate::{cmdutil, pivutil};
|
||||
use crate::pivutil::{get_algorithm_id_by_certificate, slot_equals, ToStr};
|
||||
use crate::pkiutil::bytes_to_pem;
|
||||
use crate::sshutil::SshVecWriter;
|
||||
@@ -22,13 +22,12 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV meta subcommand")
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use yubikey::{piv, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, SlotId};
|
||||
|
||||
use crate::{pinutil, pivutil, rsautil};
|
||||
use crate::{cmdutil, pinutil, pivutil, rsautil};
|
||||
use crate::util::base64_encode;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -16,16 +15,15 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV RSA sign(with SHA256) subcommand")
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let pin_opt = pinutil::read_pin(sub_arg_matches);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use serde::Serialize;
|
||||
use serde_json::{Map, Value};
|
||||
use spki::der::Encode;
|
||||
@@ -9,7 +9,7 @@ use tabled::{Table, Tabled};
|
||||
use x509_parser::parse_x509_certificate;
|
||||
use yubikey::piv::{metadata, SlotId};
|
||||
use yubikey::{Certificate, YubiKey};
|
||||
|
||||
use crate::cmdutil;
|
||||
use crate::pivutil::{get_algorithm_id_by_certificate, ToStr, ORDERED_SLOTS};
|
||||
|
||||
const NA: &str = "N/A";
|
||||
@@ -35,17 +35,17 @@ impl Command for CommandImpl {
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV subcommand")
|
||||
.arg(Arg::with_name("table").long("table").help("Show table"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(Arg::with_name("all").long("all").help("Show all"))
|
||||
.arg(Arg::with_name("ordered").long("ordered").help("Show ordered"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let show_table = sub_arg_matches.is_present("table");
|
||||
let show_all = sub_arg_matches.is_present("all");
|
||||
let show_ordered = sub_arg_matches.is_present("ordered");
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
|
||||
let mut output = Map::new();
|
||||
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
||||
|
||||
@@ -2,12 +2,12 @@ use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use openssl::rsa::{Padding, Rsa};
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use yubikey::{Key, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, SlotId};
|
||||
|
||||
use crate::{argsutil, ecdsautil, pivutil};
|
||||
use crate::{argsutil, cmdutil, ecdsautil, pivutil};
|
||||
use crate::ecdsautil::EcdsaAlgorithm;
|
||||
use crate::pivutil::slot_equals;
|
||||
|
||||
@@ -18,17 +18,16 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("PIV verify subcommand")
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(Arg::with_name("signature-hex").short("t").long("signature-hex").takes_value(true).help("Signature"))
|
||||
.arg(Arg::with_name("file").short("f").long("file").takes_value(true).help("Input file"))
|
||||
.arg(Arg::with_name("input").short("i").long("input").takes_value(true).help("Input"))
|
||||
.arg(Arg::with_name("hash-hex").short("x").long("hash-hex").takes_value(true).help("Hash"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let hash_bytes = argsutil::get_sha256_digest_or_hash(sub_arg_matches)?;
|
||||
let signature = if let Some(signature_hex) = sub_arg_matches.value_of("signature-hex") {
|
||||
|
||||
@@ -8,7 +8,7 @@ use openssl::rsa::Rsa;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use rust_util::util_msg::MessageType;
|
||||
|
||||
use crate::cmdutil;
|
||||
use crate::util::{read_stdin, try_decode};
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -25,12 +25,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("stdin").long("stdin").help("Standard input (Ciphertext)"))
|
||||
.arg(Arg::with_name("padding").long("padding").takes_value(true)
|
||||
.possible_values(&["pkcs1", "oaep", "pss", "none"]).help("Padding"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let pri_key_in = opt_value_result!(sub_arg_matches.value_of("pri-key-in"), "Require private key in");
|
||||
let pri_key_bytes = opt_result!(std::fs::read(pri_key_in), "Read file: {}, failed: {}", pri_key_in);
|
||||
|
||||
@@ -6,8 +6,7 @@ use openssl::encrypt::Encrypter;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::rsa::Rsa;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
use crate::cmdutil;
|
||||
use crate::digest::sha256_bytes;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -23,12 +22,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("data-hex").long("data-hex").takes_value(true).help("Data in HEX"))
|
||||
.arg(Arg::with_name("padding").long("padding").takes_value(true)
|
||||
.possible_values(&["pkcs1", "oaep", "pss", "none"]).help("Padding"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let pub_key_in = opt_value_result!(sub_arg_matches.value_of("pub-key-in"), "Require public key in");
|
||||
let pub_key_bytes = opt_result!(fs::read(pub_key_in), "Read file: {}, failed: {}", pub_key_in);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::seutil;
|
||||
use std::collections::BTreeMap;
|
||||
use crate::{cmdutil, seutil};
|
||||
use clap::{App, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
|
||||
@@ -11,15 +12,25 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Secure Enclave subcommand")
|
||||
// .arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
if seutil::is_support_se() {
|
||||
success!("Secure Enclave is supported.")
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::new();
|
||||
|
||||
if json_output {
|
||||
json.insert("se_supported", seutil::is_support_se());
|
||||
} else {
|
||||
failure!("Secure Enclave is NOT supported.")
|
||||
if seutil::is_support_se() {
|
||||
success!("Secure Enclave is supported.")
|
||||
} else {
|
||||
failure!("Secure Enclave is NOT supported.")
|
||||
}
|
||||
}
|
||||
|
||||
if json_output {}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use crate::keyutil::{parse_key_uri, KeyUri};
|
||||
use crate::seutil;
|
||||
use crate::{cmdutil, seutil};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use p256::elliptic_curve::sec1::FromEncodedPoint;
|
||||
use p256::{EncodedPoint, PublicKey};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use spki::EncodePublicKey;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@@ -32,21 +31,18 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("E-Public key"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
if !seutil::is_support_se() {
|
||||
return simple_error!("Secure Enclave is NOT supported.");
|
||||
}
|
||||
let key = sub_arg_matches.value_of("key").unwrap();
|
||||
let epk = sub_arg_matches.value_of("epk").unwrap();
|
||||
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
|
||||
let KeyUri::SecureEnclaveKey(se_key_uri) = parse_key_uri(key)?;
|
||||
debugging!("Secure enclave key URI: {:?}", se_key_uri);
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::keyutil::{parse_key_uri, KeyUri};
|
||||
use crate::seutil;
|
||||
use crate::{cmdutil, seutil};
|
||||
use crate::util::{base64_decode, base64_encode};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct CommandImpl;
|
||||
@@ -36,10 +35,12 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("Input in base64"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
if !seutil::is_support_se() {
|
||||
return simple_error!("Secure Enclave is NOT supported.");
|
||||
}
|
||||
@@ -51,10 +52,6 @@ impl Command for CommandImpl {
|
||||
},
|
||||
Some(input) => input.as_bytes().to_vec(),
|
||||
};
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
|
||||
let KeyUri::SecureEnclaveKey(se_key_uri) = parse_key_uri(key)?;
|
||||
debugging!("Secure enclave key URI: {:?}", se_key_uri);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use crate::pkiutil::bytes_to_pem;
|
||||
use crate::seutil;
|
||||
use crate::{cmdutil, seutil};
|
||||
use crate::util::base64_encode;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use p256::PublicKey;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use spki::DecodePublicKey;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@@ -37,19 +36,17 @@ impl Command for CommandImpl {
|
||||
.long("disable-bio")
|
||||
.help("Disable bio"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
if !seutil::is_support_se() {
|
||||
return simple_error!("Secure Enclave is NOT supported.");
|
||||
}
|
||||
let ty = sub_arg_matches.value_of("type").unwrap();
|
||||
let host = sub_arg_matches.value_of("host").unwrap_or("macbook");
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
|
||||
let sign = match ty {
|
||||
"signing" | "ecsign" | "sign" => true,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::cmd_se_generate::print_se_key;
|
||||
use crate::keyutil::{parse_key_uri, KeyUri, KeyUsage};
|
||||
use crate::seutil;
|
||||
use crate::{cmdutil, seutil};
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -22,20 +21,17 @@ impl Command for CommandImpl {
|
||||
.takes_value(true)
|
||||
.help("Key uri"),
|
||||
)
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
if !seutil::is_support_se() {
|
||||
return simple_error!("Secure Enclave is NOT supported.");
|
||||
}
|
||||
let key_uri = sub_arg_matches.value_of("key").unwrap();
|
||||
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
|
||||
let KeyUri::SecureEnclaveKey(se_key_uri) = parse_key_uri(key_uri)?;
|
||||
debugging!("Secure enclave key URI: {:?}", se_key_uri);
|
||||
|
||||
|
||||
@@ -2,45 +2,44 @@ use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use jwt::{AlgorithmType, Header, ToBase64};
|
||||
use jwt::header::HeaderType;
|
||||
use rust_util::{util_msg, util_time, XResult};
|
||||
use jwt::{AlgorithmType, Header, ToBase64};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::{util_time, XResult};
|
||||
use serde_json::{Map, Number, Value};
|
||||
use yubikey::piv::{sign_data, AlgorithmId, SlotId};
|
||||
use yubikey::{Certificate, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, sign_data, SlotId};
|
||||
|
||||
use crate::{digest, pivutil, rsautil, util};
|
||||
use crate::ecdsautil::parse_ecdsa_to_rs;
|
||||
use crate::{cmdutil, digest, pivutil, rsautil, util};
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
impl Command for CommandImpl {
|
||||
fn name(&self) -> &str { "sign-jwt" }
|
||||
fn name(&self) -> &str {
|
||||
"sign-jwt"
|
||||
}
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
let app = SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("key-id").short("K").long("key-id").takes_value(true).help("Header key ID"))
|
||||
.arg(Arg::with_name("claims").short("C").long("claims").takes_value(true).multiple(true).help("Claims, key:value"))
|
||||
.arg(Arg::with_name("payload").short("P").long("payload").takes_value(true).help("Claims in JSON"))
|
||||
.arg(Arg::with_name("jti").long("jti").help("Claims jti"))
|
||||
.arg(Arg::with_name("validity").long("validity").takes_value(true).help("Claims validity period e.g. 10m means 10 minutes (s - second, m - minute, h - hour, d - day)"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_json_arg());
|
||||
fill_sign_jwt_app_args(app)
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
let slot = opt_value_result!(
|
||||
sub_arg_matches.value_of("slot"), "--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e");
|
||||
sub_arg_matches.value_of("slot"),
|
||||
"--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"
|
||||
);
|
||||
|
||||
let (header, payload, jwt_claims) = build_jwt_parts(sub_arg_matches)?;
|
||||
|
||||
@@ -64,15 +63,34 @@ impl Command for CommandImpl {
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_jwt(yk: &mut YubiKey, slot_id: SlotId, pin_opt: &Option<String>, mut header: Header, payload: &Option<String>, claims: &Map<String, Value>) -> XResult<String> {
|
||||
pub fn fill_sign_jwt_app_args<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||
app.arg(Arg::with_name("key-id").short("K").long("key-id").takes_value(true).help("Header key ID"))
|
||||
.arg(Arg::with_name("claims").short("C").long("claims").takes_value(true).multiple(true).help("Claims, key:value"))
|
||||
.arg(Arg::with_name("payload").short("P").long("payload").takes_value(true).help("Claims in JSON"))
|
||||
.arg(Arg::with_name("jti").long("jti").help("Claims jti"))
|
||||
.arg(Arg::with_name("validity").long("validity").takes_value(true).help("Claims validity period e.g. 10m means 10 minutes (s - second, m - minute, h - hour, d - day)"))
|
||||
}
|
||||
|
||||
fn sign_jwt(
|
||||
yk: &mut YubiKey,
|
||||
slot_id: SlotId,
|
||||
pin_opt: &Option<String>,
|
||||
mut header: Header,
|
||||
payload: &Option<String>,
|
||||
claims: &Map<String, Value>,
|
||||
) -> XResult<String> {
|
||||
if let Some(pin) = pin_opt {
|
||||
opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}");
|
||||
opt_result!(
|
||||
yk.verify_pin(pin.as_bytes()),
|
||||
"YubiKey verify pin failed: {}"
|
||||
);
|
||||
}
|
||||
let cert = match Certificate::read(yk, slot_id) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return simple_error!("Read YubiKey certificate failed: {}", e),
|
||||
};
|
||||
let piv_algorithm_id = pivutil::get_algorithm_id(&cert.cert.tbs_certificate.subject_public_key_info)?;
|
||||
let piv_algorithm_id =
|
||||
pivutil::get_algorithm_id(&cert.cert.tbs_certificate.subject_public_key_info)?;
|
||||
|
||||
let (jwt_algorithm, yk_algorithm) = match piv_algorithm_id {
|
||||
AlgorithmId::Rsa1024 => return simple_error!("RSA 1024 bits not supported."),
|
||||
@@ -90,18 +108,21 @@ fn sign_jwt(yk: &mut YubiKey, slot_id: SlotId, pin_opt: &Option<String>, mut hea
|
||||
let tobe_signed = merge_header_claims(header.as_bytes(), claims.as_bytes());
|
||||
|
||||
let raw_in = match jwt_algorithm {
|
||||
AlgorithmType::Rs256 => rsautil::pkcs15_sha256_rsa_2048_padding_for_sign(
|
||||
&digest::sha256_bytes(&tobe_signed)),
|
||||
AlgorithmType::Rs256 => {
|
||||
rsautil::pkcs15_sha256_rsa_2048_padding_for_sign(&digest::sha256_bytes(&tobe_signed))
|
||||
}
|
||||
AlgorithmType::Es256 => digest::sha256_bytes(&tobe_signed),
|
||||
AlgorithmType::Es384 => digest::sha384_bytes(&tobe_signed),
|
||||
_ => return simple_error!("SHOULD NOT HAPPEN: {:?}", jwt_algorithm),
|
||||
};
|
||||
|
||||
let signed_data = opt_result!(
|
||||
sign_data(yk, &raw_in, yk_algorithm, slot_id), "Sign YubiKey failed: {}");
|
||||
sign_data(yk, &raw_in, yk_algorithm, slot_id),
|
||||
"Sign YubiKey failed: {}"
|
||||
);
|
||||
let signed_data = match jwt_algorithm {
|
||||
AlgorithmType::Rs256 => signed_data.to_vec(),
|
||||
AlgorithmType::Es256 | AlgorithmType::Es384 => parse_ecdsa_to_rs(signed_data.as_slice())?,
|
||||
AlgorithmType::Es256 | AlgorithmType::Es384 => parse_ecdsa_to_rs(signed_data.as_slice())?,
|
||||
_ => return simple_error!("SHOULD NOT HAPPEN: {:?}", jwt_algorithm),
|
||||
};
|
||||
|
||||
@@ -118,14 +139,21 @@ pub fn merge_header_claims(header: &[u8], claims: &[u8]) -> Vec<u8> {
|
||||
tobe_signed
|
||||
}
|
||||
|
||||
pub fn merge_payload_claims<'a>(payload: &'a Option<String>, claims: &'a Map<String, Value>) -> XResult<Cow<'a, str>> {
|
||||
pub fn merge_payload_claims<'a>(
|
||||
payload: &'a Option<String>,
|
||||
claims: &'a Map<String, Value>,
|
||||
) -> XResult<Cow<'a, str>> {
|
||||
Ok(match (payload, claims.is_empty()) {
|
||||
(Some(payload), true) => Cow::Owned(util::base64_encode_url_safe_no_pad(payload.as_bytes())),
|
||||
(Some(payload), true) => {
|
||||
Cow::Owned(util::base64_encode_url_safe_no_pad(payload.as_bytes()))
|
||||
}
|
||||
(_, _) => opt_result!(claims.to_base64(), "Claims to base64 failed: {}"),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_jwt_parts(sub_arg_matches: &ArgMatches) -> XResult<(Header, Option<String>, Map<String, Value>)> {
|
||||
pub fn build_jwt_parts(
|
||||
sub_arg_matches: &ArgMatches,
|
||||
) -> XResult<(Header, Option<String>, Map<String, Value>)> {
|
||||
let key_id = sub_arg_matches.value_of("key-id");
|
||||
let claims = sub_arg_matches.values_of("claims");
|
||||
let payload = sub_arg_matches.value_of("payload");
|
||||
@@ -145,8 +173,12 @@ pub fn build_jwt_parts(sub_arg_matches: &ArgMatches) -> XResult<(Header, Option<
|
||||
jwt_claims.insert(k, v);
|
||||
});
|
||||
}
|
||||
Ok(value) => { warning!("Not valid payload map: {}", value); }
|
||||
Err(e) => { warning!("Not valid payload value: {}", e); }
|
||||
Ok(value) => {
|
||||
warning!("Not valid payload map: {}", value);
|
||||
}
|
||||
Err(e) => {
|
||||
warning!("Not valid payload value: {}", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -155,8 +187,12 @@ pub fn build_jwt_parts(sub_arg_matches: &ArgMatches) -> XResult<(Header, Option<
|
||||
(_, Some(claims)) => {
|
||||
for claim in claims {
|
||||
match split_claim(claim) {
|
||||
None => { warning!("Claim '{}' do not contains ':'", claim); }
|
||||
Some((k, v)) => { jwt_claims.insert(k, v); }
|
||||
None => {
|
||||
warning!("Claim '{}' do not contains ':'", claim);
|
||||
}
|
||||
Some((k, v)) => {
|
||||
jwt_claims.insert(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !jwt_claims.contains_key("sub") {
|
||||
@@ -168,15 +204,23 @@ pub fn build_jwt_parts(sub_arg_matches: &ArgMatches) -> XResult<(Header, Option<
|
||||
|
||||
// set jti, iat and sub
|
||||
if jti && !jwt_claims.contains_key("jti") {
|
||||
jwt_claims.insert("jti".to_string(), Value::String(format!("jti-{}", util_time::get_current_millis())));
|
||||
jwt_claims.insert(
|
||||
"jti".to_string(),
|
||||
Value::String(format!("jti-{}", util_time::get_current_millis())),
|
||||
);
|
||||
}
|
||||
if let Some(validity) = validity {
|
||||
match util_time::parse_duration(validity) {
|
||||
None => { warning!("Bad validity: {}", validity) }
|
||||
None => {
|
||||
warning!("Bad validity: {}", validity)
|
||||
}
|
||||
Some(validity) => {
|
||||
let current_secs = (util_time::get_current_millis() / 1000) as u64;
|
||||
jwt_claims.insert("iat".to_string(), Value::Number(Number::from(current_secs)));
|
||||
jwt_claims.insert("exp".to_string(), Value::Number(Number::from(current_secs + validity.as_secs())));
|
||||
jwt_claims.insert(
|
||||
"exp".to_string(),
|
||||
Value::Number(Number::from(current_secs + validity.as_secs())),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
|
||||
use jwt::{AlgorithmType, Header, ToBase64};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use serde_json::{Map, Value};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::cmd_sign_jwt::{build_jwt_parts, merge_header_claims, merge_payload_claims};
|
||||
use crate::ecdsautil::parse_ecdsa_to_rs;
|
||||
use crate::keyutil::{parse_key_uri, KeyUri};
|
||||
use crate::{hmacutil, util};
|
||||
use crate::{cmd_sign_jwt, cmdutil, hmacutil, util};
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
@@ -23,21 +23,14 @@ impl Command for CommandImpl {
|
||||
}
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
let app = SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
.arg(Arg::with_name("key").long("key").required(true).takes_value(true).help("Key uri"))
|
||||
.arg(Arg::with_name("key-id").short("K").long("key-id").takes_value(true).help("Header key ID"))
|
||||
.arg(Arg::with_name("claims").short("C").long("claims").takes_value(true).multiple(true).help("Claims, key:value"))
|
||||
.arg(Arg::with_name("payload").short("P").long("payload").takes_value(true).help("Claims in JSON"))
|
||||
.arg(Arg::with_name("jti").long("jti").help("Claims jti"))
|
||||
.arg(Arg::with_name("validity").long("validity").takes_value(true).help("Claims validity period e.g. 10m means 10 minutes (s - second, m - minute, h - hour, d - day)"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg());
|
||||
cmd_sign_jwt::fill_sign_jwt_app_args(app)
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::collections::BTreeMap;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use jwt::{AlgorithmType, Header, ToBase64};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::{util_msg, XResult};
|
||||
use rust_util::XResult;
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
use crate::cmd_sign_jwt::{build_jwt_parts, merge_header_claims, merge_payload_claims};
|
||||
use crate::keychain::{KeychainKey, KeychainKeyValue};
|
||||
use crate::{digest, ecdsautil, hmacutil, keychain, rsautil, util};
|
||||
use crate::{cmd_sign_jwt, cmdutil, digest, ecdsautil, hmacutil, keychain, rsautil, util};
|
||||
|
||||
const SEPARATOR: &str = ".";
|
||||
|
||||
@@ -20,21 +20,14 @@ impl Command for CommandImpl {
|
||||
}
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
let app = SubCommand::with_name(self.name()).about("Sign JWT subcommand")
|
||||
.arg(Arg::with_name("private-key").short("k").long("private-key").takes_value(true).help("Private key PKCS#8"))
|
||||
.arg(Arg::with_name("key-id").short("K").long("key-id").takes_value(true).help("Header key ID"))
|
||||
.arg(Arg::with_name("claims").short("C").long("claims").takes_value(true).multiple(true).help("Claims, key:value"))
|
||||
.arg(Arg::with_name("payload").short("P").long("payload").takes_value(true).help("Claims in JSON"))
|
||||
.arg(Arg::with_name("jti").long("jti").help("Claims jti"))
|
||||
.arg(Arg::with_name("validity").long("validity").takes_value(true).help("Claims validity period e.g. 10m means 10 minutes (s - second, m - minute, h - hour, d - day)"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg());
|
||||
cmd_sign_jwt::fill_sign_jwt_app_args(app)
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ use yubikey::{Key, YubiKey};
|
||||
|
||||
use crate::digest::{sha256_bytes, sha384_bytes};
|
||||
use crate::pivutil::slot_equals;
|
||||
use crate::{pinutil, pivutil, util};
|
||||
use crate::{cmdutil, pinutil, pivutil, util};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -27,9 +27,9 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("SSH PIV sign cert subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(Arg::with_name("key-id").short("k").long("key-id").takes_value(true).default_value("default_key_id").help("SSH user CA key id"))
|
||||
.arg(Arg::with_name("principal").short("P").long("principal").takes_value(true).default_value("root").multiple(true).help("SSH user CA principal"))
|
||||
.arg(Arg::with_name("pub").short("f").long("pub").alias("pub-file").required(true).takes_value(true).help("SSH public key file"))
|
||||
|
||||
@@ -6,7 +6,7 @@ use rust_util::util_msg;
|
||||
use yubikey::{Key, YubiKey};
|
||||
use yubikey::piv::{AlgorithmId, sign_data};
|
||||
|
||||
use crate::{pinutil, pivutil, util};
|
||||
use crate::{cmdutil, pinutil, pivutil, util};
|
||||
use crate::pivutil::{get_algorithm_id_by_certificate, slot_equals, ToStr};
|
||||
use crate::sshutil::SshVecWriter;
|
||||
|
||||
@@ -18,9 +18,9 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("SSH piv sign subcommand")
|
||||
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN"))
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(cmdutil::build_pin_arg())
|
||||
.arg(Arg::with_name("no-pin").long("no-pin").help("No PIN"))
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
.arg(Arg::with_name("namespace").short("n").long("namespace").takes_value(true).help("Namespace"))
|
||||
.arg(Arg::with_name("in").long("in").required(true).takes_value(true).help("In file, - for stdin"))
|
||||
}
|
||||
|
||||
@@ -1,30 +1,39 @@
|
||||
use crate::digest::sha256_bytes;
|
||||
use crate::pivutil;
|
||||
use crate::pivutil::{get_algorithm_id_by_certificate, slot_equals, ToStr};
|
||||
use crate::sshutil::SshVecWriter;
|
||||
use crate::{cmdutil, pivutil};
|
||||
use base64::engine::general_purpose::STANDARD;
|
||||
use base64::Engine;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use std::collections::BTreeMap;
|
||||
use yubikey::piv::AlgorithmId;
|
||||
use yubikey::{Key, YubiKey};
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
impl Command for CommandImpl {
|
||||
fn name(&self) -> &str { "ssh-pub-key" }
|
||||
fn name(&self) -> &str {
|
||||
"ssh-pub-key"
|
||||
}
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("SSH public key subcommand")
|
||||
.arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"))
|
||||
SubCommand::with_name(self.name())
|
||||
.about("SSH public key subcommand")
|
||||
.arg(cmdutil::build_slot_arg())
|
||||
.arg(Arg::with_name("ca").long("ca").help("SSH cert-authority"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
util_msg::set_logger_std_out(false);
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let slot = opt_value_result!(sub_arg_matches.value_of("slot"), "--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e");
|
||||
let mut json = BTreeMap::<&'_ str, String>::new();
|
||||
|
||||
let slot = opt_value_result!(
|
||||
sub_arg_matches.value_of("slot"),
|
||||
"--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"
|
||||
);
|
||||
let ca = sub_arg_matches.is_present("ca");
|
||||
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
||||
let slot_id = pivutil::get_slot_id(slot)?;
|
||||
@@ -33,19 +42,28 @@ impl Command for CommandImpl {
|
||||
let mut ec_key_point = vec![];
|
||||
match Key::list(&mut yk) {
|
||||
Err(e) => warning!("List keys failed: {}", e),
|
||||
Ok(keys) => for k in &keys {
|
||||
let slot_str = format!("{:x}", Into::<u8>::into(k.slot()));
|
||||
if slot_equals(&slot_id, &slot_str) {
|
||||
let cert = &k.certificate().cert.tbs_certificate;
|
||||
let certificate = k.certificate();
|
||||
if let Ok(algorithm_id) = get_algorithm_id_by_certificate(certificate) {
|
||||
match algorithm_id {
|
||||
AlgorithmId::EccP256 | AlgorithmId::EccP384 => {
|
||||
let public_key_bit_string = &cert.subject_public_key_info.subject_public_key;
|
||||
ec_key_point.extend_from_slice(public_key_bit_string.raw_bytes());
|
||||
algorithm_id_opt = Some(algorithm_id);
|
||||
Ok(keys) => {
|
||||
for k in &keys {
|
||||
let slot_str = format!("{:x}", Into::<u8>::into(k.slot()));
|
||||
if slot_equals(&slot_id, &slot_str) {
|
||||
let cert = &k.certificate().cert.tbs_certificate;
|
||||
let certificate = k.certificate();
|
||||
if let Ok(algorithm_id) = get_algorithm_id_by_certificate(certificate) {
|
||||
match algorithm_id {
|
||||
AlgorithmId::EccP256 | AlgorithmId::EccP384 => {
|
||||
let public_key_bit_string =
|
||||
&cert.subject_public_key_info.subject_public_key;
|
||||
ec_key_point
|
||||
.extend_from_slice(public_key_bit_string.raw_bytes());
|
||||
algorithm_id_opt = Some(algorithm_id);
|
||||
}
|
||||
_ => {
|
||||
return simple_error!(
|
||||
"Not P256/384 key: {}",
|
||||
algorithm_id.to_str()
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => return simple_error!("Not P256/384 key: {}", algorithm_id.to_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,18 +100,34 @@ impl Command for CommandImpl {
|
||||
ssh_pub_key.write_bytes(&ecc_key_blob);
|
||||
|
||||
let ssh_pub_key_sha256 = sha256_bytes(&ssh_pub_key);
|
||||
information!("SSH key SHA256: {} (base64)", STANDARD.encode(&ssh_pub_key_sha256));
|
||||
information!(
|
||||
"SSH key SHA256: {} (base64)",
|
||||
STANDARD.encode(&ssh_pub_key_sha256)
|
||||
);
|
||||
information!("SSH key SHA256: {} (hex)", hex::encode(&ssh_pub_key_sha256));
|
||||
eprintln!();
|
||||
|
||||
println!(
|
||||
let ssh_pub_key = format!(
|
||||
"{}ecdsa-sha2-{} {} Yubikey-PIV-{}",
|
||||
if ca { "cert-authority,principals=\"root\" " } else { "" },
|
||||
if ca {
|
||||
"cert-authority,principals=\"root\" "
|
||||
} else {
|
||||
""
|
||||
},
|
||||
ssh_algorithm,
|
||||
STANDARD.encode(&ssh_pub_key),
|
||||
slot_id
|
||||
);
|
||||
|
||||
if json_output {
|
||||
json.insert("ssh_pub_key", ssh_pub_key);
|
||||
} else {
|
||||
println!("{}", &ssh_pub_key);
|
||||
}
|
||||
|
||||
if json_output {
|
||||
println!("{}", serde_json::to_string_pretty(&json).unwrap());
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,10 @@ use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::sign::Verifier;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg;
|
||||
use x509_parser::certificate::X509Certificate;
|
||||
use x509_parser::prelude::FromDer;
|
||||
|
||||
use crate::digest;
|
||||
use crate::{cmdutil, digest};
|
||||
use crate::fido;
|
||||
use crate::fido::{U2fRegistrationData, U2fV2Challenge};
|
||||
use crate::util::base64_encode;
|
||||
@@ -29,12 +28,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("timeout").short("t").long("timeout").default_value("30").help("Timeout in seconds"))
|
||||
.arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX"))
|
||||
.arg(Arg::with_name("challenge-with-timestamp-prefix").long("challenge-with-timestamp-prefix").help("Challenge with timestamp prefix"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let timeout_ms = match sub_arg_matches.value_of("timeout").unwrap().parse::<u32>() {
|
||||
Ok(t) => (t * 1000) as u64,
|
||||
|
||||
@@ -13,7 +13,7 @@ use openssl::pkey::PKey;
|
||||
use openssl::sign::Verifier;
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
|
||||
use crate::digest;
|
||||
use crate::{cmdutil, digest};
|
||||
use crate::fido;
|
||||
use crate::fido::U2fV2Challenge;
|
||||
use crate::util::base64_encode;
|
||||
@@ -31,12 +31,11 @@ impl Command for CommandImpl {
|
||||
.arg(Arg::with_name("challenge").long("challenge").takes_value(true).help("Challenge HEX"))
|
||||
.arg(Arg::with_name("challenge-with-timestamp-prefix").long("challenge-with-timestamp-prefix").help("Challenge with timestamp prefix"))
|
||||
.arg(Arg::with_name("key-handle").short("k").long("key-handle").takes_value(true).multiple(true).help("Key handle"))
|
||||
.arg(Arg::with_name("json").long("json").help("JSON output"))
|
||||
.arg(cmdutil::build_json_arg())
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output { rust_util::util_msg::set_logger_std_out(false); }
|
||||
let json_output = cmdutil::check_json_output(sub_arg_matches);
|
||||
|
||||
let timeout_ms = match sub_arg_matches.value_of("timeout").unwrap().parse::<u32>() {
|
||||
Ok(t) => (t * 1000) as u64,
|
||||
|
||||
33
src/cmdutil.rs
Normal file
33
src/cmdutil.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use clap::{Arg, ArgMatches};
|
||||
use rust_util::util_msg;
|
||||
|
||||
pub fn build_slot_arg() -> Arg<'static, 'static> {
|
||||
Arg::with_name("slot")
|
||||
.short("s")
|
||||
.long("slot")
|
||||
.takes_value(true)
|
||||
.help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e")
|
||||
}
|
||||
|
||||
pub fn build_pin_arg() -> Arg<'static, 'static> {
|
||||
Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN")
|
||||
}
|
||||
|
||||
pub fn build_keychain_name_arg() -> Arg<'static, 'static> {
|
||||
Arg::with_name("keychain-name")
|
||||
.long("keychain-name")
|
||||
.takes_value(true)
|
||||
.help("Key chain name")
|
||||
}
|
||||
|
||||
pub fn build_json_arg() -> Arg<'static, 'static> {
|
||||
Arg::with_name("json").long("json").help("JSON output")
|
||||
}
|
||||
|
||||
pub fn check_json_output(sub_arg_matches: &ArgMatches) -> bool {
|
||||
let json_output = sub_arg_matches.is_present("json");
|
||||
if json_output {
|
||||
util_msg::set_logger_std_out(false);
|
||||
}
|
||||
json_output
|
||||
}
|
||||
@@ -71,6 +71,7 @@ mod signfile;
|
||||
mod sshutil;
|
||||
mod util;
|
||||
mod keychain;
|
||||
mod cmdutil;
|
||||
|
||||
pub struct DefaultCommandImpl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user