-- |
-- Module      : Crypto.Saltine.Core.Password
-- Description : Argon2 password hash
-- Copyright   : (c) Promethea Raschke 2018
--                   Max Amanshauser 2021
-- License     : MIT
-- Maintainer  : max@lambdalifting.org
-- Stability   : experimental
-- Portability : non-portable
--
-- Password hashing and key derivation
--
-- When in doubt, just use one of [ interactivePolicy, moderatePolicy, sensitivePolicy ],
-- but this module also allows you to fine-tune parameters for specific circumstances.
--
-- This module uses the @Text@ type for passwords, because this seems to be the only
-- reasonable way to get consistent encodings across locales and architectures, short of
-- letting users mess around with ByteStrings themselves.

module Crypto.Saltine.Core.Password
  ( Salt
  , newSalt

  , needsRehash

  , pwhashStr
  , pwhashStrVerify
  , pwhash

  , Policy(..)
  , interactivePolicy
  , moderatePolicy
  , sensitivePolicy

  , Opslimit
  , opslimit
  , getOpslimit

  , minOpslimit
  , maxOpslimit

  , opslimitInteractive
  , opslimitModerate
  , opslimitSensitive

  , Memlimit
  , memlimit
  , getMemlimit

  , minMemlimit
  , maxMemlimit

  , memlimitInteractive
  , memlimitModerate
  , memlimitSensitive

  , Algorithm
  , defaultAlgorithm
  ) where

import Crypto.Saltine.Internal.Util
import Crypto.Saltine.Internal.Password as I
import Data.ByteString (ByteString)
import Data.Text       (Text)
import Foreign.C
import System.IO.Unsafe

import qualified Crypto.Saltine.Internal.Password as Bytes
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE


newSalt :: IO Salt
newSalt :: IO Salt
newSalt = ByteString -> Salt
Salt (ByteString -> Salt) -> IO ByteString -> IO Salt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> IO ByteString
randomByteString Int
Bytes.pwhash_saltbytes

-- | Hashes a password according to the policy
-- This function is non-deterministic and hence in IO.
-- Since this function may cause a huge amount of memory to be allocated, it will return
-- Nothing if the allocation failed and on any other error.
pwhashStr :: Text -> Policy -> IO (Maybe PasswordHash)
pwhashStr :: Text -> Policy -> IO (Maybe PasswordHash)
pwhashStr Text
pw Policy
policy = do
  let (CULLong
ops, CSize
mem, CInt
_alg) = Policy -> (CULLong, CSize, CInt)
unpackPolicy Policy
policy

  -- Hash is always ASCII, so no decoding needed
  (Maybe String -> Maybe PasswordHash)
-> IO (Maybe String) -> IO (Maybe PasswordHash)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((String -> PasswordHash) -> Maybe String -> Maybe PasswordHash
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> PasswordHash
PasswordHash (Text -> PasswordHash)
-> (String -> Text) -> String -> PasswordHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack)) (IO (Maybe String) -> IO (Maybe PasswordHash))
-> IO (Maybe String) -> IO (Maybe PasswordHash)
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr CChar -> IO (Maybe String)) -> IO (Maybe String)
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
pwhash_strbytes ((Ptr CChar -> IO (Maybe String)) -> IO (Maybe String))
-> (Ptr CChar -> IO (Maybe String)) -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
pp ->
    [ByteString]
-> ([CStringLen] -> IO (Maybe String)) -> IO (Maybe String)
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [Text -> ByteString
TE.encodeUtf8 Text
pw] (([CStringLen] -> IO (Maybe String)) -> IO (Maybe String))
-> ([CStringLen] -> IO (Maybe String)) -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ \ [(Ptr CChar
ppw, Int
ppwlen)] -> do
          CInt
ret <- Ptr CChar -> Ptr CChar -> CULLong -> CULLong -> CSize -> IO CInt
c_pwhash_str Ptr CChar
pp Ptr CChar
ppw (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ppwlen) (CULLong -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral CULLong
ops) (CSize -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
mem)

          case CInt
ret of
              CInt
