Code: Select all
Procedure.s TOTP(Secret$)
Protected.i Last4Bits, v, SecretLen, i, Offset
Protected.q Interval
Protected Digest$, codeString$, Interval$
Protected *Base32, *Secret, *Interval
If Secret$ <> ""
*Base32 = AllocateMemory(Len(Secret$), #PB_Memory_NoClear)
If *Base32
SecretLen = Base32Decoder(Secret$, *Base32, MemorySize(*Base32))
If SecretLen
*Secret = AllocateMemory(SecretLen, #PB_Memory_NoClear)
If *Secret
CopyMemory(*Base32, *Secret, SecretLen)
Interval = DateUTC() / 30
Interval$ = RSet(Hex(Interval), 16, "0")
*Interval = AllocateMemory(8)
If *Interval
For i = 0 To 7
PokeA(*Interval + i, Val("$" + Mid(Interval$, 1 + i * 2, 2)))
Next i
Digest$ = hmac(*Interval, *Secret)
Offset = Val("$" + Right(Digest$, 1))
v = (Val("$" + Mid(Digest$, 1 + (Offset + 0) * 2, 2)) & $7F) << 24
v | (Val("$" + Mid(Digest$, 1 + (Offset + 1) * 2, 2)) << 16)
v | (Val("$" + Mid(Digest$, 1 + (Offset + 2) * 2, 2)) << 8)
v | Val("$" + Mid(Digest$, 1 + (Offset + 3) * 2, 2))
codeString$ = RSet(Str(v % 1000000), 6, "0")
FreeMemory(*Interval)
EndIf
FillMemory(*Secret, SecretLen)
FreeMemory(*Secret)
EndIf
EndIf
FreeMemory(*Base32)
EndIf
EndIf
ProcedureReturn codeString$
EndProcedure
Code: Select all
XIncludeFile "Base32.pbi"
XIncludeFile "HMAC.pbi"
https://www.purebasic.fr/english/viewtopic.php?t=85009