packages feed

fastpbkdf2-0.1.0.0: test/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Exception (evaluate, try, SomeException)
import Crypto.KDF.PBKDF2
import Data.ByteString as B
import Data.ByteString.Base16 (decode)
import Data.ByteString.Char8 as C8
import Data.Either (isLeft, isRight)
import Data.Monoid
import Test.Tasty
import Test.Tasty.HUnit

----------------------------------------------------------------------
unhex :: ByteString -> ByteString
unhex = fst . decode

----------------------------------------------------------------------
type CryptoFn = ByteString -> ByteString -> Int -> Int -> ByteString

----------------------------------------------------------------------
testVectors :: CryptoFn -> [(C8.ByteString, C8.ByteString,Int,ByteString)] -> Assertion
testVectors _ [] = return ()
testVectors fn ((input, salt, iter, expected_hex):xs) = do
  let actual = fn input salt iter (floor ((fromIntegral $ B.length expected_hex) / fromIntegral 2))
  actual @?= (unhex expected_hex)
  testVectors fn xs

----------------------------------------------------------------------
testInvalidIterationNumber :: Assertion
testInvalidIterationNumber = do
  (res :: Either SomeException ByteString) <- try $ evaluate (fastpbkdf2_hmac_sha1 "password" "salt" 0 32)
  isLeft res @?= True

----------------------------------------------------------------------
testInvalidKeyLen :: Assertion
testInvalidKeyLen = do
  (res :: Either SomeException ByteString) <- try $ evaluate (fastpbkdf2_hmac_sha1 "password" "salt" 1 (-1))
  isLeft res @?= True

----------------------------------------------------------------------
testEmptyPassword :: Assertion
testEmptyPassword = do
  (res :: Either SomeException ByteString) <- try $ evaluate (fastpbkdf2_hmac_sha1 "" "salt" 1 32)
  isRight res @?= True

----------------------------------------------------------------------
testEmptySalt :: Assertion
testEmptySalt = do
  (res :: Either SomeException ByteString) <- try $ evaluate (fastpbkdf2_hmac_sha1 "password" "" 1 32)
  isRight res @?= True

----------------------------------------------------------------------
main :: IO ()
main = do
  defaultMainWithIngredients defaultIngredients $ testGroup "all tests" [
    testGroup "Test Vectors" $ [
        testCase "RFC6070 SHA1 Test Vectors"   (testVectors fastpbkdf2_hmac_sha1   test_vectors_sha1)
      , testCase "RFC6070 SHA256 Test Vectors" (testVectors fastpbkdf2_hmac_sha256 test_vectors_sha256)
      , testCase "(Partial) RFC6070 SHA512 Test Vectors" (testVectors fastpbkdf2_hmac_sha512 test_vectors_sha512)
      ]
    , testGroup "Edge cases" $ [
        testCase "Invalid iteration number" testInvalidIterationNumber
      , testCase "Invalid key length" testInvalidKeyLen
      , testCase "Empty password" testEmptyPassword
      , testCase "Empty salt" testEmptySalt
      ]
    ]

-- RFC6070 test vectors
test_vectors_sha1 :: [(C8.ByteString,C8.ByteString,Int,ByteString)]
test_vectors_sha1 = [ ("password", "salt", 1, "0c60c80f961f0e71f3a9b524af6012062fe037a6")
                    , ("password", "salt", 2, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957")
                    , ("password", "salt", 4096, "4b007901b765489abead49d926f721d065a429c1")
                    , ("password", "salt", 16777216, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984")
                    , ( "passwordPASSWORDpassword"
                      , "saltSALTsaltSALTsaltSALTsaltSALTsalt"
                      , 4096
                      , "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038")
                    , ("pass\0word", "sa\0lt", 4096, "56fa6aa75548099dcc37d7f03425e0c3")
                    ]

test_vectors_sha256 :: [(C8.ByteString,C8.ByteString,Int,ByteString)]
test_vectors_sha256 = [ ("password", "salt", 1, "120fb6cffcf8b32c43e7225256c4f837a86548c9")
                    , ("password", "salt", 2, "ae4d0c95af6b46d32d0adff928f06dd02a303f8e")
                    , ("password", "salt", 4096, "c5e478d59288c841aa530db6845c4c8d962893a0")
                    , ("password", "salt", 16777216, "cf81c66fe8cfc04d1f31ecb65dab4089f7f179e8")
                    , ( "passwordPASSWORDpassword"
                      , "saltSALTsaltSALTsaltSALTsaltSALTsalt"
                      , 4096
                      , "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c")
                    , ("pass\0word", "sa\0lt", 4096, "89b69d0516f829893c696226650a8687")
                    ]

test_vectors_sha512 :: [(C8.ByteString,C8.ByteString,Int,ByteString)]
test_vectors_sha512 = [ ("password", "salt", 1, "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470"
                                             <> "a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"
                        )
                      , ("password", "salt", 2, "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f"
                                             <> "7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"
                        )
                      ]