argon2-1.1.0: Tests.hs
{-# LANGUAGE OverloadedStrings #-}
import Crypto.Argon2
import Test.QuickCheck
import Test.Tasty
import Data.Ix
import Test.Tasty.QuickCheck
import qualified Crypto.Argon2.FFI as FFI
import qualified Data.ByteString as BS
import qualified Data.Text.Encoding as T
import Data.Bits (shiftL)
arbitraryVariant :: Gen Argon2Variant
arbitraryVariant = arbitraryBoundedEnum
-- The hard-coded constants correspond to `decode_string`, but see
-- https://github.com/P-H-C/phc-winner-argon2/issues/77
arbitraryHashOptions :: Gen HashOptions
arbitraryHashOptions =
do p <-
arbitraryWithin (max (max FFI.ARGON2_MIN_LANES FFI.ARGON2_MIN_THREADS) 1)
(min (min FFI.ARGON2_MAX_LANES FFI.ARGON2_MAX_THREADS) 254)
HashOptions <$>
arbitraryWithin FFI.ARGON2_MIN_TIME
(min FFI.ARGON2_MAX_TIME (2 ^ 32 - 1)) <*>
arbitraryWithin
(max (max FFI.ARGON2_MIN_MEMORY (8 * p))
(shiftL p 3))
FFI.ARGON2_MAX_MEMORY <*>
pure p <*>
arbitraryVariant
arbitraryWithin lower upper = arbitrary `suchThat` (inRange (lower,upper))
arbitraryBytes :: Gen BS.ByteString
arbitraryBytes = fmap BS.pack arbitrary
arbitraryPassword :: Gen BS.ByteString
arbitraryPassword = arbitraryBytes `suchThat`
(\pwd ->
(FFI.ARGON2_MIN_PWD_LENGTH
,FFI.ARGON2_MAX_PWD_LENGTH) `inRange`
BS.length pwd)
arbitrarySalt =
arbitraryBytes `suchThat`
(\salt ->
(FFI.ARGON2_MIN_SALT_LENGTH,FFI.ARGON2_MAX_SALT_LENGTH) `inRange`
BS.length salt)
main :: IO ()
main =
defaultMain
(testGroup "Properties"
[testProperty
"Round trip"
(forAll arbitraryHashOptions $
\hashOptions ->
forAll arbitraryPassword $
\password ->
forAll arbitrarySalt $
\salt ->
verify (hashEncoded hashOptions password salt) password)
,testProperty
"Unencoded hashing"
(forAll arbitraryHashOptions $
\hashOptions ->
forAll arbitraryPassword $
\password ->
forAll arbitrarySalt $
\salt -> hash hashOptions password salt /= password)
,testProperty
"defaultHashOptions"
(forAll arbitraryVariant $
\variant ->
(forAll arbitraryPassword $
\password ->
forAll arbitrarySalt $
\salt ->
verify (hashEncoded
(defaultHashOptions {hashVariant = variant})
password
salt)
password))])