0 -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> IO String -> IO (Maybe String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CChar -> IO String
peekCAString Ptr CChar
pp
              CInt
_ -> Maybe String -> IO (Maybe String)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe String
forall a. Maybe a
Nothing

-- | Verifies that a certain password hash was constructed from the supplied password
pwhashStrVerify :: PasswordHash -> Text -> Bool
pwhashStrVerify :: PasswordHash -> Text -> Bool
pwhashStrVerify (PasswordHash Text
h) Text
pw = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
  [ByteString] -> ([CStringLen] -> IO Bool) -> IO Bool
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [Text -> ByteString
TE.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ Text -> Char -> Text
T.snoc Text
h Char
'\NUL', Text -> ByteString
TE.encodeUtf8 Text
pw] (([CStringLen] -> IO Bool) -> IO Bool)
-> ([CStringLen] -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \[(Ptr CChar
ph, Int
_), (Ptr CChar
ppw, Int
ppwlen)] -> do
    CInt
res <- Ptr CChar -> Ptr CChar -> CULLong -> IO CInt
c_pwhash_str_verify Ptr CChar
ph Ptr CChar
ppw (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ppwlen)
    Bool -> IO Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0)

-- | Indicates whether a password needs to be rehashed, because the opslimit/memlimit parameters
-- used to hash the password are inconsistent with the supplied values.
-- Returns Nothing if the hash appears to be invalid.
-- Internally this function will always use the current DefaultAlgorithm and hence will give
-- undefined results if a different algorithm was used to hash the password.
needsRehash :: Opslimit -> Memlimit -> PasswordHash -> Maybe Bool
needsRehash :: Opslimit -> Memlimit -> PasswordHash -> Maybe Bool
needsRehash (Opslimit Int
ops) (Memlimit Int
mem) (PasswordHash Text
h) =
    IO (Maybe Bool) -> Maybe Bool
forall a. IO a -> a
unsafePerformIO (IO (Maybe Bool) -> Maybe Bool) -> IO (Maybe Bool) -> Maybe Bool
forall a b. (a -> b) -> a -> b
$
        [ByteString]
-> ([CStringLen] -> IO (Maybe Bool)) -> IO (Maybe Bool)
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [Text -> ByteString
TE.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ Text -> Char -> Text
T.snoc Text
h Char
'\NUL'] (([CStringLen] -> IO (Maybe Bool)) -> IO (Maybe Bool))
-> ([CStringLen] -> IO (Maybe Bool)) -> IO (Maybe Bool)
forall a b. (a -> b) -> a -> b
$ \[(Ptr CChar
ph,Int
_)] -> do
            CInt
res <- Ptr CChar -> CULLong -> CSize -> IO CInt
c_pwhash_str_needs_rehash Ptr CChar
ph (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ops) (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
mem)
            Maybe Bool -> IO (Maybe Bool)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Bool -> IO (Maybe Bool)) -> Maybe Bool -> IO (Maybe Bool)
forall a b. (a -> b) -> a -> b
$  if CInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== -CInt
1
                    then Maybe Bool
forall a. Maybe a
Nothing
                    else Bool -> Maybe Bool
forall a. a -> Maybe a
Just (CInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1)

-- | Derives a key of the specified length from a password using a salt according to the provided policy.
-- Since this function may cause a huge amount of memory to be allocated, it will return
-- Nothing if the allocation failed and on any other error.
pwhash :: Text -> Int -> Salt -> Policy -> Maybe ByteString
pwhash :: Text -> Int -> Salt -> Policy -> Maybe ByteString
pwhash Text
pw Int
len (Salt ByteString
salt) Policy
policy = do
  let (CULLong
ops, CSize
mem, CInt
alg) = Policy -> (CULLong, CSize, CInt)
unpackPolicy Policy
policy

  let (CInt
e, ByteString
hashed) =
        Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
len ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
hbuf ->
          [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [Text -> ByteString
TE.encodeUtf8 Text
pw, ByteString
salt] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(Ptr CChar
ppw,Int
ppwlen), (Ptr CChar
psalt,Int
_)] ->
              Ptr CChar
-> CULLong
-> Ptr CChar
-> CULLong
-> Ptr CChar
-> CULLong
-> CSize
-> CInt
-> IO CInt
c_pwhash
                    Ptr CChar
