OTP (empty) → 0.0.0.1
raw patch · 5 files changed
+117/−0 lines, 5 filesdep +Cryptodep +basedep +timesetup-changed
Dependencies added: Crypto, base, time
Files
- Data/OTP.hs +39/−0
- LICENSE +18/−0
- OTP.cabal +35/−0
- Setup.hs +2/−0
- Test/opt.hs +23/−0
+ Data/OTP.hs view
@@ -0,0 +1,39 @@+-- |Implements HMAC-Based One-Time Password Algorithm as defined in RFC 4226 and +-- Time-Based One-Time Password Algorithm as defined in RFC 6238. +module Data.OTP (hotp, totp) where + +import Codec.Utils +import Data.Bits +import Data.HMAC +import Data.Time.Clock +import Data.Time.Clock.POSIX + +-- | Compute an HOTP using secret key and counter value. +hotp + :: [Octet] -- ^ Secret key + -> Int -- ^ Counter value + -> Int -- ^ Number of digits in password + -> Int -- ^ HOTP +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 + +-- | Compute an TOTP using secret key and time. +totp + :: [Octet] -- ^ Secret key + -> UTCTime -- ^ Time + -> Int -- ^ Number of digits in password + -> Int -- ^ Period + -> Int -- ^ TOTP +totp key time digit' period = hotp key timeCounter digit' + where timePOSIX = utcTimeToPOSIXSeconds time + timeCounter = (floor timePOSIX) `div` period
+ LICENSE view
@@ -0,0 +1,18 @@+Copyright (c) 2012 Artem Leshchev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ OTP.cabal view
@@ -0,0 +1,35 @@+name: OTP +-- PVP summary: +-+------- breaking API changes +-- | | +----- non-breaking API additions +-- | | | +--- code changes with no API change +version: 0.0.0.1 +synopsis: HMAC-Based and Time-Based One-Time Passwords +description: Implements HMAC-Based One-Time Password Algorithm as defined in RFC 4226 and Time-Based One-Time Password Algorithm as defined in RFC 6238. +license: MIT +license-file: LICENSE +copyright: (c) 2012 Artem Leshchev +author: Artem Leshchev +maintainer: matshch@gmail.com +homepage: https://github.com/matshch/OTP +bug-reports: https://github.com/matshch/OTP/issues +category: Cryptography +build-type: Simple +cabal-version: >=1.8 + +library + exposed-modules: Data.OTP + build-depends: base >= 3 && < 5, Crypto >= 4, time >= 1.1 + +Test-Suite tests + type: exitcode-stdio-1.0 + main-is: Test/opt.hs + build-depends: base >= 3 && < 5, Crypto >= 4, time >= 1.1 + +source-repository head + type: git + location: git://github.com/matshch/OTP.git + +source-repository this + type: git + location: git://github.com/matshch/OTP.git + tag: v0.0.0.1
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ Test/opt.hs view
@@ -0,0 +1,23 @@+module Main where + +import Codec.Utils +import Data.OTP +import Data.Time +import System.Exit (exitFailure) + +secret_otp :: [Octet] +secret_otp = [49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57,48] + +hotp_t = zipWith (\x y -> (hotp secret_otp x 6) == y) [0..9] + [755224, 287082, 359152, 969429, 338314, 254676, 287922, 162583, 399871, 520489] + +totp_t = zipWith (\x y -> (totp secret_otp x 8 30) == y) (map (read) ["1970-01-01 00:00:59 UTC", + "2005-03-18 01:58:29 UTC", "2005-03-18 01:58:31 UTC", "2009-02-13 23:31:30 UTC", + "2033-05-18 03:33:20 UTC"]) + [94287082, 07081804, 14050471, 89005924, 69279037] +tests = hotp_t ++ totp_t + +main = if (and tests) then putStrLn "Tests succeful!" + else do + putStrLn "Tests falls!" + exitFailure