conradkleinespel / rpassword

Cross platform Rust library to read a password in the terminal (Linux, BSD, OSX, Windows, WASM).
Apache License 2.0
244 stars 38 forks source link

Masked echo functionality #43

Closed tov closed 4 years ago

tov commented 4 years ago

I’d like a way to provide per-keystroke feedback, such as printing "•" or "***" for each character that the user enters. (I have some users who are just getting accustomed to terminals, and this is one of their first interactions. Oh, and I’m having them paste a big long key, not just type a password that they know.)

Even better, something like this:

pub fn read_password_with_hook<F>(hook: F) -> std::io::Result<()>
where F: FnMut(char) -> std::io::Result<bool>;  // Ok(true) means continue

would let me write my thing (quick and dirty):

fn read_with_echo(echo: &str) -> Result<String> {
    let mut result = String::new();

    read_password_with_hook(|c|
        if c == '\n' {
            tty_print_raw!("\n")?;
            Ok(false)
        } else {
            if c != '\r' {
                result.push(c);
                tty_print_raw!("{}", echo)?;
            }
            Ok(true)
        })?;

    Ok(result)
}

If you like this idea, I’m happy to implement it and submit a PR. There’s probably a better design than read_password_with_hook, and I’m happy to discuss that too. Are you interested?

conradkleinespel commented 4 years ago

Hi @tov ! I really like the idea. Actually, sometimes, I mistype my password specifically because I don't know how many chars I've typed. So yeah, I'm totally open to merging something like that :+1:

I'm not sure what you mean by Ok(true) means continue. What continues ?

tov commented 4 years ago

The idea is that the closure returns Ok(true) to tell the function to keep reading, Ok(false) to tell the function to stop reading and return Ok(()), and Err(e) to tell the function to return Err(e).

conradkleinespel commented 4 years ago

@tov Oh OK, that's interesting ! I'm totally open to this if it's something that useful to you. I guess it would allow to read password that contain newlines in them (passphrases and what not), which is currently not possible.

How would you write a hook that detects \r\n (2 chars) which is I think what Windows uses? Maybe send the hook a slice of what has been read up to a given point?

conradkleinespel commented 4 years ago

Given this issue is now 6 months old without change, I'll go ahead and close it. Feel free to reopen it you want to keep working on this.