feat: supports -R
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
|
use std::{fs, io};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -8,7 +8,7 @@ use std::time::Instant;
|
|||||||
use clap::Args;
|
use clap::Args;
|
||||||
use openpgp_card::crypto_data::Cryptogram;
|
use openpgp_card::crypto_data::Cryptogram;
|
||||||
use openpgp_card::OpenPgp;
|
use openpgp_card::OpenPgp;
|
||||||
use rust_util::{debugging, failure, opt_result, simple_error, success, util_term, XResult};
|
use rust_util::{debugging, failure, information, opt_result, simple_error, success, util_term, warning, XResult};
|
||||||
use x509_parser::prelude::FromDer;
|
use x509_parser::prelude::FromDer;
|
||||||
use x509_parser::x509::SubjectPublicKeyInfo;
|
use x509_parser::x509::SubjectPublicKeyInfo;
|
||||||
use yubikey::piv::{AlgorithmId, decrypt_data, RetiredSlotId, SlotId};
|
use yubikey::piv::{AlgorithmId, decrypt_data, RetiredSlotId, SlotId};
|
||||||
@@ -32,12 +32,15 @@ pub struct CmdDecrypt {
|
|||||||
/// Slot
|
/// Slot
|
||||||
#[arg(long, short = 's')]
|
#[arg(long, short = 's')]
|
||||||
pub slot: Option<String>,
|
pub slot: Option<String>,
|
||||||
|
/// Remove source file
|
||||||
|
#[arg(long, short = 'R')]
|
||||||
|
pub remove_source_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> {
|
pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> {
|
||||||
debugging!("Cmd decrypt: {:?}", cmd_decrypt);
|
debugging!("Cmd decrypt: {:?}", cmd_decrypt);
|
||||||
for path in &cmd_decrypt.paths {
|
for path in &cmd_decrypt.paths {
|
||||||
match decrypt_single(path, &cmd_decrypt.pin, &cmd_decrypt.slot) {
|
match decrypt_single(path, &cmd_decrypt.pin, &cmd_decrypt.slot, &cmd_decrypt) {
|
||||||
Ok(_) => success!("Decrypt {} succeed", path.to_str().unwrap_or("N/A")),
|
Ok(_) => success!("Decrypt {} succeed", path.to_str().unwrap_or("N/A")),
|
||||||
Err(e) => failure!("Decrypt {} failed: {}", path.to_str().unwrap_or("N/A"), e),
|
Err(e) => failure!("Decrypt {} failed: {}", path.to_str().unwrap_or("N/A"), e),
|
||||||
}
|
}
|
||||||
@@ -45,7 +48,7 @@ pub fn decrypt(cmd_decrypt: CmdDecrypt) -> XResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_single(path: &PathBuf, pin: &Option<String>, slot: &Option<String>) -> XResult<()> {
|
pub fn decrypt_single(path: &PathBuf, pin: &Option<String>, slot: &Option<String>, cmd_decrypt: &CmdDecrypt) -> XResult<()> {
|
||||||
let path_display = format!("{}", path.display());
|
let path_display = format!("{}", path.display());
|
||||||
util::require_tiny_enc_file_and_exists(path)?;
|
util::require_tiny_enc_file_and_exists(path)?;
|
||||||
|
|
||||||
@@ -73,6 +76,14 @@ pub fn decrypt_single(path: &PathBuf, pin: &Option<String>, slot: &Option<String
|
|||||||
|
|
||||||
util::zeroize(key);
|
util::zeroize(key);
|
||||||
util::zeroize(nonce);
|
util::zeroize(nonce);
|
||||||
|
drop(file_in);
|
||||||
|
drop(file_out);
|
||||||
|
if cmd_decrypt.remove_source_file {
|
||||||
|
match fs::remove_file(path) {
|
||||||
|
Err(e) => warning!("Remove file: {} failed: {}", path_display, e),
|
||||||
|
Ok(_) => information!("Remove file: {} succeed", path_display),
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +152,7 @@ fn try_decrypt_key_ecdh(envelop: &TinyEncryptEnvelop, pin: &Option<String>, slot
|
|||||||
&epk_bytes,
|
&epk_bytes,
|
||||||
AlgorithmId::EccP256,
|
AlgorithmId::EccP256,
|
||||||
slot_id,
|
slot_id,
|
||||||
), "Decrypt piv failed: {}");
|
), "Decrypt via PIV card failed: {}");
|
||||||
let key = simple_kdf(decrypted_shared_secret.as_slice());
|
let key = simple_kdf(decrypted_shared_secret.as_slice());
|
||||||
let decrypted_key = aes_gcm_decrypt(&key, &wrap_key.nonce, &wrap_key.encrypted_data)?;
|
let decrypted_key = aes_gcm_decrypt(&key, &wrap_key.nonce, &wrap_key.encrypted_data)?;
|
||||||
Ok(decrypted_key)
|
Ok(decrypted_key)
|
||||||
@@ -181,10 +192,10 @@ fn read_slot(slot: &Option<String>) -> XResult<String> {
|
|||||||
io::stdout().flush().ok();
|
io::stdout().flush().ok();
|
||||||
let mut buff = String::new();
|
let mut buff = String::new();
|
||||||
let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin");
|
let _ = io::stdin().read_line(&mut buff).expect("Read line from stdin");
|
||||||
if buff.is_empty() {
|
if buff.trim().is_empty() {
|
||||||
simple_error!("Slot is required, and not inputed")
|
simple_error!("Slot is required, and not inputted")
|
||||||
} else {
|
} else {
|
||||||
Ok(buff)
|
Ok(buff.trim().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ use std::time::Instant;
|
|||||||
|
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use rsa::Pkcs1v15Encrypt;
|
use rsa::Pkcs1v15Encrypt;
|
||||||
use rust_util::{debugging, failure, opt_result, simple_error, success, XResult};
|
use rust_util::{debugging, failure, information, opt_result, simple_error, success, warning, XResult};
|
||||||
|
|
||||||
use crate::util;
|
|
||||||
use crate::compress::GzStreamEncoder;
|
use crate::compress::GzStreamEncoder;
|
||||||
use crate::config::{TinyEncryptConfig, TinyEncryptConfigEnvelop};
|
use crate::config::{TinyEncryptConfig, TinyEncryptConfigEnvelop};
|
||||||
use crate::crypto_aes::aes_gcm_encrypt;
|
use crate::crypto_aes::aes_gcm_encrypt;
|
||||||
use crate::crypto_rsa::parse_spki;
|
use crate::crypto_rsa::parse_spki;
|
||||||
use crate::spec::{EncMetadata, TINY_ENCRYPT_VERSION_10, TinyEncryptEnvelop, TinyEncryptEnvelopType, TinyEncryptMeta};
|
use crate::spec::{EncMetadata, TINY_ENCRYPT_VERSION_10, TinyEncryptEnvelop, TinyEncryptEnvelopType, TinyEncryptMeta};
|
||||||
|
use crate::util;
|
||||||
use crate::util::{ENC_AES256_GCM_P256, encode_base64, encode_base64_url_no_pad, make_key256_and_nonce, simple_kdf, TINY_ENC_CONFIG_FILE, zeroize};
|
use crate::util::{ENC_AES256_GCM_P256, encode_base64, encode_base64_url_no_pad, make_key256_and_nonce, simple_kdf, TINY_ENC_CONFIG_FILE, zeroize};
|
||||||
use crate::util_ecdh::compute_shared_secret;
|
use crate::util_ecdh::compute_shared_secret;
|
||||||
use crate::wrap_key::{WrapKey, WrapKeyHeader};
|
use crate::wrap_key::{WrapKey, WrapKeyHeader};
|
||||||
@@ -37,6 +37,9 @@ pub struct CmdEncrypt {
|
|||||||
/// Compatible with 1.0
|
/// Compatible with 1.0
|
||||||
#[arg(long, short = '1')]
|
#[arg(long, short = '1')]
|
||||||
pub compatible_with_1_0: bool,
|
pub compatible_with_1_0: bool,
|
||||||
|
/// Remove source file
|
||||||
|
#[arg(long, short = 'R')]
|
||||||
|
pub remove_source_file: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt(cmd_encrypt: CmdEncrypt) -> XResult<()> {
|
pub fn encrypt(cmd_encrypt: CmdEncrypt) -> XResult<()> {
|
||||||
@@ -120,6 +123,14 @@ fn encrypt_single(path: &PathBuf, envelops: &[&TinyEncryptConfigEnvelop], cmd_en
|
|||||||
|
|
||||||
zeroize(key);
|
zeroize(key);
|
||||||
zeroize(nonce);
|
zeroize(nonce);
|
||||||
|
drop(file_in);
|
||||||
|
drop(file_out);
|
||||||
|
if cmd_encrypt.remove_source_file {
|
||||||
|
match fs::remove_file(path) {
|
||||||
|
Err(e) => warning!("Remove file: {} failed: {}", path_display, e),
|
||||||
|
Ok(_) => information!("Remove file: {} succeed", path_display),
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user