feat: add pgp card

This commit is contained in:
2023-02-12 18:11:32 +08:00
parent 34993a83a5
commit 817b088a67
7 changed files with 1420 additions and 17 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.tinyenc
# ---> Rust
# Generated by Cargo
# will have compiled files and executables

1362
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,18 @@ description = "A simple and tiny file encrypt tool"
[dependencies]
aes-gcm = { version = "0.10.1", features = ["zeroize"] }
base64 = "0.21.0"
clap = { version = "4.1.4", features = ["derive"] }
hex = "0.4.3"
openpgp-card = "0.3.3"
openpgp-card-pcsc = "0.3.0"
reqwest = { version = "0.11.14", features = ["blocking", "rustls", "rustls-tls"] }
rust_util = "0.6.41"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
yubico_manager = "0.9.0"
[profile.release]
codegen-units = 1
opt-level = 'z'
lto = true

13
src/card.rs Normal file
View File

@@ -0,0 +1,13 @@
use openpgp_card_pcsc::PcscBackend;
use rust_util::{opt_result, opt_value_result, simple_error, warning, XResult};
pub fn get_card() -> XResult<PcscBackend> {
let card_list = opt_result!(PcscBackend::cards(None), "Read OpenPGP card list failed: {}");
if card_list.is_empty() {
return simple_error!("Cannot find any card");
}
if card_list.len() > 1 {
warning!("Find {} OpenPGP cards, will use first card", card_list.len());
}
Ok(opt_value_result!(card_list.into_iter().next(), "SHOULD NOT HAPPEN, CANNOT FIND ANY CARD"))
}

43
src/cmd_decrypt.rs Normal file
View File

@@ -0,0 +1,43 @@
use std::path::PathBuf;
use std::fs::File;
use std::io::Read;
use base64::Engine;
use base64::engine::general_purpose;
use openpgp_card::crypto_data::Cryptogram;
use openpgp_card::OpenPgp;
use rust_util::{debugging, failure, opt_result, simple_error, success, XResult};
use crate::card::get_card;
use crate::file;
pub fn decrypt(path: PathBuf, pin: &Option<String>) -> XResult<()> {
let path_display = format!("{}", path.display());
let mut file_in = opt_result!(File::open(path), "Open file: {} failed: {}", &path_display);
let meta = opt_result!(file::read_tiny_encrypt_meta(&mut file_in), "Read file: {}, failed: {}", &path_display);
let mut card = match get_card() {
Err(e) => {
failure!("Get PGP card failed: {}", e);
return simple_error!("Get card failed: {}", e);
}
Ok(card) => card
};
let mut pgp = OpenPgp::new(card);
let mut trans = opt_result!(pgp.transaction(), "Open card failed: {}");
let pin = pin.as_ref().map(|s| s.as_str()).unwrap_or_else(|| "123456");
if let Err(e) = trans.verify_pw1_user(pin.as_ref()) {
failure!("Verify user pin failed: {}", e);
return simple_error!("User pin verify failed: {}", e);
}
success!("User pin verify success!");
let pgp_envelop = meta.pgp_envelop.unwrap();
debugging!("PGP envelop: {}", &pgp_envelop);
let pgp_envelop_bytes = opt_result!(general_purpose::STANDARD.decode(&pgp_envelop), "Decode PGP envelop failed: {}");
let key = trans.decipher(Cryptogram::RSA(&pgp_envelop_bytes))?;
success!("{}", hex::encode(&key));
Ok(())
}

View File

@@ -7,7 +7,6 @@ pub fn info(path: PathBuf) -> XResult<()> {
let path_display = format!("{}", path.display());
let mut file_in = opt_result!(File::open(path), "Open file: {} failed: {}", &path_display);
let meta = opt_result!(file::read_tiny_encrypt_meta(&mut file_in), "Read file: {}, failed: {}", &path_display);
// println!("{}", serde_json::to_string_pretty(&meta).expect("SHOULD NOT HAPPEN"));
let mut infos = vec![];
infos.push("Tiny Encrypt File Info".to_string());

View File

@@ -9,7 +9,9 @@ use rust_util::{information, XResult};
mod spec;
mod crypto;
mod file;
mod card;
mod cmd_info;
mod cmd_decrypt;
#[derive(Debug, Parser)]
#[command(name = "tiny-encrypt-rs")]
@@ -47,7 +49,10 @@ fn main() -> XResult<()> {
paths.iter().for_each(|f| information!("{:?}", f));
Ok(())
}
Commands::Decrypt { .. } => {
Commands::Decrypt { mut paths } => {
for path in paths {
cmd_decrypt::decrypt(path, &Some("123456".to_string())).unwrap();
}
Ok(())
}
Commands::Info { path } => {