module Crypto.KDF.Argon2
(
Options(..)
, TimeCost
, MemoryCost
, Parallelism
, Variant(..)
, Version(..)
, defaultOptions
, hash
) where
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Error
import Control.Monad (when)
import Data.Word
import Foreign.C
import Foreign.Ptr
data Variant =
Argon2d
| Argon2i
| Argon2id
deriving (Variant -> Variant -> Bool
(Variant -> Variant -> Bool)
-> (Variant -> Variant -> Bool) -> Eq Variant
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Variant -> Variant -> Bool
== :: Variant -> Variant -> Bool
$c/= :: Variant -> Variant -> Bool
/= :: Variant -> Variant -> Bool
Eq,Eq Variant
Eq Variant =>
(Variant -> Variant -> Ordering)
-> (Variant -> Variant -> Bool)
-> (Variant -> Variant -> Bool)
-> (Variant -> Variant -> Bool)
-> (Variant -> Variant -> Bool)
-> (Variant -> Variant -> Variant)
-> (Variant -> Variant -> Variant)
-> Ord Variant
Variant -> Variant -> Bool
Variant -> Variant -> Ordering
Variant -> Variant -> Variant
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Variant -> Variant -> Ordering
compare :: Variant -> Variant -> Ordering
$c< :: Variant -> Variant -> Bool
< :: Variant -> Variant -> Bool
$c<= :: Variant -> Variant -> Bool
<= :: Variant -> Variant -> Bool
$c> :: Variant -> Variant -> Bool
> :: Variant -> Variant -> Bool
$c>= :: Variant -> Variant -> Bool
>= :: Variant -> Variant -> Bool
$cmax :: Variant -> Variant -> Variant
max :: Variant -> Variant -> Variant
$cmin :: Variant -> Variant -> Variant
min :: Variant -> Variant -> Variant
Ord,ReadPrec [Variant]
ReadPrec Variant
Int -> ReadS Variant
ReadS [Variant]
(Int -> ReadS Variant)
-> ReadS [Variant]
-> ReadPrec Variant
-> ReadPrec [Variant]
-> Read Variant
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Variant
readsPrec :: Int -> ReadS Variant
$creadList :: ReadS [Variant]
readList :: ReadS [Variant]
$creadPrec :: ReadPrec Variant
readPrec :: ReadPrec Variant
$creadListPrec :: ReadPrec [Variant]
readListPrec :: ReadPrec [Variant]
Read,Int -> Variant -> ShowS
[Variant] -> ShowS
Variant -> String
(Int -> Variant -> ShowS)
-> (Variant -> String) -> ([Variant] -> ShowS) -> Show Variant
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Variant -> ShowS
showsPrec :: Int -> Variant -> ShowS
$cshow :: Variant -> String
show :: Variant -> String
$cshowList :: [Variant] -> ShowS
showList :: [Variant] -> ShowS
Show,Int -> Variant
Variant -> Int
Variant -> [Variant]
Variant -> Variant
Variant -> Variant -> [Variant]
Variant -> Variant -> Variant -> [Variant]
(Variant -> Variant)
-> (Variant -> Variant)
-> (Int -> Variant)
-> (Variant -> Int)
-> (Variant -> [Variant])
-> (Variant -> Variant -> [Variant])
-> (Variant -> Variant -> [Variant])
-> (Variant -> Variant -> Variant -> [Variant])
-> Enum Variant
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Variant -> Variant
succ :: Variant -> Variant
$cpred :: Variant -> Variant
pred :: Variant -> Variant
$ctoEnum :: Int -> Variant
toEnum :: Int -> Variant
$cfromEnum :: Variant -> Int
fromEnum :: Variant -> Int
$cenumFrom :: Variant -> [Variant]
enumFrom :: Variant -> [Variant]
$cenumFromThen :: Variant -> Variant -> [Variant]
enumFromThen :: Variant -> Variant -> [Variant]
$cenumFromTo :: Variant -> Variant -> [Variant]
enumFromTo :: Variant -> Variant -> [Variant]
$cenumFromThenTo :: Variant -> Variant -> Variant -> [Variant]
enumFromThenTo :: Variant -> Variant -> Variant -> [Variant]
Enum,Variant
Variant -> Variant -> Bounded Variant
forall a. a -> a -> Bounded a
$cminBound :: Variant
minBound :: Variant
$cmaxBound :: Variant
maxBound :: Variant
Bounded)
data Version = Version10 | Version13
deriving (Version -> Version -> Bool
(Version -> Version -> Bool)
-> (Version -> Version -> Bool) -> Eq Version
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Version -> Version -> Bool
== :: Version -> Version -> Bool
$c/= :: Version -> Version -> Bool
/= :: Version -> Version -> Bool
Eq,Eq Version
Eq Version =>
(Version -> Version -> Ordering)
-> (Version -> Version -> Bool)
-> (Version -> Version -> Bool)
-> (Version -> Version -> Bool)
-> (Version -> Version -> Bool)
-> (Version -> Version -> Version)
-> (Version -> Version -> Version)
-> Ord Version
Version -> Version -> Bool
Version -> Version -> Ordering
Version -> Version -> Version
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Version -> Version -> Ordering
compare :: Version -> Version -> Ordering
$c< :: Version -> Version -> Bool
< :: Version -> Version -> Bool
$c<= :: Version -> Version -> Bool
<= :: Version -> Version -> Bool
$c> :: Version -> Version -> Bool
> :: Version -> Version -> Bool
$c>= :: Version -> Version -> Bool
>= :: Version -> Version -> Bool
$cmax :: Version -> Version -> Version
max :: Version -> Version -> Version
$cmin :: Version -> Version -> Version
min :: Version -> Version -> Version
Ord,ReadPrec [Version]
ReadPrec Version
Int -> ReadS Version
ReadS [Version]
(Int -> ReadS Version)
-> ReadS [Version]
-> ReadPrec Version
-> ReadPrec [Version]
-> Read Version
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Version
readsPrec :: Int -> ReadS Version
$creadList :: ReadS [Version]
readList :: ReadS [Version]
$creadPrec :: ReadPrec Version
readPrec :: ReadPrec Version
$creadListPrec :: ReadPrec [Version]
readListPrec :: ReadPrec [Version]
Read,Int -> Version -> ShowS
[Version] -> ShowS
Version -> String
(Int -> Version -> ShowS)
-> (Version -> String) -> ([Version] -> ShowS) -> Show Version
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Version -> ShowS
showsPrec :: Int -> Version -> ShowS
$cshow :: Version -> String
show :: Version -> String
$cshowList :: [Version] -> ShowS
showList :: [Version] -> ShowS
Show,Int -> Version
Version -> Int
Version -> [Version]
Version -> Version
Version -> Version -> [Version]
Version -> Version -> Version -> [Version]
(Version -> Version)
-> (Version -> Version)
-> (Int -> Version)
-> (Version -> Int)
-> (Version -> [Version])
-> (Version -> Version -> [Version])
-> (Version -> Version -> [Version])
-> (Version -> Version -> Version -> [Version])
-> Enum Version
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Version -> Version
succ :: Version -> Version
$cpred :: Version -> Version
pred :: Version -> Version
$ctoEnum :: Int -> Version
toEnum :: Int -> Version
$cfromEnum :: Version -> Int
fromEnum :: Version -> Int
$cenumFrom :: Version -> [Version]
enumFrom :: Version -> [Version]
$cenumFromThen :: Version -> Version -> [Version]
enumFromThen :: Version -> Version -> [Version]
$cenumFromTo :: Version -> Version -> [Version]
enumFromTo :: Version -> Version -> [Version]
$cenumFromThenTo :: Version -> Version -> Version -> [Version]
enumFromThenTo :: Version -> Version -> Version -> [Version]
Enum,Version
Version -> Version -> Bounded Version
forall a. a -> a -> Bounded a
$cminBound :: Version
minBound :: Version
$cmaxBound :: Version
maxBound :: Version
Bounded)
type TimeCost = Word32
type MemoryCost = Word32
type Parallelism = Word32
data Options = Options
{ Options -> TimeCost
iterations :: !TimeCost
, Options -> TimeCost
memory :: !MemoryCost
, Options -> TimeCost
parallelism :: !Parallelism
, Options -> Variant
variant :: !Variant
, Options -> Version
version :: !Version
}
deriving (Options -> Options -> Bool
(Options -> Options -> Bool)
-> (Options -> Options -> Bool) -> Eq Options
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
/= :: Options -> Options -> Bool
Eq,Eq Options
Eq Options =>
(Options -> Options -> Ordering)
-> (Options -> Options -> Bool)
-> (Options -> Options -> Bool)
-> (Options -> Options -> Bool)
-> (Options -> Options -> Bool)
-> (Options -> Options -> Options)
-> (Options -> Options -> Options)
-> Ord Options
Options -> Options -> Bool
Options -> Options -> Ordering
Options -> Options -> Options
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Options -> Options -> Ordering
compare :: Options -> Options -> Ordering
$c< :: Options -> Options -> Bool
< :: Options -> Options -> Bool
$c<= :: Options -> Options -> Bool
<= :: Options -> Options -> Bool
$c> :: Options -> Options -> Bool
> :: Options -> Options -> Bool
$c>= :: Options -> Options -> Bool
>= :: Options -> Options -> Bool
$cmax :: Options -> Options -> Options
max :: Options -> Options -> Options
$cmin :: Options -> Options -> Options
min :: Options -> Options -> Options
Ord,ReadPrec [Options]
ReadPrec Options
Int -> ReadS Options
ReadS [Options]
(Int -> ReadS Options)
-> ReadS [Options]
-> ReadPrec Options
-> ReadPrec [Options]
-> Read Options
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Options
readsPrec :: Int -> ReadS Options
$creadList :: ReadS [Options]
readList :: ReadS [Options]
$creadPrec :: ReadPrec Options
readPrec :: ReadPrec Options
$creadListPrec :: ReadPrec [Options]
readListPrec :: ReadPrec [Options]
Read,Int -> Options -> ShowS
[Options] -> ShowS
Options -> String
(Int -> Options -> ShowS)
-> (Options -> String) -> ([Options] -> ShowS) -> Show Options
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Options -> ShowS
showsPrec :: Int -> Options -> ShowS
$cshow :: Options -> String
show :: Options -> String
$cshowList :: [Options] -> ShowS
showList :: [Options] -> ShowS
Show)
saltMinLength :: Int
saltMinLength :: Int
saltMinLength = Int
8
outputMinLength :: Int
outputMinLength :: Int
outputMinLength = Int
4
outputMaxLength :: Int
outputMaxLength :: Int
outputMaxLength = Int
0x7fffffff
defaultOptions :: Options
defaultOptions :: Options
defaultOptions =
Options { iterations :: TimeCost
iterations = TimeCost
1
, memory :: TimeCost
memory = TimeCost
2 TimeCost -> Int -> TimeCost
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
17 :: Int)
, parallelism :: TimeCost
parallelism = TimeCost
4
, variant :: Variant
variant = Variant
Argon2i
, version :: Version
version = Version
Version13
}
hash :: (ByteArrayAccess password, ByteArrayAccess salt, ByteArray out)
=> Options
-> password
-> salt
-> Int
-> CryptoFailable out
hash :: forall password salt out.
(ByteArrayAccess password, ByteArrayAccess salt, ByteArray out) =>
Options -> password -> salt -> Int -> CryptoFailable out
hash Options
options password
password salt
salt Int
outLen
| Int
saltLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
saltMinLength = CryptoError -> CryptoFailable out
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SaltTooSmall
| Int
outLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
outputMinLength = CryptoError -> CryptoFailable out
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_OutputLengthTooSmall
| Int
outLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
outputMaxLength = CryptoError -> CryptoFailable out
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_OutputLengthTooBig
| Bool
otherwise = out -> CryptoFailable out
forall a. a -> CryptoFailable a
CryptoPassed (out -> CryptoFailable out) -> out -> CryptoFailable out
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr HashOut -> IO ()) -> out
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
outLen ((Ptr HashOut -> IO ()) -> out) -> (Ptr HashOut -> IO ()) -> out
forall a b. (a -> b) -> a -> b
$ \Ptr HashOut
out -> do
CVariant
res <- password -> (Ptr Pass -> IO CVariant) -> IO CVariant
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
forall p a. password -> (Ptr p -> IO a) -> IO a
B.withByteArray password
password ((Ptr Pass -> IO CVariant) -> IO CVariant)
-> (Ptr Pass -> IO CVariant) -> IO CVariant
forall a b. (a -> b) -> a -> b
$ \Ptr Pass
pPass ->
salt -> (Ptr Salt -> IO CVariant) -> IO CVariant
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
forall p a. salt -> (Ptr p -> IO a) -> IO a
B.withByteArray salt
salt ((Ptr Salt -> IO CVariant) -> IO CVariant)
-> (Ptr Salt -> IO CVariant) -> IO CVariant
forall a b. (a -> b) -> a -> b
$ \Ptr Salt
pSalt ->
TimeCost
-> TimeCost
-> TimeCost
-> Ptr Pass
-> CSize
-> Ptr Salt
-> CSize
-> Ptr HashOut
-> CSize
-> CVariant
-> CVariant
-> IO CVariant
argon2_hash (Options -> TimeCost
iterations Options
options)
(Options -> TimeCost
memory Options
options)
(Options -> TimeCost
parallelism Options
options)
Ptr Pass
pPass
(Int -> CSize
csizeOfInt Int
passwordLen)
Ptr Salt
pSalt
(Int -> CSize
csizeOfInt Int
saltLen)
Ptr HashOut
out
(Int -> CSize
csizeOfInt Int
outLen)
(Variant -> CVariant
cOfVariant (Variant -> CVariant) -> Variant -> CVariant
forall a b. (a -> b) -> a -> b
$ Options -> Variant
variant Options
options)
(Version -> CVariant
cOfVersion (Version -> CVariant) -> Version -> CVariant
forall a b. (a -> b) -> a -> b
$ Options -> Version
version Options
options)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CVariant
res CVariant -> CVariant -> Bool
forall a. Eq a => a -> a -> Bool
/= CVariant
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall a. HasCallStack => String -> a
error String
"argon2: hash: internal error"
where
saltLen :: Int
saltLen = salt -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length salt
salt
passwordLen :: Int
passwordLen = password -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length password
password
data Pass
data Salt
data HashOut
type CVariant = CInt
type CVersion = CInt
cOfVersion :: Version -> CVersion
cOfVersion :: Version -> CVariant
cOfVersion Version
Version10 = CVariant
0x10
cOfVersion Version
Version13 = CVariant
0x13
cOfVariant :: Variant -> CVariant
cOfVariant :: Variant -> CVariant
cOfVariant Variant
Argon2d = CVariant
0
cOfVariant Variant
Argon2i = CVariant
1
cOfVariant Variant
Argon2id = CVariant
2
csizeOfInt :: Int -> CSize
csizeOfInt :: Int -> CSize
csizeOfInt = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral
foreign import ccall unsafe "crypton_argon2_hash"
argon2_hash :: Word32 -> Word32 -> Word32
-> Ptr Pass -> CSize
-> Ptr Salt -> CSize
-> Ptr HashOut -> CSize
-> CVariant
-> CVersion
-> IO CInt