diff --git a/Cargo.lock b/Cargo.lock index 5e6db6f..99790fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -538,6 +538,12 @@ dependencies = [ "spki", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -721,6 +727,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "iana-time-zone" version = "0.1.58" @@ -1075,6 +1090,26 @@ dependencies = [ "base64ct", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pinentry" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5b8bc68be6a5e2ba84ee86db53f816cba1905b94fcb7c236e606221cc8fc8" +dependencies = [ + "log", + "nom", + "percent-encoding", + "secrecy", + "which", + "zeroize", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -1753,7 +1788,7 @@ dependencies = [ [[package]] name = "tiny-encrypt" -version = "1.7.2" +version = "1.7.3" dependencies = [ "aes-gcm-stream", "base64", @@ -1768,6 +1803,7 @@ dependencies = [ "openpgp-card-pcsc", "p256", "p384", + "pinentry", "pqcrypto-kyber", "pqcrypto-traits", "rand 0.8.5", @@ -1775,6 +1811,7 @@ dependencies = [ "rsa", "rust-crypto", "rust_util", + "secrecy", "security-framework", "serde", "serde_json", @@ -1936,6 +1973,18 @@ version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 49a174f..206ef8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiny-encrypt" -version = "1.7.2" +version = "1.7.3" edition = "2021" license = "MIT" description = "A simple and tiny file encrypt tool" @@ -48,6 +48,8 @@ swift-rs = { path = "swift-rs", optional = true } spki = "0.7.3" pqcrypto-kyber = "0.8.0" pqcrypto-traits = "0.3.5" +pinentry = "0.5.0" +secrecy = "0.8.0" [build-dependencies] swift-rs = { path = "swift-rs", features = ["build"], optional = true } diff --git a/README.md b/README.md index 2d213c8..caac8db 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # tiny-encrypt-rs -**IMPORTANT**: To use tiny-encrypt, a Yubikey(https://www.yubico.com/products/) or MacBook with Secure Enclave get the best security effect, the key MUST support PIV or OpenPGP. +**IMPORTANT**: To use tiny-encrypt, a Yubikey(https://www.yubico.com/products/) or MacBook with Secure Enclave get the +best security effect, the key MUST support PIV or OpenPGP. ![](https://cdn.hatter.ink/doc/7684_4DB4452911E2A25AB993429AA7FFCD65/yubikey-5-family.png) @@ -147,9 +148,11 @@ Environment | TINY_ENCRYPT_DEFAULT_ALGORITHM | Encryption algorithm, `aes` or `chacha20` | | TINY_ENCRYPT_DEFAULT_COMPRESS | File compress, `1` or `on`, default `false` | | TINY_ENCRYPT_NO_PROGRESS | Do not display progress bar | +| TINY_ENCRYPT_NO_DEFAULT_PIN_HINT | Do not display default PIN hint | | TINY_ENCRYPT_PIN | PIV Card PIN | | TINY_ENCRYPT_KEY_ID | Default Key ID | | TINY_ENCRYPT_AUTO_SELECT_KEY_IDS | Auto select Key IDs | +| TINY_ENCRYPT_PIN_ENTRY | PIN entry command cli | | SECURE_EDITOR | Secure Editor | | EDITOR | Editor (Plaintext) | diff --git a/src/util.rs b/src/util.rs index c3de44d..2a148e2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,12 +4,15 @@ use std::path::{Path, PathBuf}; use base64::Engine; use base64::engine::general_purpose; +use pinentry::PassphraseInput; use rand::random; use rust_util::{information, opt_result, print_ex, simple_error, util_term, warning, XResult}; +use secrecy::ExposeSecret; use zeroize::Zeroize; use crate::consts::TINY_ENC_FILE_EXT; use crate::util_digest::DigestWrite; +use crate::util_env; pub struct SecVec(pub Vec); @@ -28,10 +31,22 @@ impl AsRef<[u8]> for SecVec { pub fn read_pin(pin: &Option) -> String { match pin { Some(pin) => pin.to_string(), - None => if util_term::read_yes_no("Use default PIN 123456, please confirm") { + None => if !util_env::get_no_default_pin_hint() && util_term::read_yes_no("Use default PIN 123456, please confirm") { "123456".into() } else { - rpassword::prompt_password("Please input PIN: ").expect("Read PIN failed") + let pin_entry = util_env::get_pin_entry().unwrap_or_else(|| "pinentry".to_string()); + if let Some(mut input) = PassphraseInput::with_binary(pin_entry) { + let secret = input + .with_description("Enter new passphrase for FooBar") + .with_prompt("Passphrase:") + .with_confirmation("Confirm passphrase:", "Passphrases do not match") + .interact(); + secret.expect("Read PIN from pinentry failed") + .expose_secret() + .to_string() + } else { + rpassword::prompt_password("Please input PIN: ").expect("Read PIN failed") + } } } } diff --git a/src/util_env.rs b/src/util_env.rs index 9afcb1f..a469d04 100644 --- a/src/util_env.rs +++ b/src/util_env.rs @@ -12,6 +12,8 @@ pub const TINY_ENCRYPT_ENV_PIN: &str = "TINY_ENCRYPT_PIN"; pub const TINY_ENCRYPT_ENV_KEY_ID: &str = "TINY_ENCRYPT_KEY_ID"; pub const TINY_ENCRYPT_ENV_AUTO_SELECT_KEY_IDS: &str = "TINY_ENCRYPT_AUTO_SELECT_KEY_IDS"; pub const TINY_ENCRYPT_ENV_GPG_COMMAND: &str = "TINY_ENCRYPT_GPG_COMMAND"; +pub const TINY_ENCRYPT_ENV_NO_DEFAULT_PIN_HINT: &str = "TINY_ENCRYPT_NO_DEFAULT_PIN_HINT"; +pub const TINY_ENCRYPT_ENV_PIN_ENTRY: &str = "TINY_ENCRYPT_PIN_ENTRY"; pub fn get_default_encryption_algorithm() -> Option<&'static str> { let env_default_algorithm = env::var(TINY_ENCRYPT_ENV_DEFAULT_ALGORITHM).ok(); @@ -39,6 +41,10 @@ pub fn get_gpg_cmd() -> Option { env::var(TINY_ENCRYPT_ENV_GPG_COMMAND).ok() } +pub fn get_pin_entry() -> Option { + env::var(TINY_ENCRYPT_ENV_PIN_ENTRY).ok() +} + pub fn get_auto_select_key_ids() -> Option> { env::var(TINY_ENCRYPT_ENV_AUTO_SELECT_KEY_IDS).ok().map(|key_ids| { key_ids.split(',').map(ToString::to_string).collect::>() @@ -51,4 +57,8 @@ pub fn get_default_compress() -> Option { pub fn get_no_progress() -> bool { rust_util_env::is_env_on(TINY_ENCRYPT_ENV_NO_PROGRESS) +} + +pub fn get_no_default_pin_hint() -> bool { + rust_util_env::is_env_on(TINY_ENCRYPT_ENV_NO_DEFAULT_PIN_HINT) } \ No newline at end of file diff --git a/swift-rs/src-rs/lib.rs b/swift-rs/src-rs/lib.rs index 3933189..9bbf1c6 100644 --- a/swift-rs/src-rs/lib.rs +++ b/swift-rs/src-rs/lib.rs @@ -7,7 +7,7 @@ mod swift_arg; mod swift_ret; mod types; -pub use autorelease::*; +// pub use autorelease::*; pub use swift::*; pub use swift_arg::*; pub use swift_ret::*;