password-3.0.1.0: test/tasty/Argon2.hs
{-# LANGUAGE OverloadedStrings #-}
module Argon2 (testArgon2) where
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertBool, assertEqual, testCase)
import Data.Password.Argon2
import Internal
testArgon2 :: TestTree
testArgon2 = testGroup "Argon2"
[ referenceTest
, testCorrectPassword "Argon2 (hashPassword)" hashFast checkPassword
, testIncorrectPassword "Argon2 (hashPassword) fail" hashFast checkPassword
, testWithSalt "Argon2 (hashPasswordWithSalt)"
(hashPasswordWithSalt fastParams)
checkPassword
, testWithParams "Argon2 (Argon2i)" $ fastParams{ argon2Variant = Argon2i }
, testWithParams "Argon2 (Argon2d)" $ fastParams{ argon2Variant = Argon2d }
, paddingTests
, omittedVersionTest
]
where
testWithParams s params =
testWithSalt s (hashPasswordWithSalt params) checkPassword
hashFast = hashPasswordWithParams fastParams
fastParams =
defaultParams{
argon2MemoryCost = 2 ^ (8 :: Int),
argon2TimeCost = 1
}
paddingTests :: TestTree
paddingTests = testGroup "Padding"
[ testCase "with padding" $
assertBool "Bad hash" $ checkPassword pass hashWithPadding == PasswordCheckSuccess
, testCase "without padding" $
assertBool "Bad hash" $ checkPassword pass hashWithoutPadding == PasswordCheckSuccess
]
pass :: Password
pass = "foobar"
-- Hashed password ("foobar") with salt ("abcdefghijklmnop")
hashWithPadding, hashWithoutPadding :: PasswordHash Argon2
hashWithPadding = PasswordHash "$argon2id$v=19$m=65536,t=2,p=1$YWJjZGVmZ2hpamtsbW5vcA==$BztdyfEefG5V18ZNlztPrfZaU5duVFKZiI6dJeWht0o="
hashWithoutPadding = PasswordHash "$argon2id$v=19$m=65536,t=2,p=1$YWJjZGVmZ2hpamtsbW5vcA$BztdyfEefG5V18ZNlztPrfZaU5duVFKZiI6dJeWht0o"
-- Very old hashes might not have version parts, so infer as version 1.0
omittedVersionTest :: TestTree
omittedVersionTest = testGroup "Version 1.0"
[ go "version 1.0 part in hash (placebo)" "testtest" v10Hash
, go "no version part in hash == version 1.0" "testtest" v10HashWithoutVersion
, go "version 1.3 part in hash (reference)" "password" referenceHash
, testCase "no version 1.3 part in hash should fail" $
assertEqual "check passed!?" PasswordCheckFail $
checkPassword "password" referenceHashWithoutVersion
]
where
go s p = testCase s
. assertEqual "check failed" PasswordCheckSuccess
. checkPassword p
-- Reference check using the Command-line Utility output example
-- from: https://github.com/P-H-C/phc-winner-argon2
referenceTest :: TestTree
referenceTest = testCase "PHC Argon2 reference" $
assertEqual "output hash is wrong" referenceHash $
hashPasswordWithSalt params salt pwd
where
salt = Salt "somesalt"
pwd = mkPassword "password"
params = defaultParams {
argon2Variant = Argon2i,
argon2Parallelism = 4,
argon2OutputLength = 24
}
-- Weirdly lined out to show it's exactly the same, except the 'v=' part is missing.
referenceHash, referenceHashWithoutVersion :: PasswordHash Argon2
referenceHash = PasswordHash "$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG"
referenceHashWithoutVersion = PasswordHash "$argon2i$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG"
v10Hash, v10HashWithoutVersion :: PasswordHash Argon2
v10Hash = PasswordHash "$argon2i$v=16$m=65536,t=2,p=1$Kx1BEcpIg0Ey5GyXq5do2w$0qRfWHw09EdqQkSsaG57O/ou8v/E6Vc83w"
v10HashWithoutVersion = PasswordHash "$argon2i$m=65536,t=2,p=1$Kx1BEcpIg0Ey5GyXq5do2w$0qRfWHw09EdqQkSsaG57O/ou8v/E6Vc83w"