3 releases (stable)

Uses old Rust 2015

1.1.0 Mar 18, 2020
1.0.0 Dec 17, 2017
0.0.1 Dec 10, 2017

#729 in Authentication

Apache-2.0

24KB
404 lines

pw Build Status

pw generates passwords statelessly, much like a brain wallet. pw has options to insert special characters, to be used in a One Time Pad mode, to generate passwords based on the current date (for organizations which require you to reset your passwords every N days), or to use some pre-shared key material in addition to the user secret to generate passwords. These options are all available via the command line, or additionally via a config file, which can be encrypted via the native OS keyring.

Installation

To install pw using a recent version of rust/cargo, do:

cargo install pw

It has a few other dependencies, which are likely installed on desktop systems:

  • dbus on Linux (libdbus-1-dev on Ubuntu)
  • gmp (libgmp-dev on Ubuntu)

Analysis

pw uses pbkdf2 with sha512 to stretch your password, with the supplied entity as the salt. The result is encoded in base58, meaning that each symbol in the password has ~5.86 of entropy. By default, pw generates passwords of length 20, so there are ~117 bits of entropy per (default) password. By comparison, "correct horse battery staple" is only 44.

Password Rotation

Changing passwords, memorably. pw offers several features for changing the generated password for a given salt and user secret combination. For example, some organizations require users to change their password every 90 days. This is security theater, but nonetheless, users must cooperate. Using a standard password generator, users could append a "2" and a "3" ("4"...) to their password ad infinitum; the problem with this is that it makes some part of the plaintext input known. pw uses a novel method of changing the number of iterations for pbkdf2 based on such inputs. --otp can be directly used to change the number of iterations and thus the generated password. --period and --date can be used together to work around organizations who e.g. require you to change your password every 90 days. --period alone calculates the password based on the current date, while --date allows you to pass an arbitrary date for which to calculate password.

Adding Special Characters

By default the base58 encoding includes only alphanumeric characters. Some organizations require special characters in their passwords. Users can add arbitrary special characters by supplying an argument to --special. By default, --special includes 25 typically allowed special characters.

Salt Recommendations

The salt is of particular importance to generated passwords. A typical suggestion is to use the domain of the entity that the password is for, but the problem is that an attacker who steals usbank.com's password database may just generate a rainbow table for usbank.com. So, some personalized version of the salt is recommended. For example, I might choose tycho.usbank.com. An additional feature (discussed in TODO) would be a global offset for the algorithm, so people could choose e.g. to not use the default offset of 0, but something else for all of their passwords.

Usage

pw has support for storing a password in the OS native keyring, via --{get,set,delete}-keyring-password, so that users don't have to type in their password each invocation.

There is also X11 clipboard support on Linux via xclip, so users can pass --clipboard to pw, and it will automatically copy the generated password to the clipboard.

Finally, worth noting is that pw has support for a configuration file, allowing for a few other features, which can be configured via --{get,set,edit,delete}-keyring-config. For example, users can store OTP offsets, special character sets, or even pre-shared key material (config key preshared, a string) to use for generating particular passwords. Currently this config file must be stored in the keyring, so it is not exposed to unencrypted access. Of course, this is not stateless, and pw can function entirely without this configuration, but it may be useful to some.

TODO

  • Encrypt the config file. This is mostly supported if you put the config file in your keyring, so not a high priority, especially given that I've not seen a file encryption library for rust that really jumps out at me.
  • global setting for --otp to further thwart rainbow tables

Dependencies

~15MB
~350K SLoC