password-instances-0.3.0.0: typeclass instances for password package

Copyright(c) Dennis Gosnell 2019
LicenseBSD-style (see LICENSE file)
Maintainercdep.illabout@gmail.com
Stabilityexperimental
PortabilityPOSIX
Safe HaskellNone
LanguageHaskell2010

Data.Password.Instances

Contents

Description

This module provides the same interface as Data.Password, but it also provides additional typeclass instances for Pass and PassHash.

See the Data.Password module for more information.

Synopsis

Plaintext Password

newtype Pass #

A plain-text password.

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

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

Constructors

Pass 

Fields

Instances
Read Pass 
Instance details

Defined in Data.Password

IsString Pass 
Instance details

Defined in Data.Password

Methods

fromString :: String -> Pass #

FromJSON Pass Source #

This instance allows a Pass to be created from a JSON blob.

>>> let maybePass = decode "\"foobar\"" :: Maybe Pass
>>> fmap unsafeShowPassword maybePass
Just "foobar"

There is no instance for ToJSON for Pass because we don't want to accidentally encode a plain-text Pass to JSON and send it to the end-user.

Similarly, there is no ToJSON and FromJSON instance for PassHash because we don't want to accidentally send the password hash to the end user.

Instance details

Defined in Data.Password.Instances

FromHttpApiData Pass Source #

This instance allows a Pass to be created with functions like parseUrlPiece or parseQueryParam.

>>> let eitherPass = parseUrlPiece "foobar" :: Either Text Pass
>>> fmap unsafeShowPassword eitherPass
Right "foobar"
Instance details

Defined in Data.Password.Instances

Hashed Password

newtype PassHash #

A hashed password.

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

Constructors

PassHash 

Fields

Instances
Eq PassHash 
Instance details

Defined in Data.Password

Ord PassHash 
Instance details

Defined in Data.Password

Read PassHash 
Instance details

Defined in Data.Password

Show PassHash 
Instance details

Defined in Data.Password

PersistFieldSql PassHash Source #

This instance allows a PassHash to be stored as a field in an SQL database in Database.Persist.Sql.

Instance details

Defined in Data.Password.Instances

PersistField PassHash Source #

This instance allows a PassHash to be stored as a field in a database using Database.Persist.

>>> let salt = Salt "abcdefghijklmnopqrstuvwxyz012345"
>>> let pass = Pass "foobar"
>>> let hashedPassword = hashPassWithSalt (Pass "foobar") salt
>>> toPersistValue hashedPassword
PersistText "14|8|1|YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU=|nENDaqWBmPKapAqQ3//H0iBImweGjoTqn5SvBS8Mc9FPFbzq6w65maYPZaO+SPamVZRXQjARQ8Y+5rhuDhjIhw=="

In the example above, the long PersistText will be the value you store in the database.

We don't provide an instance of PersistField for Pass, because we don't want to make it easy to store a plain-text password in the database.

Instance details

Defined in Data.Password.Instances

newtype Salt #

Constructors

Salt 

Fields

Instances
Eq Salt 
Instance details

Defined in Crypto.Scrypt

Methods

(==) :: Salt -> Salt -> Bool #

(/=) :: Salt -> Salt -> Bool #

Show Salt 
Instance details

Defined in Crypto.Scrypt

Methods

showsPrec :: Int -> Salt -> ShowS #

show :: Salt -> String #

showList :: [Salt] -> ShowS #

Functions for Hashing Plaintext Passwords

hashPass :: MonadIO m => Pass -> m PassHash #

Just like hashPassWithSalt, but generate a new Salt everytime with a call to newSalt.

>>> hashPass (Pass "foobar")
PassHash {unPassHash = "14|8|1|...|..."}

hashPassWithSalt :: Pass -> Salt -> PassHash #

Hash a password with the given Salt.

The resulting PassHash has the parameters used to hash it, as well as the Salt appended to it, separated by |.

The input Salt and resulting PassHash are both byte-64 encoded.

