use std::{env, fs}; use pinentry::PassphraseInput; use secrecy::ExposeSecret; const PIN_ENTRY_ENV: &str = "PIN_ENTRY_CMD"; const PIN_ENTRY_1: &str = "/usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac"; const PIN_ENTRY_DEFAULT: &str = "pinentry"; pub fn get_pin() -> Result { let pin_entry = get_pin_entry(); let description = "Please input PIN"; let prompt = "PIN: "; if let Some(mut input) = PassphraseInput::with_binary(pin_entry) { let secret = input .with_description(&format!("{}.", description)) .with_prompt(prompt) .interact(); match secret { Ok(secret_string) => { Ok(secret_string.expose_secret().to_string()) } Err(e) => { Err(format!("Read PIN failed: {}", e)) } } } else { match rpassword::prompt_password(format!("{}: ", description)) { Ok(pin) => { Ok(pin) } Err(e) => { Err(format!("Read PIN2 failed: {}", e)) } } } } fn get_pin_entry() -> String { if let Ok(pin_entry) = env::var(PIN_ENTRY_ENV) { return pin_entry; } if let Ok(m) = fs::metadata(PIN_ENTRY_1) { if m.is_file() { return PIN_ENTRY_1.to_string(); } } PIN_ENTRY_DEFAULT.to_string() }