feat: v0.2.4, add config subcommand
This commit is contained in:
74
Cargo.lock
generated
74
Cargo.lock
generated
@@ -231,6 +231,12 @@ version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@@ -1289,6 +1295,17 @@ dependencies = [
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "papergrid"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8"
|
||||
dependencies = [
|
||||
"bytecount",
|
||||
"fnv",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.12.2"
|
||||
@@ -1405,6 +1422,30 @@ dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.68"
|
||||
@@ -1979,6 +2020,30 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabled"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfe9c3632da101aba5131ed63f9eed38665f8b3c68703a6bb18124835c1a5d22"
|
||||
dependencies = [
|
||||
"papergrid",
|
||||
"tabled_derive",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabled_derive"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.0"
|
||||
@@ -2063,7 +2128,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tiny-encrypt"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
dependencies = [
|
||||
"aes-gcm-stream",
|
||||
"base64",
|
||||
@@ -2084,6 +2149,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"simpledateformat",
|
||||
"tabled",
|
||||
"x25519-dalek",
|
||||
"x509-parser",
|
||||
"yubikey",
|
||||
@@ -2214,6 +2280,12 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiny-encrypt"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "A simple and tiny file encrypt tool"
|
||||
@@ -27,6 +27,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
sha256 = "1.4"
|
||||
simpledateformat = "0.1"
|
||||
tabled = "0.14"
|
||||
x25519-dalek = "2.0"
|
||||
x509-parser = "0.15"
|
||||
yubikey = { version = "0.8", features = ["untested"] }
|
||||
|
||||
13
README.md
13
README.md
@@ -46,13 +46,12 @@ Encrypt config `~/.tinyencrypt/config-rs.json`:
|
||||
|
||||
Supported PKI encryption types:
|
||||
|
||||
| Type | Description |
|
||||
|------------|------------------------|
|
||||
| pgp | OpenPGP RSA PKCS1-v1.5 |
|
||||
| pgp-x25519 | ECDH X25519 |
|
||||
| ecdh | ECDH P256 |
|
||||
| ecdh-p384 | ECDH P384 |
|
||||
|
||||
| Type | Algorithm | Description |
|
||||
|------------|-----------------|------------------------|
|
||||
| pgp | PKCS1-v1.5 | OpenPGP Encryption Key |
|
||||
| pgp-x25519 | ECDH(X25519) | OpenPGP Encryption Key |
|
||||
| ecdh | ECDH(secp256r1) | PIV Slot |
|
||||
| ecdh-p384 | ECDH(secp384r1) | PIV Slot |
|
||||
|
||||
Smart Card(Yubikey) protected ECDH Encryption description:
|
||||
|
||||
|
||||
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