How do I use getpass?

In v0.6.x, I used Base.getpass to prompt the user for a password, then just used string interpolation to pass the password to create a login cookie. I think this was possible because previously, getpass just returned a string.

Now (in v0.7), it seems getpass returns a SecretBuffer, which seems like an improvement, but now I don’t know how to use the output.

help?> Base.SecretBuffer
Base.SecretBuffer()

An IOBuffer-like object where the contents will be securely wiped when garbage collected.

It is considered best practice to wipe the buffer using Base.shred!(::SecretBuffer) as soon as the secure data are no longer required. When initializing with existing data, the SecretBuffer! method is highly recommended to securely zero the passed argument. Avoid initializing with and converting to Strings as they are unable to be securely zeroed.

You can read from it like any IO object - just avoid putting it into a string (i.e. no simple read). Most methods and packages dealing with passwords (hashing etc.) I’ve seen can handle IO directly, so you should be able to pass it directly to them.

Interestingly in both 0.7/1.0, Base. has to be prepended for both getpass and SecretBuffer to get the doc to show up. Might be best to report an issue about that.

I’m using the password in a python API, which appears to handle passwords using plain strings only. Ignoring the issue of whether or not that’s a good idea, is getpass usable in this situation? Or do I need to use something like Base.prompt?

Well, yes - but you’re losing all the benefit of using getpass in the first place if you need to convert it to a String anyway. The only benefit is the input not showing up in for example the REPL. Maybe there is some kind of preprocessing you can do to avoid sending the password itself as a string?

You can read from the SecretBuffer to return a String using read(x, String) where x is the SecretBuffer returned by getpass.

2 Likes

Thanks. I wonder what the utility of getpass in v0.6 actually was, then, since it just returned a String

True - but it didn’t display the input while typing, as Base.prompt does now.

Testing this in the REPL, I only get an empty string…

Hmm

julia> Base.getpass("Password:")
Password::
SecretBuffer("*******")

julia> read(ans, String)
"hunter2"
1 Like

:confused:

               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: https://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.7.0 (2018-08-08 06:46 UTC)
 _/ |\__'_|_|_|\__'_|  |  Official http://julialang.org/ release
|__/                   |  x86_64-w64-mingw32

julia> Base.getpass("Test: ")
Test: : SecretBuffer("*******")

julia> read(ans,String)
┌ Warning: a SecretBuffer was `shred!`ed by the GC; use `shred!` manually after use to minimize exposure.
└ @ Base secretbuffer.jl:169
""

I guess that makes sense if you take the warning into account, but trying it again does not yield a warning and still gives an empty string.

p.s. nice password

Are you sure you’ve entered something? I get the same behaviour @kristoffer.carlsson observes, on both 0.7 and 1.0.

Well, as sure as I can be. I’ve been just typing in the same manner as when I was typing everything else in the REPL. I also just tried pasting something from my clipboard, to no avail. This is weird.

Edit: I think it is something with the input, though. Using Base.winprompt works.

Ah, that might explain the difference - I’m (effectively) on Linux (through WSL). Do you mind opening an issue? Offending code should be here - seems like there are different functions depending on OS. I can only check later today on my main machine whether I can reproduce this.

Issue created here