wraithdu Posted September 21, 2013 Share Posted September 21, 2013 (edited) I've had this one rolling around my brain for a while now. And while I can't take credit for much of anything at this point since it's just implementation, here's a framework for Time-based One-Time Password authentication, ie Google Authenticator. I've added links in all the places where I've harvested code. I'm planning on building this into an actual authenticator app, so this is just step one. As always, thanks to everyone whose code contributed. _GAuth.au3 expandcollapse popup#include-once #include <_HMAC.au3> #include <Date.au3> ;; http://tools.ietf.org/html/rfc6238 Func _GenerateTOTP($key, $keyIsBase32 = True, $time = Default, $period = 30, $digits = 6) Local $DIGITS_POWER[9] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000] ; time is some number of seconds If $time = Default Then $time = _GetUnixTimeUTC() $time = StringFormat("%016X", Floor($time / $period)) If $keyIsBase32 Then $key = _Base32ToHex($key, True) ; return binary Else $key = StringToBinary($key) EndIf ; HMAC function expects binary arguments Local $hash = _HMAC_SHA1($key, Binary("0x" & $time)) Local $offset = BitAND(BinaryMid($hash, BinaryLen($hash), 1), 0xf) Local $otp = BitOR(BitShift(BitAND(BinaryMid($hash, $offset + 1, 1), 0x7f), -24), _ BitShift(BitAND(BinaryMid($hash, $offset + 2, 1), 0xff), -16), _ BitShift(BitAND(BinaryMid($hash, $offset + 3, 1), 0xff), -8), _ BitAND(BinaryMid($hash, $offset + 4, 1), 0xff) _ ) $otp = Mod($otp, $DIGITS_POWER[$digits]) Return StringFormat("%0" & $digits & "i", $otp) EndFunc ;; http://www.autoitscript.com/forum/topic/153617-seconds-since-epoch-aka-unix-timestamp/ Func _GetUnixTimeUTC() ; returns number of seconds since EPOCH in UTC Local $aSysTimeInfo = _Date_Time_GetTimeZoneInformation() Local $utcTime = "" Local $sDate = _NowCalc() If $aSysTimeInfo[0] = 2 Then $utcTime = _DateAdd('n', $aSysTimeInfo[1] + $aSysTimeInfo[7], $sDate) Else $utcTime = _DateAdd('n', $aSysTimeInfo[1], $sDate) EndIf Return _DateDiff('s', "1970/01/01 00:00:00", $utcTime) EndFunc ;; http://tomeko.net/online_tools/base32.php?lang=en Func _Base32ToHex($sInput, $returnBinary = False) $sInput = StringRegExpReplace(StringUpper($sInput), "[^A-Z2-7]", "") Local $key = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" Local $buffer = 0, $bitsLeft = 0, $i = 0, $count = 0, $output = "", $val While $i < StringLen($sInput) $val = StringInStr($key, StringMid($sInput, $i + 1, 1)) - 1 ; StringInStr returns 1 as 1st position If $val >=0 And $val < 32 Then $buffer = BitOR(BitShift($buffer, -5), $val) $bitsLeft += 5 If $bitsLeft >= 8 Then $output &= Chr(BitAND(BitShift($buffer, $bitsLeft - 8), 0xFF)) $bitsLeft -= 8 EndIf EndIf $i += 1 WEnd If $bitsLeft > 0 Then $buffer = BitShift($buffer, -5) $output &= Chr(BitAND(BitShift($buffer, $bitsLeft - 3), 0xFF)) EndIf If $returnBinary Then Return StringToBinary($output) Else Return $output EndIf EndFunc #cs Alternate base32 to hex functions Func _b32toh($input) $input = StringRegExpReplace(StringUpper($input), "[^A-Z2-7]", "") Local $ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" Local $bits = "", $hex = "", $val, $i For $i = 0 To StringLen($input) - 1 $val = StringInStr($ch, StringMid($input, $i + 1, 1)) - 1 $bits &= StringFormat("%05s", _itob($val)) Next $i = 0 Local $chunk While ($i + 4) <= StringLen($bits) $chunk = StringMid($bits, $i + 1, 4) $hex &= StringFormat("%X", _btoi($chunk)) $i += 4 WEnd Return $hex EndFunc ; int to binary (0's and 1's) string Func _itob($int) Local $o = "" While $int $o = BitAND($int, 1) & $o $int = BitShift($int, 1) WEnd Return $o EndFunc ; binary (0's and 1's) string to int Func _btoi($b) Local $p = 0, $o = 0 For $i = StringLen($b) To 1 Step -1 $o += (2 ^ $p) * Number(StringMid($b, $i, 1)) $p += 1 Next Return $o EndFunc #ce Func _TOTPTestVectors() #cs Test vectors operate in HOTP mode. The test token shared secret uses the ASCII string value "12345678901234567890". With Time Step X = 30, and the Unix epoch as the initial value to count time steps, where T0 = 0, the TOTP algorithm will display the following values for specified modes and timestamps. +-------------+--------------+------------------+----------+--------+ | Time (sec) | UTC Time | Value of T (hex) | TOTP | Mode | +-------------+--------------+------------------+----------+--------+ | 59 | 1970-01-01 | 0000000000000001 | 94287082 | SHA1 | | | 00:00:59 | | | | | 1111111109 | 2005-03-18 | 00000000023523EC | 07081804 | SHA1 | | | 01:58:29 | | | | | 1111111111 | 2005-03-18 | 00000000023523ED | 14050471 | SHA1 | | | 01:58:31 | | | | | 1234567890 | 2009-02-13 | 000000000273EF07 | 89005924 | SHA1 | | | 23:31:30 | | | | | 2000000000 | 2033-05-18 | 0000000003F940AA | 69279037 | SHA1 | | | 03:33:20 | | | | | 20000000000 | 2603-10-11 | 0000000027BC86AA | 65353130 | SHA1 | | | 11:33:20 | | | | +-------------+--------------+------------------+----------+--------+ #ce Local $times[6] = [59, 1111111109, 1111111111, 1234567890, 2000000000, 20000000000] For $i = 0 To 5 ConsoleWrite(StringFormat("%016X", Floor($times[$i] / 30)) & " : " & _ _GenerateTOTP("12345678901234567890", False, $times[$i], 30, 8) & @CRLF) Next EndFunc _HMAC.au3 expandcollapse popup#include-once #include <Crypt.au3> ;; http://www.autoitscript.com/forum/topic/145556-solved-hmac-sha1/?p=1028830 Func _HMAC_SHA1($key, $message) If Not IsBinary($key) Then $key = Binary($key) If Not IsBinary($message) Then $message = Binary($message) Local $blocksize = 64 Local $a_opad[$blocksize], $a_ipad[$blocksize] Local Const $oconst = 0x5C, $iconst = 0x36 Local $opad = Binary(''), $ipad = Binary('') If BinaryLen($key) > $blocksize Then $key = _Crypt_HashData($key, $CALG_SHA1) For $i = 1 To BinaryLen($key) $a_ipad[$i-1] = Number(BinaryMid($key, $i, 1)) $a_opad[$i-1] = Number(BinaryMid($key, $i, 1)) Next For $i = 0 To $blocksize - 1 $a_opad[$i] = BitXOR($a_opad[$i], $oconst) $a_ipad[$i] = BitXOR($a_ipad[$i], $iconst) Next For $i = 0 To $blocksize - 1 $ipad &= Binary('0x' & Hex($a_ipad[$i], 2)) $opad &= Binary('0x' & Hex($a_opad[$i], 2)) Next Return _Crypt_HashData($opad & _Crypt_HashData($ipad & $message, $CALG_SHA1), $CALG_SHA1) EndFunc Func _HMAC_MD5($key, $message) If Not IsBinary($key) Then $key = Binary($key) If Not IsBinary($message) Then $message = Binary($message) Local $blocksize = 64 Local $a_opad[$blocksize], $a_ipad[$blocksize] Local Const $oconst = 0x5C, $iconst = 0x36 Local $opad = Binary(''), $ipad = Binary('') If BinaryLen($key) > $blocksize Then $key = _Crypt_HashData($key, $CALG_MD5) For $i = 1 To BinaryLen($key) $a_ipad[$i-1] = Number(BinaryMid($key, $i, 1)) $a_opad[$i-1] = Number(BinaryMid($key, $i, 1)) Next For $i = 0 To $blocksize - 1 $a_opad[$i] = BitXOR($a_opad[$i], $oconst) $a_ipad[$i] = BitXOR($a_ipad[$i], $iconst) Next For $i = 0 To $blocksize - 1 $ipad &= Binary('0x' & Hex($a_ipad[$i], 2)) $opad &= Binary('0x' & Hex($a_opad[$i], 2)) Next Return _Crypt_HashData($opad & _Crypt_HashData($ipad & $message, $CALG_MD5), $CALG_MD5) EndFunc Example: Use the test vectors function to test HOTP mode, or visit http://gauth.apps.gbraad.nl/ for a live test site. The default account uses "JBSWY3DPEHPK3PXP" as the key ( https://code.google.com/p/google-authenticator/wiki/KeyUriFormat ). ConsoleWrite(_GenerateTOTP("JBSWY3DPEHPK3PXP") & @CRLF) Edited September 21, 2013 by wraithdu KLM, Colduction, TheDcoder and 1 other 2 2 Link to comment Share on other sites More sharing options...
sheck Posted January 28, 2014 Share Posted January 28, 2014 (edited) Nice. I was just going to write my own, but it's already done and posted. Thanks. You saved me a bunch of time. This worked perfectly. Tested with Android Google Authenticator. Edited January 28, 2014 by sheck Live and Learn, 'cause Knowledge is Super Power. Link to comment Share on other sites More sharing options...
Lefiya Posted November 6, 2018 Share Posted November 6, 2018 (edited) 嗨〜 我將此UDF用於TOTP,但OTP不正確。 我找不到錯誤,你能幫幫我嗎?謝謝〜 (我在UTC + 8) 此代碼生成值<> http://gauth.apps.gbraad.nl/ value 我也使用谷歌 身份驗證器 <> http://gauth.apps.gbraad.nl/ 值。 昏暗$ OTP = _GenerateTOTP (“JBSWY3DPEHPK3PXP” ,真,默認,30 ,6 ) Translation: Hi~ I use this UDF for TOTP, but the OTP is incorrect. I can't find the error, can you help me? Thank you~ (I am at UTC + 8)This code generates a value <> http://gauth.apps.gbraad.nl/ valueI also use the Google Authenticator <> http://gauth.apps.gbraad.nl/ value. Dim $ OTP = _GenerateTOTP ("JBSWY3DPEHPK3PXP", true, default, 30, 6) Edited November 6, 2018 by Melba23 Added translation Link to comment Share on other sites More sharing options...
argumentum Posted November 8, 2018 Share Posted November 8, 2018 (edited) On 11/6/2018 at 9:24 AM, Lefiya said: I use this UDF for TOTP, but the OTP is incorrect I tested the code as shown and it works just fine with "JBSWY3DPEHPK3PXP" and "alice@google.com" on http://gauth.apps.gbraad.nl/ PS: http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/ may have what you need, as it works like the link above. PS2: UTC is UTC. UTC+8 is YOUR time. Use UTC =) Edited November 8, 2018 by argumentum more info Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Lefiya Posted November 12, 2018 Share Posted November 12, 2018 (edited) On 2018/11/9 at 12:59 AM, argumentum said: 我測試了所顯示的代碼,它與http://gauth.apps.gbraad.nl/上的“JBSWY3DPEHPK3PXP”和“ alice@google.com ” 一樣正常工作 PS:http: //blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/ 可能有你需要的東西,因為它像上面的鏈接一樣工作。 PS2:UTC是UTC。UTC + 8是你的時間。使用UTC =) Thank you for your heip ^^ but i understand about how to use... Can you heip me again? thx~ And why use >> ConsoleWrite(_GenerateTOTP("JBSWY3DPEHPK3PXP") & @CRLF) == 8 What mean about 8? The site OTP <> code OTP... Video: expandcollapse popup#include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Constants.au3> #include <GuiListBox.au3> #include <GuiComboBox.au3> #include <GuiListView.au3> #include <Array.au3> #include <Misc.au3> #include <Process.au3> #include <GUIConstants.au3> #include <EditConstants.au3> #Include <GuiEdit.au3> #include <APIConstants.au3> #include <GDIPlus.au3> #include <Memory.au3> #include <WinAPIEx.au3> #include <MsgBoxConstants.au3> #include <Access.au3> #include <Thread.au3> #include <GuiIPAddress.au3> #include <Crypt.au3> #include <Excel.au3> #include <GuiMenu.au3> #include <_HMAC.au3> #include <_GAuth.au3> #include <math.au3> #include <Clipboard.au3> Dim $a, $n Opt("GUIOnEventMode", 1) $Form1 = GUICreate('GAuth', 500, 500, -1, -1) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_EVENT_CLOSE") $Edit1 = GUICtrlCreateEdit('',20,20,460,410) GUICtrlCreateButton('Grt OTP',200,450,100,30,$BS_DEFPUSHBUTTON) GUICtrlSetOnEvent(-1, "_RUN") GUISetState(@SW_SHOW) _SetWindowPos($Form1,-1,-1,-1,-1,$HWND_TOPMOST,$SWP_NOMOVE+$SWP_NOSIZE);;TOP While 1 Sleep(100) WEnd Func GUI_EVENT_CLOSE() Exit EndFunc Func _RUN() Dim $unixTime = _GetUnixTimeUTC() Dim $time = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC Dim $easy0 = ConsoleWrite(_GenerateTOTP("JBSWY3DPEHPK3PXP") & @CRLF) Dim $easy1 = _GenerateTOTP("JBSWY3DPEHPK3PXP", True, Default, 30, 6) Dim $counter = Int($unixTime) / 30 Dim $T = Floor($counter) Dim $key = _HMAC_SHA1('JBSWY3DPEHPK3PXP',$T) Dim $Offset = StringRight($key,1) If StringRegExp($Offset,'[a-fA-F]',0) = 1 Then If $Offset = 'A' Then $Offset = '10' If $Offset = 'B' Then $Offset = '11' If $Offset = 'C' Then $Offset = '12' If $Offset = 'D' Then $Offset = '13' If $Offset = 'E' Then $Offset = '14' If $Offset = 'F' Then $Offset = '15' EndIf $m = StringSplit($key,'x') $Sbits = StringMid($m[2],$Offset,8) ;;---hex $Sbits2 = StringMid ($Sbits,5,2) & StringMid ($Sbits,3,6) ;;---hex to dec Dim $s = 7 Dim $tenVal = Null, $num = Null, $num2 = Null For $i = 0 to 7 $num = StringMid ($Sbits2,$i+1,1) If StringRegExp($num,'[a-fA-F]',0) = 1 Then If $num = 'A' Then $num = '10' If $num = 'B' Then $num = '11' If $num = 'C' Then $num = '12' If $num = 'D' Then $num = '13' If $num = 'E' Then $num = '14' If $num = 'F' Then $num = '15' EndIf $num2 = $num * 16 ^ $s $s -= 1 $tenVal += $num2 ;;dec Next $Digit = 6 ;;6 digits key $OTP = Mod($tenVal,10^$Digit)-1 ;;---Number of digits: 6 If StringLen($OTP) < 6 Then $a = 6 - StringLen($OTP) If $a = 6 Then $OTP = '000000' & Mod($tenVal,10^6) If $a = 5 Then $OTP = '00000' & Mod($tenVal,10^6) If $a = 4 Then $OTP = '0000' & Mod($tenVal,10^6) If $a = 3 Then $OTP = '000' & Mod($tenVal,10^6) If $a = 2 Then $OTP = '00' & Mod($tenVal,10^6) If $a = 1 Then $OTP = '0' & Mod($tenVal,10^6) EndIf GUICtrlSetData($Edit1, 'Basic' & @CRLF & '===================' & @CRLF & '$unixTime: ' & $unixTime & @CRLF & 'unix to time: ' & _DateAdd('s',$unixTime,"1970/01/01 00:00:00") & @CRLF & '$time: ' & $time & @CRLF & @CRLF & 'wraithdu code' & @CRLF & '===================' & @CRLF & 'ConsoleWrite(_GenerateTOTP("JBSWY3DPEHPK3PXP") & @CRLF):' & $easy0 & @CRLF & '_GenerateTOTP:' & $easy1 & @CRLF & @CRLF & 'my code' & @CRLF & '===================' & @CRLF & '$counter: ' & $counter & @CRLF & '$T: ' & $T & @CRLF & '$key: ' & $key & @CRLF & '$Sbits: ' & $Sbits & @CRLF & '$tenVal: ' & $tenVal & @CRLF & '$OTP: ' & $OTP) EndFunc Func _SetWindowPos($hWnd,$x,$y,$cX,$cY,$hWndInsertAfter = -1,$wFlags = 1) DllCall("user32.dll","long","SetWindowPos","long",$hWnd,"long",$hWndInsertAfter,"long",$x,"long",$y,"long",$cX,"long",$cY,"long",$wFlags) EndFunc;==>_SetWindowPos Edited November 12, 2018 by Lefiya Link to comment Share on other sites More sharing options...
argumentum Posted November 12, 2018 Share Posted November 12, 2018 5 hours ago, Lefiya said: And why use >> ConsoleWrite(_GenerateTOTP("JBSWY3DPEHPK3PXP") & @CRLF) == 8 The " == 8", I do not see anywhere AND would be useless. The StringLen($OfGenertatedTOTP) would be 6 anyway ( as declared in the example). As long as the 2 devices ( the server side and client side ) have the same time ( UTC time ), the original code shows to perform as advertised. PS: The " == 8" is because you added the "@CRLF" in your implementation and ConsoleWrite reports to have written 6 ( $OfGenertatedTOTP ) + 2 ( @CRLF ). The rest I can not understand, as I am not a programmer. Just a kind soul to copy and paste to see if it works, or not. =/ I can no longer help. And since you are attempting a new implementation, kindly use the help and support forum, referencing this topic. Lefiya 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Lefiya Posted November 12, 2018 Share Posted November 12, 2018 7 minutes ago, argumentum said: “== 8”,我什麼都看不到,也沒用。無論如何,StringLen($ OfGenertatedTOTP)將為6(如示例中所聲明的)。只要2個設備(服務器端和客戶端)具有相同的時間(UTC時間),原始代碼就會顯示為廣告執行。 PS:“== 8”是因為您在實現中添加了“@CRLF”,而ConsoleWrite報告中寫入了6($ OfGenertatedTOTP)+ 2(@CRLF)。 其餘我無法理解,因為我不是程序員。只是一個善良的複制和粘貼靈魂,看看它是否有效。= / 我再也無法幫助了。由於您正在嘗試新的實施,請使用幫助和支持論壇,引用此主題。 thank you~ for everything^^ i think maybe demo site server time and i different... Can i inquire you about Your location?(UTC+?) i want to try it~ thank you very much~ Link to comment Share on other sites More sharing options...
Moderators JLogan3o13 Posted November 12, 2018 Moderators Share Posted November 12, 2018 @Lefiya in the future please just hit reply rather than quoting everything everyone says. We know what we said, we were there when we said it "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum! Link to comment Share on other sites More sharing options...
argumentum Posted November 12, 2018 Share Posted November 12, 2018 (edited) 34 minutes ago, Lefiya said: Can i inquire you about Your location?(UTC+?) Mine is "-5" but read about UTC and you will see that is not important if I'm in "-5" and you are in "+8", as we are plus or minus of the reference. PS: ConsoleWrite('GetMyTimeUTC() = "' & GetMyTimeUTC() & '"' & @CRLF) Func GetMyTimeUTC() Local $tTime = _Date_Time_EncodeFileTime(@MON, @MDAY, @YEAR, @HOUR, @MIN, @SEC) Local $tLocal = _Date_Time_LocalFileTimeToFileTime($tTime) Return _Date_Time_FileTimeToStr($tLocal, 1) EndFunc ;==>GetMyTimeUTC PS2: https://www.autoitscript.com/forum/topic/182902-autoit-real-time-server-with-inet/?do=findComment&comment=1313452 Edited November 12, 2018 by argumentum Lefiya 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
TheDcoder Posted December 14, 2022 Share Posted December 14, 2022 Thanks for sharing the UDF and I apologize in advance for posting in such an old topic, but I believe I found a bug. The OTP generation isn't working properly on my client's computer and I narrowed it down the function to convert base32 to hex, which is the part acting faulty on my client's computer, I haven't dug deeper so I have no idea what's going wrong. However the bug that I want to report here is that the given alternative function seems to be omitting the final hex digit for some reason... Here's my code for testing: For $iKey = 0 To 100 ConsoleWrite('Input: ' & $iKey & @CRLF) ConsoleWrite('_Base32ToHex: ' & _Base32ToHex(String($iKey), True) & @CRLF) ConsoleWrite('_b32toh: ' & '0x' & _b32toh(String($iKey)) & @CRLF) Next And the output: expandcollapse popupInput: 0 _Base32ToHex: _b32toh: 0x Input: 1 _Base32ToHex: _b32toh: 0x Input: 2 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 3 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 4 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 5 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 6 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 7 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 8 _Base32ToHex: _b32toh: 0x Input: 9 _Base32ToHex: _b32toh: 0x Input: 10 _Base32ToHex: _b32toh: 0x Input: 11 _Base32ToHex: _b32toh: 0x Input: 12 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 13 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 14 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 15 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 16 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 17 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 18 _Base32ToHex: _b32toh: 0x Input: 19 _Base32ToHex: _b32toh: 0x Input: 20 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 21 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 22 _Base32ToHex: 0xD680 _b32toh: 0xD6 Input: 23 _Base32ToHex: 0xD6C0 _b32toh: 0xD6 Input: 24 _Base32ToHex: 0xD700 _b32toh: 0xD7 Input: 25 _Base32ToHex: 0xD740 _b32toh: 0xD7 Input: 26 _Base32ToHex: 0xD780 _b32toh: 0xD7 Input: 27 _Base32ToHex: 0xD7C0 _b32toh: 0xD7 Input: 28 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 29 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 30 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 31 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 32 _Base32ToHex: 0xDE80 _b32toh: 0xDE Input: 33 _Base32ToHex: 0xDEC0 _b32toh: 0xDE Input: 34 _Base32ToHex: 0xDF00 _b32toh: 0xDF Input: 35 _Base32ToHex: 0xDF40 _b32toh: 0xDF Input: 36 _Base32ToHex: 0xDF80 _b32toh: 0xDF Input: 37 _Base32ToHex: 0xDFC0 _b32toh: 0xDF Input: 38 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 39 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 40 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 41 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 42 _Base32ToHex: 0xE680 _b32toh: 0xE6 Input: 43 _Base32ToHex: 0xE6C0 _b32toh: 0xE6 Input: 44 _Base32ToHex: 0xE700 _b32toh: 0xE7 Input: 45 _Base32ToHex: 0xE740 _b32toh: 0xE7 Input: 46 _Base32ToHex: 0xE780 _b32toh: 0xE7 Input: 47 _Base32ToHex: 0xE7C0 _b32toh: 0xE7 Input: 48 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 49 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 50 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 51 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 52 _Base32ToHex: 0xEE80 _b32toh: 0xEE Input: 53 _Base32ToHex: 0xEEC0 _b32toh: 0xEE Input: 54 _Base32ToHex: 0xEF00 _b32toh: 0xEF Input: 55 _Base32ToHex: 0xEF40 _b32toh: 0xEF Input: 56 _Base32ToHex: 0xEF80 _b32toh: 0xEF Input: 57 _Base32ToHex: 0xEFC0 _b32toh: 0xEF Input: 58 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 59 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 60 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 61 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 62 _Base32ToHex: 0xF680 _b32toh: 0xF6 Input: 63 _Base32ToHex: 0xF6C0 _b32toh: 0xF6 Input: 64 _Base32ToHex: 0xF700 _b32toh: 0xF7 Input: 65 _Base32ToHex: 0xF740 _b32toh: 0xF7 Input: 66 _Base32ToHex: 0xF780 _b32toh: 0xF7 Input: 67 _Base32ToHex: 0xF7C0 _b32toh: 0xF7 Input: 68 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 69 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 70 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 71 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 72 _Base32ToHex: 0xFE80 _b32toh: 0xFE Input: 73 _Base32ToHex: 0xFEC0 _b32toh: 0xFE Input: 74 _Base32ToHex: 0xFF00 _b32toh: 0xFF Input: 75 _Base32ToHex: 0xFF40 _b32toh: 0xFF Input: 76 _Base32ToHex: 0xFF80 _b32toh: 0xFF Input: 77 _Base32ToHex: 0xFFC0 _b32toh: 0xFF Input: 78 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 79 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 80 _Base32ToHex: _b32toh: 0x Input: 81 _Base32ToHex: _b32toh: 0x Input: 82 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 83 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 84 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 85 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 86 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 87 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 88 _Base32ToHex: _b32toh: 0x Input: 89 _Base32ToHex: _b32toh: 0x Input: 90 _Base32ToHex: _b32toh: 0x Input: 91 _Base32ToHex: _b32toh: 0x Input: 92 _Base32ToHex: 0xD0 _b32toh: 0xD Input: 93 _Base32ToHex: 0xD8 _b32toh: 0xD Input: 94 _Base32ToHex: 0xE0 _b32toh: 0xE Input: 95 _Base32ToHex: 0xE8 _b32toh: 0xE Input: 96 _Base32ToHex: 0xF0 _b32toh: 0xF Input: 97 _Base32ToHex: 0xF8 _b32toh: 0xF Input: 98 _Base32ToHex: _b32toh: 0x Input: 99 _Base32ToHex: _b32toh: 0x Input: 100 _Base32ToHex: _b32toh: 0x As you can see, _b32toh always omits the final digit in the result when you compare it to _Base32ToHex Anybody know why this is the case? I'm too tired to debug it myself... I'll post here if I find a solution before others. EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
garbb Posted June 16, 2023 Share Posted June 16, 2023 (edited) Strangely I was unable to get the correct OTP code to be generated until I uncommented the _b32toh() code and replaced $key = _Base32ToHex($key, True) with $key = Binary('0x'&_b32toh($key)) in GenerateTOTP(). EDIT: The problem appears to be that but _b32toh("JBSWY3DPEHPK3PXP") = 0x48656C6C6F21DEADBEEF, but _Base32ToHex("JBSWY3DPEHPK3PXP") = 0x48656C6C6F21DEADBE8145. I do not know why... Edited June 16, 2023 by garbb argumentum 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now