feat: v1.1.0, add static x25519 support

This commit is contained in:
2023-12-08 21:36:03 +08:00
parent 883ed0918b
commit fd7e8d35a6
12 changed files with 209 additions and 39 deletions

View File

@@ -9,7 +9,7 @@ use std::time::{Instant, SystemTime};
use clap::Args;
use flate2::Compression;
use openpgp_card::crypto_data::Cryptogram;
use rust_util::{debugging, failure, iff, information, opt_result, println_ex, simple_error, success, util_cmd, util_msg, util_size, util_time, warning, XResult};
use rust_util::{debugging, failure, iff, information, opt_result, opt_value_result, println_ex, simple_error, success, util_cmd, util_msg, util_size, util_time, warning, XResult};
use rust_util::util_time::UnixEpochTime;
use x509_parser::prelude::FromDer;
use x509_parser::x509::SubjectPublicKeyInfo;
@@ -18,6 +18,8 @@ use yubikey::YubiKey;
use zeroize::Zeroize;
use crate::{cmd_encrypt, consts, crypto_simple, util, util_enc_file, util_env, util_envelop, util_file, util_pgp, util_piv};
#[cfg(feature = "macos")]
use crate::util_keychainpasskey;
use crate::compress::GzStreamDecoder;
use crate::config::TinyEncryptConfig;
use crate::consts::{
@@ -61,9 +63,12 @@ pub struct CmdDecrypt {
/// Digest file
#[arg(long, short = 'D')]
pub digest_file: bool,
// Edit file
/// Edit file
#[arg(long, short = 'E')]
pub edit_file: bool,
// Readonly
#[arg(long)]
pub readonly: bool,
/// Digest algorithm (sha1, sha256[default], sha384, sha512 ...)
#[arg(long, short = 'A')]
pub digest_algorithm: Option<String>,
@@ -196,6 +201,10 @@ pub fn decrypt_single(config: &Option<TinyEncryptConfig>,
let do_edit_file = || -> XResult<()> {
let temp_file_content_bytes = run_file_editor_and_wait_content(&editor, &temp_file, secure_editor, &temp_encryption_key_nonce)?;
if cmd_decrypt.readonly {
information!("Readonly, do not check temp file is changed.");
return Ok(());
}
let temp_file_content_bytes = if secure_editor {
let mut decryptor = temp_cryptor.decryptor(&temp_key_nonce)?;
decryptor.decrypt(&temp_file_content_bytes)?
@@ -421,6 +430,8 @@ pub fn try_decrypt_key(config: &Option<TinyEncryptConfig>,
match envelop.r#type {
TinyEncryptEnvelopType::Pgp => try_decrypt_key_pgp(envelop, pin),
TinyEncryptEnvelopType::PgpX25519 => try_decrypt_key_ecdh_pgp_x25519(envelop, pin),
#[cfg(feature = "macos")]
TinyEncryptEnvelopType::StaticX25519 => try_decrypt_key_ecdh_static_x25519(config, envelop),
TinyEncryptEnvelopType::Ecdh | TinyEncryptEnvelopType::EcdhP384 => try_decrypt_key_ecdh(config, envelop, pin, slot),
unknown_type => simple_error!("Unknown or unsupported type: {}", unknown_type.get_name()),
}
@@ -491,6 +502,36 @@ fn try_decrypt_key_ecdh_pgp_x25519(envelop: &TinyEncryptEnvelop, pin: &Option<St
Ok(decrypted_key)
}
#[cfg(feature = "macos")]
fn try_decrypt_key_ecdh_static_x25519(config: &Option<TinyEncryptConfig>, envelop: &TinyEncryptEnvelop) -> XResult<Vec<u8>> {
let wrap_key = WrapKey::parse(&envelop.encrypted_key)?;
let cryptor = match wrap_key.header.enc.as_str() {
ENC_AES256_GCM_X25519 => Cryptor::Aes256Gcm,
ENC_CHACHA20_POLY1305_X25519 => Cryptor::ChaCha20Poly1305,
_ => return simple_error!("Unsupported header enc: {}", &wrap_key.header.enc),
};
let e_pub_key_bytes = wrap_key.header.get_e_pub_key_bytes()?;
let config = opt_value_result!(config, "Tiny encrypt config is not found");
let config_envelop = opt_value_result!(
config.find_by_kid(&envelop.kid), "Cannot find config for: {}", &envelop.kid);
let config_envelop_args = opt_value_result!(&config_envelop.args, "No arguments found for: {}", &envelop.kid);
if config_envelop_args.len() < 3 {
return simple_error!("Not enough arguments for: {}", &envelop.kid);
}
let service_name = &config_envelop_args[1];
let key_name = &config_envelop_args[2];
let shared_secret = opt_result!(
util_keychainpasskey::decrypt_data(service_name, key_name, &e_pub_key_bytes), "Decrypt static x25519 failed: {}");
let key = util::simple_kdf(shared_secret.as_slice());
let key_nonce = KeyNonce { k: &key, n: &wrap_key.nonce };
let decrypted_key = crypto_simple::decrypt(
cryptor, &key_nonce, &wrap_key.encrypted_data)?;
util::zeroize(key);
util::zeroize(shared_secret);
Ok(decrypted_key)
}
fn try_decrypt_key_pgp(envelop: &TinyEncryptEnvelop, pin: &Option<String>) -> XResult<Vec<u8>> {
let mut pgp = util_pgp::get_openpgp()?;
let mut trans = opt_result!(pgp.transaction(), "Connect OpenPGP card failed: {}");
@@ -523,7 +564,9 @@ pub fn select_envelop<'a>(meta: &'a TinyEncryptMeta, key_id: &Option<String>, co
if envelops.len() == 1 {
let selected_envelop = &envelops[0];
success!("Auto selected envelop: #{} {}", 1, util_envelop::format_envelop(selected_envelop, config));
util::read_line("Press enter to continue: ");
if !selected_envelop.r#type.auto_select() {
util::read_line("Press enter to continue: ");
}
return Ok(selected_envelop);
}