{-# LANGUAGE OverloadedStrings #-} module KAT_OTP ( tests ) where import Crypto.Hash.Algorithms (SHA1(..), SHA256(..), SHA512(..)) import Crypto.OTP import Data.ByteString (ByteString) import Imports -- | Test values from Appendix D of http://tools.ietf.org/html/rfc4226 hotpExpected :: [(Word64, Word32)] hotpExpected = [ (0, 755224) , (1, 287082) , (3, 969429) , (4, 338314) , (5, 254676) , (6, 287922) , (7, 162583) , (8, 399871) , (9, 520489) ] -- | Test data from Appendix B of http://tools.ietf.org/html/rfc6238 -- Note that the shared keys for the non SHA-1 values are actually -- different (see the errata, or the Java example code). totpSHA1Expected :: [(Word64, Word32)] totpSHA1Expected = [ (59 , 94287082) , (1111111109, 07081804) , (1111111111, 14050471) , (1234567890, 89005924) , (2000000000, 69279037) , (20000000000, 65353130) ] totpSHA256Expected :: [(Word64, Word32)] totpSHA256Expected = [ (59 , 46119246) , (1111111109, 68084774) , (1111111111, 67062674) , (1234567890, 91819424) , (2000000000, 90698825) , (20000000000, 77737706) ] totpSHA512Expected :: [(Word64, Word32)] totpSHA512Expected = [ (59 , 90693936) , (1111111109, 25091201) , (1111111111, 99943326) , (1234567890, 93441116) , (2000000000, 38618901) , (20000000000, 47863826) ] otpKey = "12345678901234567890" :: ByteString totpSHA256Key = "12345678901234567890123456789012" :: ByteString totpSHA512Key = "1234567890123456789012345678901234567890123456789012345678901234" :: ByteString makeKATs otp expected = concatMap (makeTest otp) (zip3 is counts otps) where is :: [Int] is = [1..] counts = map fst expected otps = map snd expected makeTest otp (i, count, password) = [ testCase (show i) (assertEqual "" password (otp count)) ] Right totpSHA1Params = mkTOTPParams SHA1 0 30 OTP8 TwoSteps Right totpSHA256Params = mkTOTPParams SHA256 0 30 OTP8 TwoSteps Right totpSHA512Params = mkTOTPParams SHA512 0 30 OTP8 TwoSteps -- resynching with the expected value should just return the current counter + 1 prop_resyncExpected ctr window = resynchronize SHA1 OTP6 window key ctr (otp, []) == Just (ctr + 1) where key = "1234" :: ByteString otp = hotp SHA1 OTP6 key ctr tests = testGroup "OTP" [ testGroup "HOTP" [ testGroup "KATs" (makeKATs (hotp SHA1 OTP6 otpKey) hotpExpected) , testGroup "properties" [ testProperty "resync-expected" prop_resyncExpected ] ] , testGroup "TOTP" [ testGroup "KATs" [ testGroup "SHA1" (makeKATs (totp totpSHA1Params otpKey . fromIntegral) totpSHA1Expected) , testGroup "SHA256" (makeKATs (totp totpSHA256Params totpSHA256Key . fromIntegral) totpSHA256Expected) , testGroup "SHA512" (makeKATs (totp totpSHA512Params totpSHA512Key . fromIntegral) totpSHA512Expected) ] ] ]