feat: v1.1.0, add static x25519 support
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user