>>> let salt = Salt "abcdefghijklmnopqrstuvwxyz012345"
>>> hashPassWithSalt (Pass "foobar") salt
PassHash {unPassHash = "14|8|1|YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU=|nENDaqWBmPKapAqQ3//H0iBImweGjoTqn5SvBS8Mc9FPFbzq6w65maYPZaO+SPamVZRXQjARQ8Y+5rhuDhjIhw=="}

(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 hashPass. hashPass generates a new Salt everytime it is called.)

This function uses the hash function from the scrypt package: encryptPass.

newSalt :: IO Salt #

Generate a random 32-byte salt.

Functions for Checking Plaintext Passwords Against Hashed Passwords

checkPass :: Pass -> PassHash -> PassCheck #

Check a Pass against a PassHash.

Returns PassCheckSucc on success.

>>> let salt = Salt "abcdefghijklmnopqrstuvwxyz012345"
>>> let pass = Pass "foobar"
>>> let passHash = hashPassWithSalt pass salt
>>> checkPass pass passHash
PassCheckSucc

Returns PassCheckFail If an incorrect Pass or PassHash is used.

>>> let badpass = Pass "incorrect-password"
>>> checkPass badpass passHash
PassCheckFail

This should always fail if an incorrect password is given.

\(Blind badpass) -> let correctPassHash = hashPassWithSalt (Pass "foobar") salt in checkPass badpass correctPassHash == PassCheckFail

data PassCheck #

The result of a checking a password against a hashed version. This is returned by checkPass.

Constructors

PassCheckSucc

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

PassCheckFail

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

Instances
Eq PassCheck 
Instance details

Defined in Data.Password

Read PassCheck 
Instance details

Defined in Data.Password

Show PassCheck 
Instance details

Defined in Data.Password

Unsafe Debugging Functions for Showing a Password

unsafeShowPassword :: Pass -> String #

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

>>> unsafeShowPasswordText $ Pass "foobar"
"foobar"

You should generally not use this function.

unsafeShowPasswordText :: Pass -> Text #

This is like unsafeShowPassword but produces a Text instead of a String.

Setup for doctests.

>>> :set -XOverloadedStrings

Import needed functions.

>>> import Data.Aeson (decode)
>>> import Data.Text (Text)
>>> import Database.Persist.Class (PersistField(toPersistValue))
>>> import Web.HttpApiData (parseUrlPiece)

Orphan instances

FromJSON Pass Source #

This instance allows a Pass to be created from a JSON blob.

>>> let maybePass = decode "\"foobar\"" :: Maybe Pass
>>> fmap unsafeShowPassword maybePass
Just "foobar"

There is no instance for ToJSON for Pass because we don't want to accidentally encode a plain-text Pass to JSON and send it to the end-user.

Similarly, there is no ToJSON and FromJSON instance for PassHash because we don't want to accidentally send the password hash to the end user.

Instance details

FromHttpApiData Pass Source #

This instance allows a Pass to be created with functions like parseUrlPiece or parseQueryParam.

>>> let eitherPass = parseUrlPiece "foobar" :: Either Text Pass
>>> fmap unsafeShowPassword eitherPass
Right "foobar"
Instance details

PersistFieldSql PassHash Source #

This instance allows a PassHash to be stored as a field in an SQL database in Database.Persist.Sql.

Instance details

PersistField PassHash Source #

This instance allows a PassHash to be stored as a field in a database using Database.Persist.

>>> let salt = Salt "abcdefghijklmnopqrstuvwxyz012345"
>>> let pass = Pass "foobar"
>>> let hashedPassword = hashPassWithSalt (Pass "foobar") salt
>>> toPersistValue hashedPassword
PersistText "14|8|1|YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU=|nENDaqWBmPKapAqQ3//H0iBImweGjoTqn5SvBS8Mc9FPFbzq6w65maYPZaO+SPamVZRXQjARQ8Y+5rhuDhjIhw=="

In the example above, the long PersistText will be the value you store in the database.

We don't provide an instance of PersistField for Pass, because we don't want to make it easy to store a plain-text password in the database.

Instance details