1

When I use the secret key "abcdefghijklmnop" in Google Authenticator (Android), Microsoft Authenticator (Android) and oathtool (Ubuntu 18.04.3 LTS), I get matching Time-based One-Time Password (TOTP) values. Unfortunately, I do not get a matching TOTP value when I use the same key in the following Haskell code (whether that be on Windows 10 or Ubuntu 18.04.3 LTS):

{-# LANGUAGE OverloadedStrings #-}
import Data.OTP
import Data.Time.Clock

main = do
    -- This key is just for testing purposes
    let theSecretKey = "abcdefghijklmnop"

    -- See http://hackage.haskell.org/package/OTP-0.1.0.0/docs/Data-OTP.html#g:2
    curTime <- getCurrentTime
    let theTOTP = totp SHA1 theSecretKey curTime 30 6
    print theTOTP

I reckon this means the above code has a bug. If I were to hazard a guess, either "theSecretKey" or "curTime" is being passed in an invalid format, but I'm not sure which.

What should I change in the above code to correctly call the totp function?

NOTE: While testing with oathtool, I was able to verify that I should be using the SHA1 hashing algorithm

Shawn Eary
  • 684
  • 2
  • 7
  • 21
  • 1
    Can you clarify? When you get the values from Google Authenticator and Microsoft Authenticator, you are using the **same** value of _curTime_ as you are in the Haskell code? – Bob Dalgleish Jan 14 '20 at 20:46
  • Unfortunately, I'm not sure where Google Authenticator and Microsoft Authenticator for Android are getting the time from. The above Haskell code is running on Windows 10 though. I just ran getCurrentTime on WinCHCi at 3:35 PM CDT and got this back which seems right: 2020-01-14 21:35:01.9539814 UTC I'm not sure what to do with the milliseconds though. The example on the Data.OTP site does not show milliseconds. – Shawn Eary Jan 14 '20 at 21:32
  • I confirmed via oathtool that the algorithm should be likely be SHA1. I'm editing my question to remove the references to SHA512 and SHA256. – Shawn Eary Jan 14 '20 at 22:18
  • The issue is that the TOTP result is intimately dependent on the time passed in. That means that you cannot directly compare a TOTP from two different authorities because they will use different times, hence will return different values. – Bob Dalgleish Jan 15 '20 at 13:35
  • The TOTP I'm getting on Android via Windows and Google Authenticator is identical to the TOTP I'm getting in UBuntu via oathtool on separate machine. – Shawn Eary Jan 15 '20 at 13:58

1 Answers1

0

The reason you aren't getting the correct output is, the Base32 encoding used by the apps and tools you mentioned above for the secret key. Therefore, I would suggest you to decode the secret key with Base32 decryption and then apply the totp function to get the correct TOTP value.

The decodeBase32 function from the package Data.ByteString.Base32 can come handy when decoding the key.

CodeMascot
  • 855
  • 1
  • 10
  • 19