feat: v0.2.4, add config subcommand
This commit is contained in:
66
src/cmd_config.rs
Normal file
66
src/cmd_config.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use clap::Args;
|
||||
use rust_util::XResult;
|
||||
use tabled::{Table, Tabled};
|
||||
use tabled::settings::Style;
|
||||
|
||||
use crate::config::TinyEncryptConfig;
|
||||
use crate::util::TINY_ENC_CONFIG_FILE;
|
||||
|
||||
#[derive(Tabled)]
|
||||
struct ConfigProfile {
|
||||
profiles: String,
|
||||
keys: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
pub struct CmdConfig {}
|
||||
|
||||
pub fn config(_cmd_version: CmdConfig) -> XResult<()> {
|
||||
let config = TinyEncryptConfig::load(TINY_ENC_CONFIG_FILE)?;
|
||||
|
||||
let mut reverse_map = HashMap::new();
|
||||
for (p, v) in &config.profiles {
|
||||
let p = p;
|
||||
let mut v2 = v.clone();
|
||||
v2.sort();
|
||||
let vs = v2.join(",");
|
||||
match reverse_map.get_mut(&vs) {
|
||||
None => { reverse_map.insert(vs, vec![(p, v)]); }
|
||||
Some(vec) => { vec.push((p, v)); }
|
||||
}
|
||||
}
|
||||
|
||||
let mut config_profiles = vec![];
|
||||
for pvs in reverse_map.values() {
|
||||
let mut ps: Vec<_> = pvs.iter().map(|pv| pv.0).collect();
|
||||
ps.sort();
|
||||
let pp = ps.iter().map(|s| s.to_string()).collect::<Vec<_>>().join(", ");
|
||||
let kids = pvs[0].1;
|
||||
let mut ks = Vec::with_capacity(kids.len());
|
||||
for kid in kids {
|
||||
match config.find_by_kid(kid) {
|
||||
None => {
|
||||
ks.push(format!("[ERROR] Key not found: {}", kid));
|
||||
}
|
||||
Some(envelop) => {
|
||||
let desc = envelop.desc.as_ref()
|
||||
.map(|desc| format!(", Desc: {}", desc))
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
ks.push(format!("{}{}", envelop.kid, desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
config_profiles.push(ConfigProfile {
|
||||
profiles: pp,
|
||||
keys: ks.join("\n"),
|
||||
});
|
||||
}
|
||||
|
||||
let mut table = Table::new(config_profiles);
|
||||
table.with(Style::modern());
|
||||
println!("{}", table.to_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2,25 +2,30 @@ use std::{fs, io};
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
|
||||
use clap::Args;
|
||||
use openpgp_card::{OpenPgp, OpenPgpTransaction};
|
||||
use openpgp_card::crypto_data::Cryptogram;
|
||||
use rust_util::{debugging, failure, iff, information, opt_result, simple_error, success, util_msg, util_term, warning, XResult};
|
||||
use rust_util::{
|
||||
debugging, failure, iff, information, opt_result, simple_error, success,
|
||||
util_msg, util_term, warning, XResult,
|
||||
};
|
||||
use x509_parser::prelude::FromDer;
|
||||
use x509_parser::x509::SubjectPublicKeyInfo;
|
||||
use yubikey::piv::{AlgorithmId, decrypt_data, RetiredSlotId, SlotId};
|
||||
use yubikey::piv::{AlgorithmId, decrypt_data};
|
||||
use yubikey::YubiKey;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::{card, file, util};
|
||||
use crate::{card, file, util, util_piv};
|
||||
use crate::compress::GzStreamDecoder;
|
||||
use crate::config::TinyEncryptConfig;
|
||||
use crate::crypto_aes::aes_gcm_decrypt;
|
||||
use crate::spec::{TinyEncryptEnvelop, TinyEncryptEnvelopType, TinyEncryptMeta};
|
||||
use crate::util::{ENC_AES256_GCM_P256, ENC_AES256_GCM_P384, ENC_AES256_GCM_X25519, TINY_ENC_CONFIG_FILE, TINY_ENC_FILE_EXT};
|
||||
use crate::util::{
|
||||
ENC_AES256_GCM_P256, ENC_AES256_GCM_P384, ENC_AES256_GCM_X25519,
|
||||
TINY_ENC_CONFIG_FILE, TINY_ENC_FILE_EXT,
|
||||
};
|
||||
use crate::wrap_key::WrapKey;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
@@ -194,10 +199,11 @@ fn try_decrypt_key_ecdh(config: &Option<TinyEncryptConfig>,
|
||||
let epk_bytes = subject_public_key_info.subject_public_key.as_ref();
|
||||
|
||||
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
|
||||
let retired_slot_id = opt_result!(RetiredSlotId::from_str(&slot), "Slot not found: {}");
|
||||
let slot_id = SlotId::Retired(retired_slot_id);
|
||||
let slot_id = util_piv::get_slot_id(&slot)?;
|
||||
opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}");
|
||||
let algo_id = iff!(expected_enc_type == ENC_AES256_GCM_P256, AlgorithmId::EccP256, AlgorithmId::EccP384);
|
||||
let algo_id = iff!(
|
||||
expected_enc_type == ENC_AES256_GCM_P256, AlgorithmId::EccP256, AlgorithmId::EccP384
|
||||
);
|
||||
let shared_secret = opt_result!(decrypt_data(
|
||||
&mut yk,
|
||||
&epk_bytes,
|
||||
@@ -322,7 +328,9 @@ fn select_envelop(meta: &TinyEncryptMeta) -> XResult<&TinyEncryptEnvelop> {
|
||||
|
||||
envelops.iter().enumerate().for_each(|(i, envelop)| {
|
||||
let kid = iff!(envelop.kid.is_empty(), "".into(), format!(", Kid: {}", envelop.kid));
|
||||
let desc = envelop.desc.as_ref().map(|desc| format!(", Desc: {}", desc)).unwrap_or_else(|| "".to_string());
|
||||
let desc = envelop.desc.as_ref()
|
||||
.map(|desc| format!(", Desc: {}", desc))
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
println!("#{} {}{}{}", i + 1,
|
||||
envelop.r#type.get_upper_name(),
|
||||
kid,
|
||||
|
||||
@@ -2,6 +2,7 @@ extern crate core;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use rust_util::XResult;
|
||||
use crate::cmd_config::CmdConfig;
|
||||
|
||||
use crate::cmd_decrypt::CmdDecrypt;
|
||||
use crate::cmd_encrypt::CmdEncrypt;
|
||||
@@ -9,6 +10,7 @@ use crate::cmd_info::CmdInfo;
|
||||
use crate::cmd_version::CmdVersion;
|
||||
|
||||
mod util;
|
||||
mod util_piv;
|
||||
mod util_ecdh;
|
||||
mod util_p384;
|
||||
mod util_x25519;
|
||||
@@ -21,6 +23,7 @@ mod wrap_key;
|
||||
mod file;
|
||||
mod card;
|
||||
mod cmd_version;
|
||||
mod cmd_config;
|
||||
mod cmd_info;
|
||||
mod cmd_decrypt;
|
||||
mod cmd_encrypt;
|
||||
@@ -47,6 +50,9 @@ enum Commands {
|
||||
/// Show version
|
||||
#[command(short_flag = 'v')]
|
||||
Version(CmdVersion),
|
||||
/// Show Config
|
||||
#[command(short_flag = 'c')]
|
||||
Config(CmdConfig),
|
||||
}
|
||||
|
||||
fn main() -> XResult<()> {
|
||||
@@ -56,5 +62,6 @@ fn main() -> XResult<()> {
|
||||
Commands::Decrypt(cmd_decrypt) => cmd_decrypt::decrypt(cmd_decrypt),
|
||||
Commands::Info(cmd_info) => cmd_info::info(cmd_info),
|
||||
Commands::Version(cmd_version) => cmd_version::version(cmd_version),
|
||||
Commands::Config(cmd_config) => cmd_config::config(cmd_config),
|
||||
}
|
||||
}
|
||||
33
src/util_piv.rs
Normal file
33
src/util_piv.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use rust_util::{simple_error, XResult};
|
||||
use yubikey::piv::{RetiredSlotId, SlotId};
|
||||
|
||||
pub fn get_slot_id(slot: &str) -> XResult<SlotId> {
|
||||
let slot_lower = slot.to_lowercase();
|
||||
Ok(match slot_lower.as_str() {
|
||||
"9a" | "auth" | "authentication" => SlotId::Authentication,
|
||||
"9c" | "sign" | "signature" => SlotId::Signature,
|
||||
"9d" | "keym" | "keymanagement" => SlotId::KeyManagement,
|
||||
"9e" | "card" | "cardauthentication" => SlotId::CardAuthentication,
|
||||
"r1" | "82" => SlotId::Retired(RetiredSlotId::R1),
|
||||
"r2" | "83" => SlotId::Retired(RetiredSlotId::R2),
|
||||
"r3" | "84" => SlotId::Retired(RetiredSlotId::R3),
|
||||
"r4" | "85" => SlotId::Retired(RetiredSlotId::R4),
|
||||
"r5" | "86" => SlotId::Retired(RetiredSlotId::R5),
|
||||
"r6" | "87" => SlotId::Retired(RetiredSlotId::R6),
|
||||
"r7" | "88" => SlotId::Retired(RetiredSlotId::R7),
|
||||
"r8" | "89" => SlotId::Retired(RetiredSlotId::R8),
|
||||
"r9" | "8a" => SlotId::Retired(RetiredSlotId::R9),
|
||||
"r10" | "8b" => SlotId::Retired(RetiredSlotId::R10),
|
||||
"r11" | "8c" => SlotId::Retired(RetiredSlotId::R11),
|
||||
"r12" | "8d" => SlotId::Retired(RetiredSlotId::R12),
|
||||
"r13" | "8e" => SlotId::Retired(RetiredSlotId::R13),
|
||||
"r14" | "8f" => SlotId::Retired(RetiredSlotId::R14),
|
||||
"r15" | "90" => SlotId::Retired(RetiredSlotId::R15),
|
||||
"r16" | "91" => SlotId::Retired(RetiredSlotId::R16),
|
||||
"r17" | "92" => SlotId::Retired(RetiredSlotId::R17),
|
||||
"r18" | "93" => SlotId::Retired(RetiredSlotId::R18),
|
||||
"r19" | "94" => SlotId::Retired(RetiredSlotId::R19),
|
||||
"r20" | "95" => SlotId::Retired(RetiredSlotId::R20),
|
||||
_ => return simple_error!("Unknown slot: {}", slot),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user