I recently helped with the release of the password-2.0 library.
This 2.0 release corresponds to a big rewrite of the
password library, spearheaded entirely by Felix Paulusma.
What is the
password library was originally intended to be used by people implementing username/password authentication in web applications, but it is now easily usable by anyone dealing with passwords and password hashing in any type of application.
There are four main advantages of using
PasswordHashtypes that can be shared throughout your code. These are meant to be simple types with reasonable typeclass instances. You should be able to take
passwordas a dependency and rely on these types from other libraries.
Easy-to-use functions for hashing a
Password, and checking a
An optional password-instances package that provides additional typeclass instances for
FromJSON(from aeson), FromHttpApiData (from http-api-data), and PersistField (from persistent). These instances are frequently used when doing actual web development.
Great documentation. Anything confusing in the Haddocks is considered a "high-priority" bug.
What changed in
The following algorithms are now supported:
- Scrypt (this was the only algorithm supported in the original
password-2.0 also adds a bunch of much-needed documentation, as well as many tests.
How to use
This section will present a short tutorial for using
password. The following commands are run in a GHCi session. You can follow along if you start GHCi with a command like
stack --resolver nightly-2020-05-16 ghci --package password-188.8.131.52.
OverloadedStrings extension to make the following code a little easier:
The first step in using
password is to pick which hashing algorithm you want to use. If you don't know which to pick, we recommend Bcrypt. The trade-offs of the different algorithms are discussed in more detail in the Haddocks.
Once you've picked the hashing algorithm, you can import its module. We use
Data.Password.Bcrypt as an example:
Note that the
Show instance for
Password doesn't actually show the password. This is a security measure. You don't have to worry about passwords leaking into your web application logs.
PasswordHash can be stored in a database4.
checkPassword function can be used to check a
Password against a
There are a few issues in the
password library that we'd like help with from anyone interested.
Split off the
Data.Passwordmodule into a separate package called
All of the hashing algorithms provided in
However, we would ideally like people to be able to use the
PasswordHashdata types as canonical data types in different libraries on Hackage. We don't want all these packages to have to pull in a transitive dependency on
Ideally, we would have a
password-typespackage that just exports everything from the current
Data.Passwordmodule (which doesn't require a dependency on
password-instancespackage into separate packages.
password-instanceshas instances for
PasswordHashfor type classes from
Ideally, there would be a more fine-grained way to pick only the instances you want.
For instance, if you're not using
persistentto access a database, you shouldn't have to transitively depend on
persistentjust to get instances from
Add more helpful instances to
password-instanceshas helpful instances from a few widely used libraries, but it is missing many more.
If you use
password, please consider contributing missing instances!
Support different hash formats.
passwordhas its own way of encoding hashes. In the above example, you can see that the Bcrypt algorithm outputs hashes that look like this:
This works well if you're writing your application from the beginning with
password, but if you're trying to interoperate with password hashes produced by other languages and frameworks, you'll have to do some manual conversion.
It would be nice to extend the
hashPasswordfunctions to be able to read/write password hashes in other formats.
Add functionality for validating password complexity requirements.
passwordcurrently doesn't provide any functionality for validating the complexity of passwords. It would be nice if it provided an API for checking whether passwords are at least a given length, have a certain number of uppercase, lowercase, and special characters, etc.
This might be of interest to anyone who likes designing easy-to-use APIs for complicated use-cases.
Perform a security audit.
We'd love to get an in-depth review from any security-minded Haskellers.
passwordmostly just wraps around functionality provided by
cryptonite, but it would still be great to get a review for the code we do have.
If you find any big issues, feel free to email me directly if you don't feel comfortable creating a public issue on GitHub.
Please feel free to send pull requests or create issues for any of the above enhancements.
Conclusion and Thanks
There were a few other people who contributed as well:
Thanks to everyone, and I hope we get more contributions in the future!
checkPasswordall have a phantom parameter. This is used to store the algorithm that was used to hash the password. You are not able to call
checkPasswordon a hash produced from a different algorithm's