module Data.OTP (hotp, totp) where
import Codec.Utils
import Data.Bits
import Data.HMAC
import Data.Time.Clock
import Data.Time.Clock.POSIX
hotp
:: [Octet]
-> Int
-> Int
-> Int
hotp key count digit' = truncate_hotp (hmac_sha1 key count') digit'
where truncate_hotp hmac_result digit' = snum `mod` (10 ^ digit')
where snum = fromTwosComp sbits
sbits = dt hmac_result
dt hmac_r = [(head p) .&. 0x7F] ++ (tail p)
where offsetBits = (hmacr !! 19) .&. 0xF
offset = fromTwosComp [offsetBits]
p = take 4 (drop offset hmacr)
hmacr = pad hmac_r
where pad xs = if length xs < 20 then pad (0 : xs) else xs
count' = pad (toTwosComp count)
where pad xs = if length xs < 8 then pad (0 : xs) else xs
totp
:: [Octet]
-> UTCTime
-> Int
-> Int
-> Int
totp key time digit' period = hotp key timeCounter digit'
where timePOSIX = utcTimeToPOSIXSeconds time
timeCounter = (floor timePOSIX) `div` period