-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Hashing and checking of passwords -- -- A library providing functionality for working with plain-text and -- hashed passwords with different types of algorithms. -- --
-- >>> hashPassword $ mkPassword "foobar"
-- PasswordHash {unPasswordHash = "$2b$10$..."}
--
hashPassword :: MonadIO m => Password -> m (PasswordHash Bcrypt)
-- | A hashed password.
--
-- This represents a password that has been put through a hashing
-- function. The hashed password can be stored in a database.
newtype PasswordHash a
PasswordHash :: Text -> PasswordHash a
[unPasswordHash] :: PasswordHash a -> Text
-- | Check a Password against a PasswordHash Bcrypt.
--
-- Returns PasswordCheckSuccess on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> checkPassword pass passHash -- PasswordCheckSuccess ---- -- Returns PasswordCheckFail if an incorrect Password or -- PasswordHash Bcrypt is used. -- --
-- >>> let badpass = mkPassword "incorrect-password" -- -- >>> checkPassword badpass passHash -- PasswordCheckFail ---- -- This should always fail if an incorrect password is given. -- --
-- \(Blind badpass) -> let correctPasswordHash = hashPasswordWithSalt 8 salt "foobar" in checkPassword badpass correctPasswordHash == PasswordCheckFail --checkPassword :: Password -> PasswordHash Bcrypt -> PasswordCheck -- | The result of checking a password against a hashed version. This is -- returned by the checkPassword functions. data PasswordCheck -- | The password check was successful. The plain-text password matches the -- hashed password. PasswordCheckSuccess :: PasswordCheck -- | The password check failed. The plain-text password does not match the -- hashed password. PasswordCheckFail :: PasswordCheck -- | 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. hashPasswordWithParams :: MonadIO m => Int -> Password -> m (PasswordHash Bcrypt) -- | Extracts the cost parameter as an Int from a -- PasswordHash Bcrypt -- --
-- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> extractParams passHash == Just 10 -- True --extractParams :: PasswordHash Bcrypt -> Maybe Int -- | 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! -- --
-- >>> 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.)
hashPasswordWithSalt :: Int -> Salt Bcrypt -> Password -> PasswordHash Bcrypt
-- | Generate a random 16-byte bcrypt salt
newSalt :: MonadIO m => m (Salt Bcrypt)
-- | A salt used by a hashing algorithm.
newtype Salt a
Salt :: ByteString -> Salt a
[getSalt] :: Salt a -> ByteString
-- | This is an unsafe function that shows a password in plain-text.
--
--
-- >>> 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.
unsafeShowPassword :: Password -> Text
-- |
-- >>> hashPassword $ mkPassword "foobar"
-- PasswordHash {unPasswordHash = "$argon2id$v=19$m=65536,t=2,p=1$...$..."}
--
hashPassword :: MonadIO m => Password -> m (PasswordHash Argon2)
-- | A hashed password.
--
-- This represents a password that has been put through a hashing
-- function. The hashed password can be stored in a database.
newtype PasswordHash a
PasswordHash :: Text -> PasswordHash a
[unPasswordHash] :: PasswordHash a -> Text
-- | Check a Password against a PasswordHash Argon2.
--
-- Returns PasswordCheckSuccess on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> checkPassword pass passHash -- PasswordCheckSuccess ---- -- Returns PasswordCheckFail if an incorrect Password or -- PasswordHash Argon2 is used. -- --
-- >>> let badpass = mkPassword "incorrect-password" -- -- >>> checkPassword badpass passHash -- PasswordCheckFail ---- -- This should always fail if an incorrect password is given. -- --
-- \(Blind badpass) -> let correctPasswordHash = hashPasswordWithSalt testParams salt "foobar" in checkPassword badpass correctPasswordHash == PasswordCheckFail --checkPassword :: Password -> PasswordHash Argon2 -> PasswordCheck -- | The result of checking a password against a hashed version. This is -- returned by the checkPassword functions. data PasswordCheck -- | The password check was successful. The plain-text password matches the -- hashed password. PasswordCheckSuccess :: PasswordCheck -- | The password check failed. The plain-text password does not match the -- hashed password. PasswordCheckFail :: PasswordCheck -- | Hash a password using the Argon2 algorithm with the given -- Argon2Params. -- -- N.B.: If you have any doubt in your knowledge of cryptography -- and/or the Argon2 algorithm, please just use -- hashPassword. -- -- Advice to set the parameters: -- --
-- >>> defaultParams
-- Argon2Params {argon2Salt = 16, argon2Variant = Argon2id, argon2Version = Version13, argon2MemoryCost = 65536, argon2TimeCost = 2, argon2Parallelism = 1, argon2OutputLength = 32}
--
defaultParams :: Argon2Params
-- | Extracts Argon2Params from a PasswordHash Argon2.
--
-- Returns 'Just Argon2Params' on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> extractParams passHash == Just defaultParams -- True --extractParams :: PasswordHash Argon2 -> Maybe Argon2Params -- | Parameters used in the Argon2 hashing algorithm. data Argon2Params Argon2Params :: Word32 -> Variant -> Version -> Word32 -> Word32 -> Word32 -> Word32 -> Argon2Params -- | Bytes to randomly generate as a unique salt, default is 16 -- -- Limits are min: 8, and max: (2 ^ 32) - 1 [argon2Salt] :: Argon2Params -> Word32 -- | Which variant of Argon2 to use, default is Argon2id [argon2Variant] :: Argon2Params -> Variant -- | Which version of Argon2 to use, default is Version13 [argon2Version] :: Argon2Params -> Version -- | Memory cost, given in kibibytes, default is 65536 (i.e. -- 64MB) -- -- Limits are min: 8 * argon2Parallelism, and max is -- addressing space / 2, or (2 ^ 32) - 1, whichever is lower. [argon2MemoryCost] :: Argon2Params -> Word32 -- | Amount of computation realized, default is 2 -- -- Limits are min: 1, and max: (2 ^ 32) - 1 [argon2TimeCost] :: Argon2Params -> Word32 -- | Parallelism factor, default is 1 -- -- Limits are min: 1, and max: (2 ^ 24) - 1 [argon2Parallelism] :: Argon2Params -> Word32 -- | Output key length in bytes, default is 32 -- -- Limits are min: 4, and max: (2 ^ 32) - 1 [argon2OutputLength] :: Argon2Params -> Word32 -- | Which variant of Argon2 to use. You should choose the variant that is -- most applicable to your intention to hash inputs. data Variant -- | Argon2d is faster than Argon2i and uses data-depending memory access, -- which makes it suitable for cryptocurrencies and applications with no -- threats from side-channel timing attacks. Argon2d :: Variant -- | Argon2i uses data-independent memory access, which is preferred for -- password hashing and password-based key derivation. Argon2i is slower -- as it makes more passes over the memory to protect from tradeoff -- attacks. Argon2i :: Variant -- | Argon2id is a hybrid of Argon2i and Argon2d, using a combination of -- data-depending and data-independent memory accesses, which gives some -- of Argon2i's resistance to side-channel cache timing attacks and much -- of Argon2d's resistance to GPU cracking attacks Argon2id :: Variant -- | Which version of Argon2 to use data Version Version10 :: Version Version13 :: Version -- | Hash a password with the given Argon2Params and also with the -- given Salt instead of a random generated salt using -- argon2Salt from Argon2Params. (cf. -- hashPasswordWithParams) 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 8 bytes or more, or this function will -- throw an error! -- --
-- >>> let salt = Salt "abcdefghijklmnop"
--
-- >>> hashPasswordWithSalt defaultParams salt (mkPassword "foobar")
-- PasswordHash {unPasswordHash = "$argon2id$v=19$m=65536,t=2,p=1$YWJjZGVmZ2hpamtsbW5vcA$BztdyfEefG5V18ZNlztPrfZaU5duVFKZiI6dJeWht0o"}
--
--
-- (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 generates a new Salt
-- everytime it is called.)
hashPasswordWithSalt :: Argon2Params -> Salt Argon2 -> Password -> PasswordHash Argon2
-- | Generate a random 16-byte Argon2 salt
newSalt :: MonadIO m => m (Salt Argon2)
-- | A salt used by a hashing algorithm.
newtype Salt a
Salt :: ByteString -> Salt a
[getSalt] :: Salt a -> ByteString
-- | This is an unsafe function that shows a password in plain-text.
--
--
-- >>> 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.
unsafeShowPassword :: Password -> Text
instance GHC.Show.Show Data.Password.Argon2.Argon2Params
instance GHC.Classes.Eq Data.Password.Argon2.Argon2Params
-- |
-- >>> hashPassword $ mkPassword "foobar"
-- PasswordHash {unPasswordHash = "sha512:25000:...:..."}
--
hashPassword :: MonadIO m => Password -> m (PasswordHash PBKDF2)
-- | A hashed password.
--
-- This represents a password that has been put through a hashing
-- function. The hashed password can be stored in a database.
newtype PasswordHash a
PasswordHash :: Text -> PasswordHash a
[unPasswordHash] :: PasswordHash a -> Text
-- | Check a Password against a PasswordHash PBKDF2.
--
-- Returns PasswordCheckSuccess on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> checkPassword pass passHash -- PasswordCheckSuccess ---- -- Returns PasswordCheckFail if an incorrect Password or -- PasswordHash PBKDF2 is used. -- --
-- >>> let badpass = mkPassword "incorrect-password" -- -- >>> checkPassword badpass passHash -- PasswordCheckFail ---- -- This should always fail if an incorrect password is given. -- --
-- \(Blind badpass) -> let correctPasswordHash = hashPasswordWithSalt testParams salt "foobar" in checkPassword badpass correctPasswordHash == PasswordCheckFail --checkPassword :: Password -> PasswordHash PBKDF2 -> PasswordCheck -- | The result of checking a password against a hashed version. This is -- returned by the checkPassword functions. data PasswordCheck -- | The password check was successful. The plain-text password matches the -- hashed password. PasswordCheckSuccess :: PasswordCheck -- | The password check failed. The plain-text password does not match the -- hashed password. PasswordCheckFail :: PasswordCheck -- | Hash a password using the PBKDF2 algorithm with the given -- PBKDF2Params. -- -- N.B.: If you have any doubt in your knowledge of cryptography -- and/or the PBKDF2 algorithm, please just use -- hashPassword. hashPasswordWithParams :: MonadIO m => PBKDF2Params -> Password -> m (PasswordHash PBKDF2) -- | Default parameters for the PBKDF2 algorithm. -- --
-- >>> defaultParams
-- PBKDF2Params {pbkdf2Salt = 16, pbkdf2Algorithm = PBKDF2_SHA512, pbkdf2Iterations = 25000, pbkdf2OutputLength = 64}
--
defaultParams :: PBKDF2Params
-- | Extracts PBKDF2Params from a PasswordHash PBKDF2.
--
-- Returns 'Just PBKDF2Params' on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> extractParams passHash == Just defaultParams -- True --extractParams :: PasswordHash PBKDF2 -> Maybe PBKDF2Params -- | Parameters used in the PBKDF2 hashing algorithm. data PBKDF2Params PBKDF2Params :: Word32 -> PBKDF2Algorithm -> Word32 -> Word32 -> PBKDF2Params -- | Bytes to randomly generate as a unique salt, default is 16 [pbkdf2Salt] :: PBKDF2Params -> Word32 -- | Which algorithm to use for hashing, default is -- PBKDF2_SHA512 [pbkdf2Algorithm] :: PBKDF2Params -> PBKDF2Algorithm -- | Rounds to hash, default is 25,000 [pbkdf2Iterations] :: PBKDF2Params -> Word32 -- | Output key length in bytes, default is 64 -- -- Limits are min: 1, max: the amount of entropy of the hashing -- algorithm. This is limited automatically to 16, 20, 32, 64 -- for MD5, SHA1, SHA256, SHA512, respectively. [pbkdf2OutputLength] :: PBKDF2Params -> Word32 -- | Type of algorithm to use for hashing PBKDF2 passwords. -- -- N.B.: PBKDF2_MD5 and PBKDF2_SHA1 are not considered very -- secure. data PBKDF2Algorithm PBKDF2_MD5 :: PBKDF2Algorithm PBKDF2_SHA1 :: PBKDF2Algorithm PBKDF2_SHA256 :: PBKDF2Algorithm PBKDF2_SHA512 :: PBKDF2Algorithm -- | Hash a password with the given PBKDF2Params and also with the -- given Salt instead of a randomly generated salt using -- pbkdf2Salt from PBKDF2Params. (cf. -- hashPasswordWithParams) Using hashPasswordWithSalt is -- strongly disadvised and hashPasswordWithParams should be -- used instead. Never use a static salt in production -- applications! -- --
-- >>> let salt = Salt "abcdefghijklmnop"
--
-- >>> hashPasswordWithSalt defaultParams salt (mkPassword "foobar")
-- PasswordHash {unPasswordHash = "sha512:25000:YWJjZGVmZ2hpamtsbW5vcA==:JRElYYrOMe9OIV4LDxaLTgO9ho8fFBVofXoQcdngi7AcuH6Amvmlj2B0y6y1UtQciXXBepSCS+rpy8/vDDQvoA=="}
--
--
-- (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.)
hashPasswordWithSalt :: PBKDF2Params -> Salt PBKDF2 -> Password -> PasswordHash PBKDF2
-- | Generate a random 16-byte PBKDF2 salt
newSalt :: MonadIO m => m (Salt PBKDF2)
-- | A salt used by a hashing algorithm.
newtype Salt a
Salt :: ByteString -> Salt a
[getSalt] :: Salt a -> ByteString
-- | This is an unsafe function that shows a password in plain-text.
--
--
-- >>> 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.
unsafeShowPassword :: Password -> Text
instance GHC.Show.Show Data.Password.PBKDF2.PBKDF2Algorithm
instance GHC.Classes.Eq Data.Password.PBKDF2.PBKDF2Algorithm
instance GHC.Show.Show Data.Password.PBKDF2.PBKDF2Params
instance GHC.Classes.Eq Data.Password.PBKDF2.PBKDF2Params
-- |
-- >>> hashPassword $ mkPassword "foobar"
-- PasswordHash {unPasswordHash = "14|8|1|...|..."}
--
hashPassword :: MonadIO m => Password -> m (PasswordHash Scrypt)
-- | A hashed password.
--
-- This represents a password that has been put through a hashing
-- function. The hashed password can be stored in a database.
newtype PasswordHash a
PasswordHash :: Text -> PasswordHash a
[unPasswordHash] :: PasswordHash a -> Text
-- | Check a Password against a PasswordHash Scrypt.
--
-- Returns PasswordCheckSuccess on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> checkPassword pass passHash -- PasswordCheckSuccess ---- -- Returns PasswordCheckFail if an incorrect Password or -- PasswordHash Scrypt is used. -- --
-- >>> let badpass = mkPassword "incorrect-password" -- -- >>> checkPassword badpass passHash -- PasswordCheckFail ---- -- This should always fail if an incorrect password is given. -- --
-- \(Blind badpass) -> let correctPasswordHash = hashPasswordWithSalt testParams salt "foobar" in checkPassword badpass correctPasswordHash == PasswordCheckFail --checkPassword :: Password -> PasswordHash Scrypt -> PasswordCheck -- | The result of checking a password against a hashed version. This is -- returned by the checkPassword functions. data PasswordCheck -- | The password check was successful. The plain-text password matches the -- hashed password. PasswordCheckSuccess :: PasswordCheck -- | The password check failed. The plain-text password does not match the -- hashed password. PasswordCheckFail :: PasswordCheck -- | Hash a password using the Scrypt algorithm with the given -- ScryptParams. -- -- N.B.: If you have any doubt in your knowledge of cryptography -- and/or the Scrypt algorithm, please just use -- hashPassword. -- -- Advice for setting the parameters: -- --
-- >>> defaultParams
-- ScryptParams {scryptSalt = 32, scryptRounds = 14, scryptBlockSize = 8, scryptParallelism = 1, scryptOutputLength = 64}
--
defaultParams :: ScryptParams
-- | Extracts ScryptParams from a PasswordHash Scrypt.
--
-- Returns 'Just ScryptParams' on success.
--
-- -- >>> let pass = mkPassword "foobar" -- -- >>> passHash <- hashPassword pass -- -- >>> extractParams passHash == Just defaultParams -- True --extractParams :: PasswordHash Scrypt -> Maybe ScryptParams -- | Parameters used in the Scrypt hashing algorithm. data ScryptParams ScryptParams :: Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> ScryptParams -- | Bytes to randomly generate as a unique salt, default is 32 [scryptSalt] :: ScryptParams -> Word32 -- | log2(N) rounds to hash, default is 14 (i.e. 2^14 rounds) [scryptRounds] :: ScryptParams -> Word32 -- | Block size, default is 8 -- -- Limits are min: 1, and max: scryptBlockSize * -- scryptParallelism < 2 ^ 30 [scryptBlockSize] :: ScryptParams -> Word32 -- | Parallelism factor, default is 1 -- -- Limits are min: 0, and max: scryptBlockSize * -- scryptParallelism < 2 ^ 30 [scryptParallelism] :: ScryptParams -> Word32 -- | Output key length in bytes, default is 64 [scryptOutputLength] :: ScryptParams -> Word32 -- | Hash a password with the given ScryptParams and also with the -- given Salt instead of a randomly generated salt using -- scryptSalt from ScryptParams. Using -- hashPasswordWithSalt is strongly disadvised and -- hashPasswordWithParams should be used instead. Never use a -- static salt in production applications! -- -- The resulting PasswordHash has the parameters used to hash it, -- as well as the Salt appended to it, separated by |. -- -- The input Salt and resulting PasswordHash are both -- base64 encoded. -- --
-- >>> let salt = Salt "abcdefghijklmnopqrstuvwxyz012345"
--
-- >>> hashPasswordWithSalt defaultParams salt (mkPassword "foobar")
-- PasswordHash {unPasswordHash = "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
-- hashPassword. hashPassword generates a new Salt
-- everytime it is called.)
hashPasswordWithSalt :: ScryptParams -> Salt Scrypt -> Password -> PasswordHash Scrypt
-- | Generate a random 32-byte scrypt salt
newSalt :: MonadIO m => m (Salt Scrypt)
-- | A salt used by a hashing algorithm.
newtype Salt a
Salt :: ByteString -> Salt a
[getSalt] :: Salt a -> ByteString
-- | This is an unsafe function that shows a password in plain-text.
--
--
-- >>> 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.
unsafeShowPassword :: Password -> Text
instance GHC.Show.Show Data.Password.Scrypt.ScryptParams
instance GHC.Classes.Eq Data.Password.Scrypt.ScryptParams
-- | -- myValidateFunc :: Password -> Bool -- myValidateFunc = isValidPassword defaultPasswordPolicy_ ---- --
-- customPolicy :: PasswordPolicy
-- customPolicy =
-- defaultPasswordPolicy
-- { minimumLength = 12
-- , specialChars = 1
-- }
--
--
-- This custom policy will then have to be validated first, so it can be
-- used to validate Passwords further on.
--
-- -- customValidPolicy :: ValidPasswordPolicy -- customValidPolicy = $(validatePasswordPolicyTH customPolicy) ---- -- NB: any custom CharSetPredicate will be ignored by -- validatePasswordPolicyTH and replaced with the -- defaultCharSetPredicate. So if you want to use your own -- CharSetPredicate, you won't be able to validate your policy -- using validatePasswordPolicyTH. Most users, however, will find -- defaultCharSetPredicate to be sufficient. -- --
-- main :: IO () -- main = -- case (validatePasswordPolicy customPolicy) of -- Left reasons -> error $ show reasons -- Right validPolicy -> app `runReaderT` validPolicy -- -- customValidateFunc :: Password -> ReaderT ValidPasswordPolicy IO Bool -- customValidateFunc pwd = do -- policy <- ask -- return $ isValidPassword policy pwd ---- --
-- Right validPolicy = validatePasswordPolicy customPolicy -- -- customValidateFunc :: Password -> Bool -- customValidateFunc = isValidPassword validPolicy --module Data.Password.Validate -- | Checks if a given Password adheres to the provided -- ValidPasswordPolicy. -- -- In case of an invalid password, returns the reasons why it wasn't -- valid. -- --
-- >>> let pass = mkPassword "This_Is_Valid_Password1234" -- -- >>> validatePassword defaultPasswordPolicy_ pass -- ValidPassword --validatePassword :: ValidPasswordPolicy -> Password -> ValidationResult -- | This function is equivalent to: -- --
-- validatePassword policy password == ValidPassword ---- --
-- >>> let pass = mkPassword "This_Is_Valid_PassWord1234" -- -- >>> isValidPassword defaultPasswordPolicy_ pass -- True --isValidPassword :: ValidPasswordPolicy -> Password -> Bool -- | Result of validating a Password. data ValidationResult ValidPassword :: ValidationResult InvalidPassword :: [InvalidReason] -> ValidationResult -- | Verifies that a PasswordPolicy is valid and converts it into a -- ValidPasswordPolicy. -- --
-- >>> validatePasswordPolicy defaultPasswordPolicy -- Right (...) --validatePasswordPolicy :: PasswordPolicy -> Either [InvalidPolicyReason] ValidPasswordPolicy -- | Template Haskell validation function for PasswordPolicys. -- --
-- {-# LANGUAGE TemplateHaskell #-}
-- myPolicy :: PasswordPolicy
-- myPolicy = defaultPasswordPolicy{ specialChars = 1 }
--
-- myValidPolicy :: ValidPasswordPolicy
-- myValidPolicy = $(validatePasswordPolicyTH myPolicy)
--
--
-- For technical reasons, the charSetPredicate field is ignored
-- and the defaultCharSetPredicate is used. If, for any reason,
-- you do need to use a custom CharSetPredicate, please use
-- validatePasswordPolicy and either handle the failure case at
-- runtime and/or use a unit test to make sure your policy is valid.
validatePasswordPolicyTH :: PasswordPolicy -> Q Exp
-- | Set of policies used to validate a Password.
--
-- When defining your own PasswordPolicy, please keep in mind
-- that:
--
--
-- myPolicy = defaultPasswordPolicy{ minimumLength = 12 }
--
--
-- Do note that this being a default policy doesn't make it a good
-- enough policy in every situation. The most important field,
-- minimumLength, has 8 characters as the default, because
-- it is the bare minimum for some sense of security. The longer
-- the password, the more difficult it will be to guess or
-- brute-force, so a minimum of 12 or 16 would be advised in a
-- production setting.
--
-- This policy on it's own is guaranteed to be valid. Any changes made to
-- it might result in validatePasswordPolicy returning one or more
-- InvalidPolicyReasons.
--
--
-- >>> defaultPasswordPolicy
-- PasswordPolicy {minimumLength = 8, maximumLength = 64, uppercaseChars = 0, lowercaseChars = 0, specialChars = 0, digitChars = 0, charSetPredicate = <FUNCTION>}
--
defaultPasswordPolicy :: PasswordPolicy
-- | Unchangeable defaultPasswordPolicy, but guaranteed to be valid.
defaultPasswordPolicy_ :: ValidPasswordPolicy
-- | Predicate which defines the characters that can be used for a
-- password.
newtype CharSetPredicate
CharSetPredicate :: (Char -> Bool) -> CharSetPredicate
[getCharSetPredicate] :: CharSetPredicate -> Char -> Bool
-- | The default character set consists of uppercase and lowercase letters,
-- numbers, and special characters from the ASCII character set.
-- (i.e. everything from the ASCII set except the control
-- characters)
defaultCharSetPredicate :: CharSetPredicate
-- | Possible reasons for a Password to be invalid.
data InvalidReason
-- | Length of Password is too short.
PasswordTooShort :: !MinimumLength -> !ProvidedLength -> InvalidReason
-- | Length of Password is too long.
PasswordTooLong :: !MaximumLength -> !ProvidedLength -> InvalidReason
-- | Password does not contain required number of characters.
NotEnoughReqChars :: !CharacterCategory -> !MinimumAmount -> !ProvidedAmount -> InvalidReason
-- | Password contains characters that cannot be used
InvalidCharacters :: !Text -> InvalidReason
-- | Possible reasons for a PasswordPolicy to be invalid
data InvalidPolicyReason
-- | Value of minimumLength is bigger than maximumLength
--
-- -- InvalidLength minimumLength maximumLength --InvalidLength :: !MinimumLength -> !MaximumLength -> InvalidPolicyReason -- | Value of maximumLength is zero or less -- --
-- MaxLengthBelowZero maximumLength --MaxLengthBelowZero :: !MaximumLength -> InvalidPolicyReason -- | The total of the character category amount requirements are higher -- than the maximum length of the password. (i.e. the Int -- signifies the total of lowercaseChars + uppercaseChars + -- digitChars + specialChars) -- --
-- CategoryAmountsAboveMaxLength maximumLength totalRequiredChars --CategoryAmountsAboveMaxLength :: !MaximumLength -> !Int -> InvalidPolicyReason -- | charSetPredicate does not return True for a -- CharacterCategory that requires at least MinimumAmount -- characters in the password InvalidCharSetPredicate :: !CharacterCategory -> !MinimumAmount -> InvalidPolicyReason -- | Character categories data CharacterCategory -- | Uppercase letters Uppercase :: CharacterCategory -- | Lowercase letters Lowercase :: CharacterCategory -- | Special characters Special :: CharacterCategory -- | ASCII digits Digit :: CharacterCategory type MinimumLength = Int type MaximumLength = Int type ProvidedLength = Int type MinimumAmount = Int type ProvidedAmount = Int -- | Default character set -- -- Should be all non-control characters in the ASCII character set. defaultCharSet :: String -- | Validate CharSetPredicate to return True on at least one -- of the characters that is required. -- -- For instance, if PasswordPolicy states that the password -- requires at least one uppercase letter, then CharSetPredicate -- should return True on at least one uppercase letter. validateCharSetPredicate :: PasswordPolicy -> [InvalidPolicyReason] -- | Convert a CharacterCategory into its associated predicate -- function categoryToPredicate :: CharacterCategory -> Char -> Bool -- | Check if given Char is a special character. (i.e. any -- non-alphanumeric non-control ASCII character) isSpecial :: Char -> Bool -- | All Int fields of the PasswordPolicy in a row allButCSP :: PasswordPolicy -> [Int] instance GHC.Show.Show Data.Password.Validate.ValidPasswordPolicy instance GHC.Classes.Ord Data.Password.Validate.ValidPasswordPolicy instance GHC.Classes.Eq Data.Password.Validate.ValidPasswordPolicy instance GHC.Show.Show Data.Password.Validate.CharacterCategory instance GHC.Classes.Ord Data.Password.Validate.CharacterCategory instance GHC.Classes.Eq Data.Password.Validate.CharacterCategory instance GHC.Show.Show Data.Password.Validate.InvalidReason instance GHC.Classes.Ord Data.Password.Validate.InvalidReason instance GHC.Classes.Eq Data.Password.Validate.InvalidReason instance GHC.Show.Show Data.Password.Validate.InvalidPolicyReason instance GHC.Classes.Ord Data.Password.Validate.InvalidPolicyReason instance GHC.Classes.Eq Data.Password.Validate.InvalidPolicyReason instance GHC.Show.Show Data.Password.Validate.ValidationResult instance GHC.Classes.Eq Data.Password.Validate.ValidationResult instance GHC.Classes.Eq Data.Password.Validate.PasswordPolicy instance GHC.Classes.Ord Data.Password.Validate.PasswordPolicy instance GHC.Show.Show Data.Password.Validate.PasswordPolicy