hbuf (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
                    Ptr CChar
ppw (Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ppwlen)
                    Ptr CChar
psalt
                    (CULLong -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral CULLong
ops)
                    (CSize -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
mem)
                    (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CInt) -> Int -> CInt
forall a b. (a -> b) -> a -> b
$ CInt -> Int
forall a. Enum a => a -> Int
fromEnum CInt
alg)

  if CInt
e CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== -CInt
1
  then Maybe ByteString
forall a. Maybe a
Nothing
  else ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
hashed


-- | Smart constructor for opslimit
opslimit :: Algorithm -> Int -> Maybe Opslimit
opslimit :: Algorithm -> Int -> Maybe Opslimit
opslimit Algorithm
alg Int
x
  | Int -> Opslimit
Opslimit Int
x Opslimit -> Opslimit -> Bool
forall a. Ord a => a -> a -> Bool
< Algorithm -> Opslimit
minOpslimit Algorithm
alg = Maybe Opslimit
forall a. Maybe a
Nothing
  | Int -> Opslimit
Opslimit Int
x Opslimit -> Opslimit -> Bool
forall a. Ord a => a -> a -> Bool
> Algorithm -> Opslimit
maxOpslimit Algorithm
alg = Maybe Opslimit
forall a. Maybe a
Nothing
  | Bool
otherwise = Opslimit -> Maybe Opslimit
forall a. a -> Maybe a
Just (Int -> Opslimit
Opslimit Int
x)

opslimitInteractive :: Algorithm -> Opslimit
opslimitInteractive :: Algorithm -> Opslimit
opslimitInteractive Algorithm
DefaultAlgorithm = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_opslimit_interactive)
opslimitInteractive Algorithm
Argon2i13        = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_opslimit_interactive)
opslimitInteractive Algorithm
Argon2id13       = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_opslimit_interactive)

opslimitModerate :: Algorithm -> Opslimit
opslimitModerate :: Algorithm -> Opslimit
opslimitModerate Algorithm
DefaultAlgorithm   = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_opslimit_moderate)
opslimitModerate Algorithm
Argon2i13          = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_opslimit_moderate)
opslimitModerate Algorithm
Argon2id13         = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_opslimit_moderate)

opslimitSensitive :: Algorithm -> Opslimit
opslimitSensitive :: Algorithm -> Opslimit
opslimitSensitive Algorithm
DefaultAlgorithm  = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_opslimit_sensitive)
opslimitSensitive Algorithm
Argon2i13         = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_opslimit_sensitive)
opslimitSensitive Algorithm
Argon2id13        = Int -> Opslimit
Opslimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_opslimit_sensitive)


-- | Smart constructor for memlimit
memlimit :: Algorithm -> Int -> Maybe Memlimit
memlimit :: Algorithm -> Int -> Maybe Memlimit
memlimit Algorithm
alg Int
x
  | Int -> Memlimit
Memlimit Int
x Memlimit -> Memlimit -> Bool
forall a. Ord a => a -> a -> Bool
< Algorithm -> Memlimit
minMemlimit Algorithm
alg  = Maybe Memlimit
forall a. Maybe a
Nothing
  | Int -> Memlimit
Memlimit Int
x Memlimit -> Memlimit -> Bool
forall a. Ord a => a -> a -> Bool
> Algorithm -> Memlimit
maxMemlimit Algorithm
alg= Maybe Memlimit
forall a. Maybe a
Nothing
  | Bool
otherwise = Memlimit -> Maybe Memlimit
forall a. a -> Maybe a
Just (Int -> Memlimit
Memlimit Int
x)

memlimitInteractive :: Algorithm -> Memlimit
memlimitInteractive :: Algorithm -> Memlimit
memlimitInteractive Algorithm
DefaultAlgorithm = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_memlimit_interactive)
memlimitInteractive Algorithm
Argon2i13        = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_memlimit_interactive)
memlimitInteractive Algorithm
Argon2id13       = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_memlimit_interactive)

memlimitModerate :: Algorithm -> Memlimit
memlimitModerate :: Algorithm -> Memlimit
memlimitModerate Algorithm
DefaultAlgorithm   = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_memlimit_moderate)
memlimitModerate Algorithm
Argon2i13          = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_memlimit_moderate)
memlimitModerate Algorithm
Argon2id13         = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_memlimit_moderate)

