HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulepassword-3.0.4.0Haskell2010

Data.Password.Bcrypt

bcrypt

The bcrypt algorithm is a popular way of hashing passwords. It is based on the Blowfish cipher and fairly straightfoward in its usage. It has a cost parameter that, when increased, slows down the hashing speed.

It is a straightforward and easy way to get decent protection on passwords, it has also been around long enough to be battle-tested and generally considered to provide a good amount of security.

Other algorithms

bcrypt, together with PBKDF2, are only computationally intensive. And to protect from specialized hardware, new algorithms have been developed that are also resource intensive, like Scrypt and Argon2. Not having high resource demands, means an attacker with specialized software could take less time to brute-force a password, though with the default cost (10) and a decently long password, the amount of time to brute-force would still be significant.

This is the algorithm to use if you're not sure about your needs, but just want a decent, proven way to encrypt your passwords.

Properties of a bcrypt hash

The hashes generated by this library are always prefixed by the "$2b$" version prefix.

This library will accept hashes with the "$2b$", "$2y$" and "$2a$" versions. As the "$2$" and "$2x$" versions were created with flawed algorithms.

A bcrypt hash generated by this library is _ALWAYS_ 60 characters long. Now while the very first version of bcrypt would have hashes that were 59 characters long, because of the 1 character-long "$2$" version prefix, bcrypt has had a version increase shortly after release, turning the prefix into a 2 character-long one like "$2a$" pretty much from the very beginning.

  • 5 types
  • 9 values
  • Packagepassword-3.0.4.0
  • Exports14
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceBcrypt.hs

Algorithm

1 declaration
datadata Bcrypt
#

Phantom type for bcrypt

Plain-text Password

2 declarations
newtypenewtype Password
#

A plain-text password.

This represents a plain-text password that has NOT been hashed.

You should be careful with Password. Make sure not to write it to logs or store it in a database.

You can construct a Password by using the mkPassword function or as literal strings together with the OverloadedStrings pragma (or manually, by using fromString on a String). Alternatively, you could also use some of the instances in the password-instances library.

Instances2Show, IsString
  • Show PasswordDefined in password-types-1.0.0.0 · Data.Password.Types

    CAREFUL: Show-ing a Password will always print "**PASSWORD**"

    Example1 expression
    show ("hello" :: Password)"**PASSWORD**"
  • IsString PasswordDefined in password-types-1.0.0.0 · Data.Password.Types

Hash Passwords (bcrypt)

2 declarations

Hash the Password using the bcrypt hash algorithm.

N.B.: bcrypt has a limit of 72 bytes as input, so anything longer than that will be cut off at the 72 byte point and thus any password that is 72 bytes or longer will match as long as the first 72 bytes are the same.

Example1 expression
hashPassword $ mkPassword "foobar"PasswordHash {unPasswordHash = "$2b$10$..."}
newtypenewtype PasswordHash a
#

A hashed password.

This represents a password that has been put through a hashing function. The hashed password can be stored in a database.

Instances4Eq, Ord, Read, Show
  • Eq (PasswordHash a)Defined in password-types-1.0.0.0 · Data.Password.Types
  • Ord (PasswordHash a)Defined in password-types-1.0.0.0 · Data.Password.Types
  • Read (PasswordHash a)Defined in password-types-1.0.0.0 · Data.Password.Types
  • Show (PasswordHash a)Defined in password-types-1.0.0.0 · Data.Password.Types

Verify Passwords (bcrypt)

2 declarations

Check a Password against a PasswordHash Bcrypt.

Returns PasswordCheckSuccess on success.

Example3 expressions
let pass = mkPassword "foobar"passHash <- hashPassword passcheckPassword pass passHashPasswordCheckSuccess

Returns PasswordCheckFail if an incorrect Password or PasswordHash Bcrypt is used.

Example2 expressions
let badpass = mkPassword "incorrect-password"checkPassword badpass passHashPasswordCheckFail

This should always fail if an incorrect password is given.

