Based on specification in https://datatracker.ietf.org/doc/html/rfc6238
generateTOTP : Algorithm -> { outputLength : Basics.Int, periodSeconds : Basics.Int } -> Base32String -> Time.Posix -> Result String String
https://datatracker.ietf.org/doc/html/rfc6238#appendix-B
import TOTP.Algorithm
import TOTP.Base32String exposing (Base32String(..))
import Time
seed : Base32String
seed =
"12345678901234567890"
|> TOTP.Base32String.stringToBase32
|> Result.withDefault (TOTP.Base32String.test.base32String "error")
seed32 : Base32String
seed32 =
"12345678901234567890123456789012"
|> TOTP.Base32String.stringToBase32
|> Result.withDefault (TOTP.Base32String.test.base32String "error")
seed64 : Base32String
seed64 =
"1234567890123456789012345678901234567890123456789012345678901234"
|> TOTP.Base32String.stringToBase32
|> Result.withDefault (TOTP.Base32String.test.base32String "error")
testTable : List (Int, String, (TOTP.Algorithm.Algorithm, Base32String))
testTable =
[ ( 59, "94287082", ( TOTP.Algorithm.SHA1, seed ) )
, ( 59, "46119246", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 59, "90693936", ( TOTP.Algorithm.SHA512, seed64 ) )
, ( 1111111109, "07081804", ( TOTP.Algorithm.SHA1, seed ) )
, ( 1111111109, "68084774", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 1111111109, "25091201", ( TOTP.Algorithm.SHA512, seed64 ) )
, ( 1111111111, "14050471", ( TOTP.Algorithm.SHA1, seed ) )
, ( 1111111111, "67062674", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 1111111111, "99943326", ( TOTP.Algorithm.SHA512, seed64 ) )
, ( 1234567890, "89005924", ( TOTP.Algorithm.SHA1, seed ) )
, ( 1234567890, "91819424", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 1234567890, "93441116", ( TOTP.Algorithm.SHA512, seed64 ) )
, ( 2000000000, "69279037", ( TOTP.Algorithm.SHA1, seed ) )
, ( 2000000000, "90698825", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 2000000000, "38618901", ( TOTP.Algorithm.SHA512, seed64 ) )
, ( 20000000000, "65353130", ( TOTP.Algorithm.SHA1, seed ) )
, ( 20000000000, "77737706", ( TOTP.Algorithm.SHA256, seed32 ) )
, ( 20000000000, "47863826", ( TOTP.Algorithm.SHA512, seed64 ) )
]
testTable
|> List.map (\(secs, _, (alg, secret)) -> generateTOTP alg { outputLength = 8, periodSeconds = 30 } secret (Time.millisToPosix (secs * 1000)))
--> List.map (\(_, answer, _) -> Ok answer) testTable
test : { valueT : Basics.Int -> Time.Posix -> ValueT, newValueT : Basics.Int -> ValueT, hexCounter : ValueT -> String, dynamicTruncation : Basics.Int -> Array Basics.Int -> Maybe String, base32String : String -> Base32String }
Exposed functions to facilitate unit testing of this library