memlimitSensitive :: Algorithm -> Memlimit
memlimitSensitive :: Algorithm -> Memlimit
memlimitSensitive Algorithm
DefaultAlgorithm  = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_memlimit_sensitive)
memlimitSensitive Algorithm
Argon2i13         = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_memlimit_sensitive)
memlimitSensitive Algorithm
Argon2id13        = Int -> Memlimit
Memlimit (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_memlimit_sensitive)

defaultAlgorithm :: Algorithm
defaultAlgorithm :: Algorithm
defaultAlgorithm = Algorithm
DefaultAlgorithm


-- | Get raw C types from a policy, suitable for passing to FFI functions
unpackPolicy :: Policy -> (CULLong, CSize, CInt)
unpackPolicy :: Policy -> (CULLong, CSize, CInt)
unpackPolicy (Policy Opslimit
ops Memlimit
mem Algorithm
alg) =
  ( Int -> CULLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Opslimit -> Int
getOpslimit Opslimit
ops)
  , Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Memlimit -> Int
getMemlimit Memlimit
mem)
  , Algorithm -> CInt
algorithm Algorithm
alg
  )


{-
Fast policy suitable for low-powered devices

Takes approximately 0.1 seconds on a typical desktop computer
and requires 64 MiB of dedicated RAM
-}
interactivePolicy :: Policy
interactivePolicy :: Policy
interactivePolicy = Opslimit -> Memlimit -> Algorithm -> Policy
Policy (Algorithm -> Opslimit
opslimitInteractive Algorithm
defaultAlgorithm)
                           (Algorithm -> Memlimit
memlimitInteractive Algorithm
defaultAlgorithm)
                           Algorithm
defaultAlgorithm

{-|
Moderate policy with a balance of speed and security

Takes approximately 1 second on a typical desktop computer
and requires 256 MiB of dedicated RAM
-}
moderatePolicy :: Policy
moderatePolicy :: Policy
moderatePolicy = Opslimit -> Memlimit -> Algorithm -> Policy
Policy (Algorithm -> Opslimit
opslimitModerate Algorithm
defaultAlgorithm)
                        (Algorithm -> Memlimit
memlimitModerate Algorithm
defaultAlgorithm)
                        Algorithm
defaultAlgorithm

{-|
High-security policy designed to make attacking the password extremely expensive

Takes several seconds on a typical desktop computer
and requires 1024 MiB of dedicated RAM
-}
sensitivePolicy :: Policy
sensitivePolicy :: Policy
sensitivePolicy = Opslimit -> Memlimit -> Algorithm -> Policy
Policy (Algorithm -> Opslimit
opslimitSensitive Algorithm
defaultAlgorithm)
                         (Algorithm -> Memlimit
memlimitSensitive Algorithm
defaultAlgorithm)
                         Algorithm
defaultAlgorithm


minOpslimit :: Algorithm -> Opslimit
minOpslimit :: Algorithm -> Opslimit
minOpslimit Algorithm
DefaultAlgorithm = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_opslimit_min
minOpslimit Algorithm
Argon2i13        = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_opslimit_min
minOpslimit Algorithm
Argon2id13       = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_opslimit_min

maxOpslimit :: Algorithm -> Opslimit
maxOpslimit :: Algorithm -> Opslimit
maxOpslimit Algorithm
DefaultAlgorithm = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_opslimit_max
maxOpslimit Algorithm
Argon2i13        = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_opslimit_max
maxOpslimit Algorithm
Argon2id13       = Int -> Opslimit
Opslimit (Int -> Opslimit) -> Int -> Opslimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_opslimit_max

minMemlimit :: Algorithm -> Memlimit
minMemlimit :: Algorithm -> Memlimit
minMemlimit Algorithm
DefaultAlgorithm = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_memlimit_min
minMemlimit Algorithm
Argon2i13        = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_memlimit_min
minMemlimit Algorithm
Argon2id13       = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_memlimit_min

maxMemlimit :: Algorithm -> Memlimit
maxMemlimit :: Algorithm -> Memlimit
maxMemlimit Algorithm
DefaultAlgorithm = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_memlimit_max
maxMemlimit Algorithm
Argon2i13        = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2i_memlimit_max
maxMemlimit Algorithm
Argon2id13       = Int -> Memlimit
Memlimit (Int -> Memlimit) -> Int -> Memlimit
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
Bytes.pwhash_argon2id_memlimit_max