Property
\(Blind badpass) -> let correctPasswordHash = hashPasswordWithSalt 8 salt "foobar" in checkPassword badpass correctPasswordHash == PasswordCheckFail
datadata PasswordCheck
#

The result of checking a password against a hashed version. This is returned by the checkPassword functions.

Constructors

  • PasswordCheckSuccess

    The password check was successful. The plain-text password matches the hashed password.

  • PasswordCheckFail

    The password check failed. The plain-text password does not match the hashed password.

Instances3Eq, Read, Show

Hashing Manually (bcrypt)

3 declarations
valuehashPasswordWithParams
  1. :: MonadIO m
  2. => Int

    The cost parameter. Should be between 4 and 31 (inclusive). Values which lie outside this range will be adjusted accordingly.

  3. -> Password

    The password to be hashed.

  4. -> m (PasswordHash Bcrypt)

    The bcrypt hash in standard format.

#

Hash a password using the bcrypt algorithm with the given cost.

The higher the cost, the longer hashPassword and checkPassword will take to run, thus increasing the security, but taking longer and taking up more resources. The optimal cost for generic user logins would be one that would take between 0.05 - 0.5 seconds to check on the machine that will run it.

N.B.: It is advised to use hashPassword if you're unsure about the implications that changing the cost brings with it.

Hashing with salt (DISADVISED)

Hashing with a set Salt is almost never what you want to do. Use hashPassword or hashPasswordWithParams to have automatic generation of randomized salts.

valuehashPasswordWithSalt
  1. :: Int

    The cost parameter. Should be between 4 and 31 (inclusive). Values which lie outside this range will be adjusted accordingly.

  2. -> Salt Bcrypt

    The salt. MUST be 16 bytes in length or an error will be raised.

  3. -> Password

    The password to be hashed.

  4. -> PasswordHash Bcrypt

    The bcrypt hash in standard format.

#

Hash a password with the given cost and also with the given Salt instead of generating a random salt. Using hashPasswordWithSalt is strongly disadvised, and hashPasswordWithParams should be used instead. Never use a static salt in production applications!

N.B.: The salt HAS to be 16 bytes or this function will throw an error!

Example2 expressions
let salt = Salt "abcdefghijklmnop"hashPasswordWithSalt 10 salt (mkPassword "foobar")PasswordHash {unPasswordHash = "$2b$10$WUHhXETkX0fnYkrqZU3ta.N8Utt4U77kW4RVbchzgvBvBBEEdCD/u"}

(Note that we use an explicit Salt in the example above. This is so that the example is reproducible, but in general you should use hashPassword. hashPassword (and hashPasswordWithParams) generates a new Salt everytime it is called.)

newtypenewtype Salt a
#

A salt used by a hashing algorithm.

Constructors

Instances2Eq, Show
  • Eq (Salt a)Defined in password-types-1.0.0.0 · Data.Password.Types
  • Show (Salt a)Defined in password-types-1.0.0.0 · Data.Password.Types

Unsafe debugging function to show a Password

1 declaration

This is an unsafe function that shows a password in plain-text.

Example1 expression
unsafeShowPassword ("foobar" :: Password)"foobar"

You should generally not use this function in production settings, as you don't want to accidentally print a password anywhere, like logs, network responses, database entries, etc.

This will mostly be used by other libraries to handle the actual password internally, though it is conceivable that, even in a production setting, a password might have to be handled in an unsafe manner at some point.

Setup for doctests.

0 declarations
Example2 expressions
:set -XFlexibleInstances:set -XOverloadedStrings

Import needed libraries.

Example4 expressions
import Data.Password.Typesimport Data.ByteString (pack)import Test.QuickCheck (Arbitrary(arbitrary), Blind(Blind), vector)import Test.QuickCheck.Instances.Text ()
Example3 expressions
instance Arbitrary (Salt a) where arbitrary = Salt . pack <$> vector 16instance Arbitrary Password where arbitrary = fmap mkPassword arbitrarylet salt = Salt "abcdefghijklmnop"