From 1230601ed21a2fddda4d1a440e17e69f6051f9e4 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Thu, 7 Sep 2023 08:38:26 +0800 Subject: [PATCH] feat: updates --- src/cmd_decrypt.rs | 23 +++++++++-------------- src/cmd_info.rs | 2 +- src/crypto.rs | 1 - src/main.rs | 3 ++- src/spec.rs | 38 ++++++++++++++++++++++++++++---------- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/cmd_decrypt.rs b/src/cmd_decrypt.rs index a481c6f..f8e49c5 100644 --- a/src/cmd_decrypt.rs +++ b/src/cmd_decrypt.rs @@ -3,14 +3,13 @@ use std::fs::File; use std::io::{Read, Write}; use std::path::PathBuf; -use base64::Engine; use openpgp_card::crypto_data::Cryptogram; use openpgp_card::OpenPgp; use rust_util::{debugging, failure, opt_result, simple_error, success, util_term, XResult}; use crate::{file, util}; use crate::card::get_card; -use crate::spec::{TinyEncryptEnvelop, TinyEncryptMeta}; +use crate::spec::{TinyEncryptEnvelop, TinyEncryptEnvelopType, TinyEncryptMeta}; use crate::util::{decode_base64, TINY_ENC_FILE_EXT}; pub fn decrypt(path: &PathBuf, pin: &Option) -> XResult<()> { @@ -51,26 +50,22 @@ fn decrypt_file(file_in: &mut File, file_out: &mut File, key: &[u8], nonce: &[u8 let len = opt_result!(file_in.read(&mut buffer), "Read file failed: {}"); if len == 0 { let last_block = opt_result!(decryptor.finalize(), "Decrypt file failed: {}"); - if !last_block.is_empty() { - opt_result!(file_out.write_all(&last_block), "Write file failed: {}"); - } + opt_result!(file_out.write_all(&last_block), "Write file failed: {}"); success!("Decrypt finished, total bytes: {}", total_len); break; } else { total_len += len; let decrypted = decryptor.update(&buffer[0..len]); - if !decrypted.is_empty() { - opt_result!(file_out.write_all(&decrypted), "Write file failed: {}"); - } + opt_result!(file_out.write_all(&decrypted), "Write file failed: {}"); } } Ok(total_len) } fn try_decrypt_key(envelop: &TinyEncryptEnvelop, pin: &Option) -> XResult> { - match envelop.r#type.to_lowercase().as_str() { - "pgp" => try_decrypt_key_pgp(envelop, pin), - unknown_type => return simple_error!("Unknown or not supported type: {}", unknown_type) + match envelop.r#type { + TinyEncryptEnvelopType::Pgp => try_decrypt_key_pgp(envelop, pin), + unknown_type => return simple_error!("Unknown or not supported type: {}", unknown_type.get_name()) } } @@ -124,13 +119,13 @@ fn select_envelop(meta: &TinyEncryptMeta) -> XResult<&TinyEncryptEnvelop> { success!("Found {} envelops:", envelops.len()); if envelops.len() == 1 { let selected_envelop = &envelops[0]; - success!("Auto selected envelop: #{} {}", 1, selected_envelop.r#type.to_uppercase()); + success!("Auto selected envelop: #{} {}", 1, selected_envelop.r#type.get_upper_name()); return Ok(selected_envelop); } envelops.iter().enumerate().for_each(|(i, envelop)| { println!("#{} {}{}", i + 1, - envelop.r#type.to_uppercase(), + envelop.r#type.get_upper_name(), if envelop.kid.is_empty() { "".into() } else { @@ -141,6 +136,6 @@ fn select_envelop(meta: &TinyEncryptMeta) -> XResult<&TinyEncryptEnvelop> { let envelop_number = util::read_number("Please select an envelop:", 1, envelops.len()); let selected_envelop = &envelops[envelop_number - 1]; - success!("Selected envelop: #{} {}", envelop_number, selected_envelop.r#type.to_uppercase()); + success!("Selected envelop: #{} {}", envelop_number, selected_envelop.r#type.get_upper_name()); Ok(selected_envelop) } \ No newline at end of file diff --git a/src/cmd_info.rs b/src/cmd_info.rs index cfdab2b..ca82efb 100644 --- a/src/cmd_info.rs +++ b/src/cmd_info.rs @@ -46,7 +46,7 @@ pub fn info(path: PathBuf, raw_meta: bool) -> XResult<()> { meta.envelops.as_ref().map(|envelops| envelops.iter().enumerate().for_each(|(i, envelop)| { infos.push(format!("{}: {}{}{}", header(&format!("Envelop #{}", i + 1)), - envelop.r#type.to_uppercase(), + envelop.r#type.get_upper_name(), iff!(envelop.kid.is_empty(), "".into(), format!(", Kid: {}", envelop.kid)), iff!(envelop.desc.is_none(), "".into(), format!(", Desc: {}", envelop.desc.as_ref().unwrap())) )); diff --git a/src/crypto.rs b/src/crypto.rs index d9ce51f..38b966a 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -1,4 +1,3 @@ -use aes_gcm_stream::Aes256GcmStreamDecryptor; #[test] fn test_aes_gcm_01() { diff --git a/src/main.rs b/src/main.rs index c66179b..e006f62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ enum Commands { Decrypt { /// Files need to be decrypted paths: Vec, + /// PIN #[arg(long)] pin: Option, }, @@ -56,7 +57,7 @@ fn main() -> XResult<()> { paths.iter().for_each(|f| information!("{:?}", f)); Ok(()) } - Commands::Decrypt { mut paths, pin } => { + Commands::Decrypt { paths, pin } => { for path in &paths { match cmd_decrypt::decrypt(path, &pin) { Ok(_) => success!("Decrypt {} succeed", path.to_str().unwrap_or("N/A")), diff --git a/src/spec.rs b/src/spec.rs index 4019683..875b3b4 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -2,10 +2,10 @@ use serde::{Deserialize, Serialize}; pub const TINY_ENCRYPT_VERSION: &'static str = "1.0"; -pub const ENVELOP_TYPE_KMS: &'static str = "kms"; -pub const ENVELOP_TYPE_PGP: &'static str = "pgp"; -pub const ENVELOP_TYPE_AGE: &'static str = "age"; -pub const ENVELOP_TYPE_ECDH: &'static str = "ecdh"; +// pub const ENVELOP_TYPE_KMS: &'static str = "kms"; +// pub const ENVELOP_TYPE_PGP: &'static str = "pgp"; +// pub const ENVELOP_TYPE_AGE: &'static str = "age"; +// pub const ENVELOP_TYPE_ECDH: &'static str = "ecdh"; /// Specification: [Tiny Encrypt Spec V1.1](https://git.hatter.ink/hatter/tiny-encrypt-java/src/branch/master/TinyEncryptSpecV1.1.md) #[derive(Clone, Debug, Serialize, Deserialize)] @@ -37,20 +37,38 @@ pub struct TinyEncryptMeta { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TinyEncryptEnvelop { - pub r#type: String, + pub r#type: TinyEncryptEnvelopType, pub kid: String, pub desc: Option, pub encrypted_key: String, } -// use serde... +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum TinyEncryptEnvelopType { + #[serde(rename = "pgp")] Pgp, + #[serde(rename = "age")] Age, + #[serde(rename = "ecdh")] Ecdh, + #[serde(rename = "kms")] Kms, } +impl TinyEncryptEnvelopType { + pub fn get_upper_name(&self) -> String { + self.get_name().to_uppercase() + } + pub fn get_name(&self) -> &'static str { + match self { + TinyEncryptEnvelopType::Pgp => "pgp", + TinyEncryptEnvelopType::Age => "age", + TinyEncryptEnvelopType::Ecdh => "ecdh", + TinyEncryptEnvelopType::Kms => "kms", + } + } +} + impl TinyEncryptMeta { pub fn normalize(&mut self) { if self.envelops.is_none() { @@ -65,7 +83,7 @@ impl TinyEncryptMeta { fn normalize_envelop(&mut self) { if let (Some(envelop), Some(envelops)) = (&self.envelop, &mut self.envelops) { envelops.push(TinyEncryptEnvelop { - r#type: ENVELOP_TYPE_KMS.into(), + r#type: TinyEncryptEnvelopType::Kms, kid: "".into(), desc: None, encrypted_key: envelop.into(), @@ -78,7 +96,7 @@ impl TinyEncryptMeta { if let (Some(pgp_envelop), Some(pgp_fingerprint), Some(envelops)) = (&self.pgp_envelop, &self.pgp_fingerprint, &mut self.envelops) { envelops.push(TinyEncryptEnvelop { - r#type: ENVELOP_TYPE_PGP.into(), + r#type: TinyEncryptEnvelopType::Pgp, kid: pgp_fingerprint.into(), desc: None, encrypted_key: pgp_envelop.into(), @@ -92,7 +110,7 @@ impl TinyEncryptMeta { if let (Some(age_envelop), Some(age_recipient), Some(envelops)) = (&self.age_envelop, &self.age_recipient, &mut self.envelops) { envelops.push(TinyEncryptEnvelop { - r#type: ENVELOP_TYPE_AGE.into(), + r#type: TinyEncryptEnvelopType::Age, kid: age_recipient.into(), desc: None, encrypted_key: age_envelop.into(), @@ -106,7 +124,7 @@ impl TinyEncryptMeta { if let (Some(ecdh_envelop), Some(ecdh_point), Some(envelops)) = (&self.ecdh_envelop, &self.ecdh_point, &mut self.envelops) { envelops.push(TinyEncryptEnvelop { - r#type: ENVELOP_TYPE_ECDH.into(), + r#type: TinyEncryptEnvelopType::Ecdh, kid: ecdh_point.into(), desc: None, encrypted_key: ecdh_envelop.into(),