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
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Variant -> Variant -> Bool
$c/= :: Variant -> Variant -> Bool
== :: Variant -> Variant -> Bool
$c== :: Variant -> Variant -> Bool
Eq,Eq 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
min :: Variant -> Variant -> Variant
$cmin :: Variant -> Variant -> Variant
max :: Variant -> Variant -> Variant
$cmax :: Variant -> Variant -> Variant
>= :: Variant -> Variant -> Bool
$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
compare :: Variant -> Variant -> Ordering
$ccompare :: Variant -> Variant -> Ordering
Ord,ReadPrec [Variant]
ReadPrec Variant
Int -> ReadS Variant
ReadS [Variant]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Variant]
$creadListPrec :: ReadPrec [Variant]
readPrec :: ReadPrec Variant
$creadPrec :: ReadPrec Variant
readList :: ReadS [Variant]
$creadList :: ReadS [Variant]
readsPrec :: Int -> ReadS Variant
$creadsPrec :: Int -> ReadS Variant
Read,Int -> Variant -> ShowS
[Variant] -> ShowS
Variant -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Variant] -> ShowS
$cshowList :: [Variant] -> ShowS
show :: Variant -> String
$cshow :: Variant -> String
showsPrec :: Int -> Variant -> ShowS
$cshowsPrec :: Int -> Variant -> ShowS
Show,Int -> Variant
Variant -> Int
Variant -> [Variant]
Variant -> Variant
Variant -> Variant -> [Variant]
Variant -> Variant -> Variant -> [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
enumFromThenTo :: Variant -> Variant -> Variant -> [Variant]
$cenumFromThenTo :: Variant -> Variant -> Variant -> [Variant]
enumFromTo :: Variant -> Variant -> [Variant]
$cenumFromTo :: Variant -> Variant -> [Variant]
enumFromThen :: Variant -> Variant -> [Variant]
$cenumFromThen :: Variant -> Variant -> [Variant]
enumFrom :: Variant -> [Variant]
$cenumFrom :: Variant -> [Variant]
fromEnum :: Variant -> Int
$cfromEnum :: Variant -> Int
toEnum :: Int -> Variant
$ctoEnum :: Int -> Variant
pred :: Variant -> Variant
$cpred :: Variant -> Variant
succ :: Variant -> Variant
$csucc :: Variant -> Variant
Enum,Variant
forall a. a -> a -> Bounded a
maxBound :: Variant
$cmaxBound :: Variant
minBound :: Variant
$cminBound :: Variant
Bounded)
data Version = Version10 | Version13
deriving (Version -> Version -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Version -> Version -> Bool
$c/= :: Version -> Version -> Bool
== :: Version -> Version -> Bool
$c== :: Version -> Version -> Bool
Eq,Eq 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
min :: Version -> Version -> Version
$cmin :: Version -> Version -> Version
max :: Version -> Version -> Version
$cmax :: Version -> Version -> Version
>= :: Version -> Version -> Bool
$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
compare :: Version -> Version -> Ordering
$ccompare :: Version -> Version -> Ordering
Ord,ReadPrec [Version]
ReadPrec Version
Int -> ReadS Version
ReadS [Version]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Version]
$creadListPrec :: ReadPrec [Version]
readPrec :: ReadPrec Version
$creadPrec :: ReadPrec Version
readList :: ReadS [Version]
$creadList :: ReadS [Version]
readsPrec :: Int -> ReadS Version
$creadsPrec :: Int -> ReadS Version
Read,Int -> Version -> ShowS
[Version] -> ShowS
Version -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Version] -> ShowS
$cshowList :: [Version] -> ShowS
show :: Version -> String
$cshow :: Version -> String
showsPrec :: Int -> Version -> ShowS
$cshowsPrec :: Int -> Version -> ShowS
Show,Int -> Version
Version -> Int
Version -> [Version]
Version -> Version
Version -> Version -> [Version]
Version -> Version -> Version -> [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
enumFromThenTo :: Version -> Version -> Version -> [Version]
$cenumFromThenTo :: Version -> Version -> Version -> [Version]
enumFromTo :: Version -> Version -> [Version]
$cenumFromTo :: Version -> Version -> [Version]
enumFromThen :: Version -> Version -> [Version]
$cenumFromThen :: Version -> Version -> [Version]
enumFrom :: Version -> [Version]
$cenumFrom :: Version -> [Version]
fromEnum :: Version -> Int
$cfromEnum :: Version -> Int
toEnum :: Int -> Version
$ctoEnum :: Int -> Version
pred :: Version -> Version
$cpred :: Version -> Version
succ :: Version -> Version
$csucc :: Version -> Version
Enum,Version
forall a. a -> a -> Bounded a
maxBound :: Version
$cmaxBound :: Version
minBound :: Version
$cminBound :: 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
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c== :: Options -> Options -> Bool
Eq,Eq 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
min :: Options -> Options -> Options
$cmin :: Options -> Options -> Options
max :: Options -> Options -> Options
$cmax :: Options -> Options -> Options
>= :: Options -> Options -> Bool
$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
compare :: Options -> Options -> Ordering
$ccompare :: Options -> Options -> Ordering
Ord,ReadPrec [Options]
ReadPrec Options
Int -> ReadS Options
ReadS [Options]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Options]
$creadListPrec :: ReadPrec [Options]
readPrec :: ReadPrec Options
$creadPrec :: ReadPrec Options
readList :: ReadS [Options]
$creadList :: ReadS [Options]
readsPrec :: Int -> ReadS Options
$creadsPrec :: Int -> ReadS Options
Read,Int -> Options -> ShowS
[Options] -> ShowS
Options -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Options] -> ShowS
$cshowList :: [Options] -> ShowS
show :: Options -> String
$cshow :: Options -> String
showsPrec :: Int -> Options -> ShowS
$cshowsPrec :: Int -> 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 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 forall a. Ord a => a -> a -> Bool
< Int
saltMinLength = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_SaltTooSmall
| Int
outLen forall a. Ord a => a -> a -> Bool
< Int
outputMinLength = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_OutputLengthTooSmall
| Int
outLen forall a. Ord a => a -> a -> Bool
> Int
outputMaxLength = forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_OutputLengthTooBig
| Bool
otherwise = forall a. a -> CryptoFailable a
CryptoPassed forall a b. (a -> b) -> a -> b
$ forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
B.allocAndFreeze Int
outLen forall a b. (a -> b) -> a -> b
$ \Ptr HashOut
out -> do
CVariant
res <- forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
B.withByteArray password
password forall a b. (a -> b) -> a -> b
$ \Ptr Pass
pPass ->
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
B.withByteArray salt
salt 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 forall a b. (a -> b) -> a -> b
$ Options -> Variant
variant Options
options)
(Version -> CVariant
cOfVersion forall a b. (a -> b) -> a -> b
$ Options -> Version
version Options
options)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CVariant
res forall a. Eq a => a -> a -> Bool
/= CVariant
0) forall a b. (a -> b) -> a -> b
$ forall a. HasCallStack => String -> a
error String
"argon2: hash: internal error"
where
saltLen :: Int
saltLen = forall ba. ByteArrayAccess ba => ba -> Int
B.length salt
salt
passwordLen :: Int
passwordLen = 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 = forall a b. (Integral a, Num b) => a -> b
fromIntegral
foreign import ccall unsafe "cryptonite_argon2_hash"
argon2_hash :: Word32 -> Word32 -> Word32
-> Ptr Pass -> CSize
-> Ptr Salt -> CSize
-> Ptr HashOut -> CSize
-> CVariant
-> CVersion
-> IO CInt