feat: updates
This commit is contained in:
@@ -3,14 +3,13 @@ use std::fs::File;
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use base64::Engine;
|
|
||||||
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, opt_result, simple_error, success, util_term, XResult};
|
||||||
|
|
||||||
use crate::{file, util};
|
use crate::{file, util};
|
||||||
use crate::card::get_card;
|
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};
|
use crate::util::{decode_base64, TINY_ENC_FILE_EXT};
|
||||||
|
|
||||||
pub fn decrypt(path: &PathBuf, pin: &Option<String>) -> XResult<()> {
|
pub fn decrypt(path: &PathBuf, pin: &Option<String>) -> 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: {}");
|
let len = opt_result!(file_in.read(&mut buffer), "Read file failed: {}");
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
let last_block = opt_result!(decryptor.finalize(), "Decrypt file failed: {}");
|
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);
|
success!("Decrypt finished, total bytes: {}", total_len);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
total_len += len;
|
total_len += len;
|
||||||
let decrypted = decryptor.update(&buffer[0..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)
|
Ok(total_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_decrypt_key(envelop: &TinyEncryptEnvelop, pin: &Option<String>) -> XResult<Vec<u8>> {
|
fn try_decrypt_key(envelop: &TinyEncryptEnvelop, pin: &Option<String>) -> XResult<Vec<u8>> {
|
||||||
match envelop.r#type.to_lowercase().as_str() {
|
match envelop.r#type {
|
||||||
"pgp" => try_decrypt_key_pgp(envelop, pin),
|
TinyEncryptEnvelopType::Pgp => try_decrypt_key_pgp(envelop, pin),
|
||||||
unknown_type => return simple_error!("Unknown or not supported type: {}", unknown_type)
|
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());
|
success!("Found {} envelops:", envelops.len());
|
||||||
if envelops.len() == 1 {
|
if envelops.len() == 1 {
|
||||||
let selected_envelop = &envelops[0];
|
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);
|
return Ok(selected_envelop);
|
||||||
}
|
}
|
||||||
|
|
||||||
envelops.iter().enumerate().for_each(|(i, envelop)| {
|
envelops.iter().enumerate().for_each(|(i, envelop)| {
|
||||||
println!("#{} {}{}", i + 1,
|
println!("#{} {}{}", i + 1,
|
||||||
envelop.r#type.to_uppercase(),
|
envelop.r#type.get_upper_name(),
|
||||||
if envelop.kid.is_empty() {
|
if envelop.kid.is_empty() {
|
||||||
"".into()
|
"".into()
|
||||||
} else {
|
} 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 envelop_number = util::read_number("Please select an envelop:", 1, envelops.len());
|
||||||
let selected_envelop = &envelops[envelop_number - 1];
|
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)
|
Ok(selected_envelop)
|
||||||
}
|
}
|
||||||
@@ -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)| {
|
meta.envelops.as_ref().map(|envelops| envelops.iter().enumerate().for_each(|(i, envelop)| {
|
||||||
infos.push(format!("{}: {}{}{}",
|
infos.push(format!("{}: {}{}{}",
|
||||||
header(&format!("Envelop #{}", i + 1)),
|
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.kid.is_empty(), "".into(), format!(", Kid: {}", envelop.kid)),
|
||||||
iff!(envelop.desc.is_none(), "".into(), format!(", Desc: {}", envelop.desc.as_ref().unwrap()))
|
iff!(envelop.desc.is_none(), "".into(), format!(", Desc: {}", envelop.desc.as_ref().unwrap()))
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use aes_gcm_stream::Aes256GcmStreamDecryptor;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_aes_gcm_01() {
|
fn test_aes_gcm_01() {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ enum Commands {
|
|||||||
Decrypt {
|
Decrypt {
|
||||||
/// Files need to be decrypted
|
/// Files need to be decrypted
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
|
/// PIN
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pin: Option<String>,
|
pin: Option<String>,
|
||||||
},
|
},
|
||||||
@@ -56,7 +57,7 @@ fn main() -> XResult<()> {
|
|||||||
paths.iter().for_each(|f| information!("{:?}", f));
|
paths.iter().for_each(|f| information!("{:?}", f));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Commands::Decrypt { mut paths, pin } => {
|
Commands::Decrypt { paths, pin } => {
|
||||||
for path in &paths {
|
for path in &paths {
|
||||||
match cmd_decrypt::decrypt(path, &pin) {
|
match cmd_decrypt::decrypt(path, &pin) {
|
||||||
Ok(_) => success!("Decrypt {} succeed", path.to_str().unwrap_or("N/A")),
|
Ok(_) => success!("Decrypt {} succeed", path.to_str().unwrap_or("N/A")),
|
||||||
|
|||||||
38
src/spec.rs
38
src/spec.rs
@@ -2,10 +2,10 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
pub const TINY_ENCRYPT_VERSION: &'static str = "1.0";
|
pub const TINY_ENCRYPT_VERSION: &'static str = "1.0";
|
||||||
|
|
||||||
pub const ENVELOP_TYPE_KMS: &'static str = "kms";
|
// pub const ENVELOP_TYPE_KMS: &'static str = "kms";
|
||||||
pub const ENVELOP_TYPE_PGP: &'static str = "pgp";
|
// pub const ENVELOP_TYPE_PGP: &'static str = "pgp";
|
||||||
pub const ENVELOP_TYPE_AGE: &'static str = "age";
|
// pub const ENVELOP_TYPE_AGE: &'static str = "age";
|
||||||
pub const ENVELOP_TYPE_ECDH: &'static str = "ecdh";
|
// 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)
|
/// 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)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
@@ -37,20 +37,38 @@ pub struct TinyEncryptMeta {
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TinyEncryptEnvelop {
|
pub struct TinyEncryptEnvelop {
|
||||||
pub r#type: String,
|
pub r#type: TinyEncryptEnvelopType,
|
||||||
pub kid: String,
|
pub kid: String,
|
||||||
pub desc: Option<String>,
|
pub desc: Option<String>,
|
||||||
pub encrypted_key: String,
|
pub encrypted_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// use serde...
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
pub enum TinyEncryptEnvelopType {
|
pub enum TinyEncryptEnvelopType {
|
||||||
|
#[serde(rename = "pgp")]
|
||||||
Pgp,
|
Pgp,
|
||||||
|
#[serde(rename = "age")]
|
||||||
Age,
|
Age,
|
||||||
|
#[serde(rename = "ecdh")]
|
||||||
Ecdh,
|
Ecdh,
|
||||||
|
#[serde(rename = "kms")]
|
||||||
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 {
|
impl TinyEncryptMeta {
|
||||||
pub fn normalize(&mut self) {
|
pub fn normalize(&mut self) {
|
||||||
if self.envelops.is_none() {
|
if self.envelops.is_none() {
|
||||||
@@ -65,7 +83,7 @@ impl TinyEncryptMeta {
|
|||||||
fn normalize_envelop(&mut self) {
|
fn normalize_envelop(&mut self) {
|
||||||
if let (Some(envelop), Some(envelops)) = (&self.envelop, &mut self.envelops) {
|
if let (Some(envelop), Some(envelops)) = (&self.envelop, &mut self.envelops) {
|
||||||
envelops.push(TinyEncryptEnvelop {
|
envelops.push(TinyEncryptEnvelop {
|
||||||
r#type: ENVELOP_TYPE_KMS.into(),
|
r#type: TinyEncryptEnvelopType::Kms,
|
||||||
kid: "".into(),
|
kid: "".into(),
|
||||||
desc: None,
|
desc: None,
|
||||||
encrypted_key: envelop.into(),
|
encrypted_key: envelop.into(),
|
||||||
@@ -78,7 +96,7 @@ impl TinyEncryptMeta {
|
|||||||
if let (Some(pgp_envelop), Some(pgp_fingerprint), Some(envelops))
|
if let (Some(pgp_envelop), Some(pgp_fingerprint), Some(envelops))
|
||||||
= (&self.pgp_envelop, &self.pgp_fingerprint, &mut self.envelops) {
|
= (&self.pgp_envelop, &self.pgp_fingerprint, &mut self.envelops) {
|
||||||
envelops.push(TinyEncryptEnvelop {
|
envelops.push(TinyEncryptEnvelop {
|
||||||
r#type: ENVELOP_TYPE_PGP.into(),
|
r#type: TinyEncryptEnvelopType::Pgp,
|
||||||
kid: pgp_fingerprint.into(),
|
kid: pgp_fingerprint.into(),
|
||||||
desc: None,
|
desc: None,
|
||||||
encrypted_key: pgp_envelop.into(),
|
encrypted_key: pgp_envelop.into(),
|
||||||
@@ -92,7 +110,7 @@ impl TinyEncryptMeta {
|
|||||||
if let (Some(age_envelop), Some(age_recipient), Some(envelops))
|
if let (Some(age_envelop), Some(age_recipient), Some(envelops))
|
||||||
= (&self.age_envelop, &self.age_recipient, &mut self.envelops) {
|
= (&self.age_envelop, &self.age_recipient, &mut self.envelops) {
|
||||||
envelops.push(TinyEncryptEnvelop {
|
envelops.push(TinyEncryptEnvelop {
|
||||||
r#type: ENVELOP_TYPE_AGE.into(),
|
r#type: TinyEncryptEnvelopType::Age,
|
||||||
kid: age_recipient.into(),
|
kid: age_recipient.into(),
|
||||||
desc: None,
|
desc: None,
|
||||||
encrypted_key: age_envelop.into(),
|
encrypted_key: age_envelop.into(),
|
||||||
@@ -106,7 +124,7 @@ impl TinyEncryptMeta {
|
|||||||
if let (Some(ecdh_envelop), Some(ecdh_point), Some(envelops))
|
if let (Some(ecdh_envelop), Some(ecdh_point), Some(envelops))
|
||||||
= (&self.ecdh_envelop, &self.ecdh_point, &mut self.envelops) {
|
= (&self.ecdh_envelop, &self.ecdh_point, &mut self.envelops) {
|
||||||
envelops.push(TinyEncryptEnvelop {
|
envelops.push(TinyEncryptEnvelop {
|
||||||
r#type: ENVELOP_TYPE_ECDH.into(),
|
r#type: TinyEncryptEnvelopType::Ecdh,
|
||||||
kid: ecdh_point.into(),
|
kid: ecdh_point.into(),
|
||||||
desc: None,
|
desc: None,
|
||||||
encrypted_key: ecdh_envelop.into(),
|
encrypted_key: ecdh_envelop.into(),
|
||||||
|
|||||||
Reference in New Issue
Block a user