cryptonite/tests/BCrypt.hs
Luke Taylor d27d464627 Fix cost parsing for bcrypt
The tens value was wrong for values of 20+, as reported in #230.
It should be 10*costTens not 10^costTens. This wasn't detected because
the values are the same when costTens is 1, and using high cost values
is rare with bcrypt because of the performance hit.

Also added a simple hash and validate test since the KAT tests only do
validation. This doesn't cover this bug since the cost value is too
high to include in the test. It allows similar issues to be tested
locally though.
2018-04-17 13:51:04 +01:00

83 lines
4.2 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
module BCrypt
( tests
)
where
import Crypto.KDF.BCrypt
import qualified Data.ByteString as B
import Imports
-- Openwall bcrypt tests, with 2x versions and 0xFF special cases removed.
expected :: [(ByteString, ByteString)]
expected =
[ ("$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", "U*U")
, ("$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", "U*U*")
, ("$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", "U*U*U")
, ("$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui",
"0123456789abcdefghijklmnopqrstuvwxyz\
\ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\
\chars after 72 are ignored")
, ("$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", "\xff\xff\xa3")
, ("$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", "\xff\xff\xa3")
, ("$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", "\xa3")
, ("$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", "\xa3")
, ("$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", "\xa3")
, ("$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6",
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\
\chars after 72 are ignored as usual")
, ("$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy",
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\
\\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\
\\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\
\\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\
\\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\
\\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55")
, ("$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe",
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\
\\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\
\\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\
\\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\
\\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\
\\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff")
, ("$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", "")
, ("$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.", "")
, ("$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye", "")
, ("$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW", "")
, ("$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO", "")
, ("$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe", "a")
, ("$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.", "a")
, ("$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS", "a")
, ("$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i", "abc")
, ("$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm", "abc")
, ("$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi", "abc")
, ("$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC", "abcdefghijklmnopqrstuvwxyz")
]
makeKATs = concatMap maketest (zip3 is passwords hashes)
where
is :: [Int]
is = [1..]
passwords = map snd expected
hashes = map fst expected
maketest (i, password, hash) =
[ testCase (show i) (assertBool "" (validatePassword password hash))
]
tests = testGroup "bcrypt"
[ testGroup "KATs" makeKATs
, testCase "Invalid hash length" (assertEqual "" (Left "Invalid hash format") (validatePasswordEither B.empty ("$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s" :: B.ByteString)))
, testCase "Hash and validate" (assertBool "Hashed password should validate" (validatePassword somePassword (bcrypt 5 aSalt somePassword :: B.ByteString)))
]
where
somePassword = "some password" :: B.ByteString
aSalt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" :: B.ByteString