Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SHA1 and TOTP
#3
Well I did roll my own, but it got messy (keep in mind this is like a few weeks of work, and mostly as a side tinker)
It does make a code, but doesn't seem to make a new one, and not even sure that the code it is making is legit. I do have a "secretKey$" to work with, which is a fake key you would see on a typical website.

Have fun messing with this one.. I got TOTALLY burned out. The SHA1 I do not think is correct AT ALL. uhg. but I tried. Keep in mind lots of this is from c++ and python is more difficult to convert over, because I dont' know python that well. LOOOOOTTTTSSS of corrections on this one. That was most the issue.


Here is the python script - got lots of help with this one, seems everyone and their dog knows python but me LOL However, to make this work with my PWM, you have to have python installed. I do, because I am trying to learn python, but to friends who don't they wll have to use a different 2FA.

The Timestamp## I got from here, But thenI found a different one. Both work.

This python works perfect and is what I use in my app. I just have to shell out. It is fast, and not noticable, I am just OCD.

PHP Code:
import pyotp
import sys

def generate_totp
(secret_key):
    totp pyotp.TOTP(secret_key)
    return totp.now()

if 
__name__ == "__main__":
    secret_key sys.argv[1]
    totp_code generate_totp(secret_key)
    with open("totp_code.txt""w") as f:
        f.write(totp_code



Code: (Select All)
Dim secretKey As String
Dim generatedTOTP As String

' Assign the Base32 encoded secret key (this is just an example key)
secretKey$ = "JBSWY3DPEHPK3PXP"
Dim i As Integer
For i = 1 To 10
    ' Call the TOTP$ function and store the result in `generatedTOTP$`
    generatedTOTP$ = TOTP$(secretKey$)

    ' Output the generated TOTP code
    Print "Your TOTP code is: "; generatedTOTP$
    Print
Next


Function GetTimeStep
    Dim unixTime As Long
    unixTime = TimeStamp(Date$, Timer + MyTimeZone)
    GetTimeStep = unixTime \ 30 ' Divide by 30 to get the time step
End Function

Function HMAC_SHA1$ (key$, message$)
    ' Step 1: Prepare the key
    If Len(key$) > 64 Then
        key$ = SHA1$(key$) ' Assuming you have an SHA1 function
    End If

    ' Pad key to 64 bytes
    key$ = Left$(key$ + String$(64, Chr$(0)), 64)

    ' Step 2: Create inner and outer padded keys
    Dim ipad As String
    Dim opad As String
    ipad$ = ""
    opad$ = ""

    For i = 1 To 64
        ipad$ = ipad$ + Chr$(Asc(Mid$(key$, i, 1)) Xor &H36)
        opad$ = opad$ + Chr$(Asc(Mid$(key$, i, 1)) Xor &H5C)
    Next i

    ' Step 3: Hash the inner padded key with the message
    innerHash$ = SHA1$(ipad$ + message$) ' First hash (ipad + message)

    ' Step 4: Hash the outer padded key with the result of the first hash
    HMAC_SHA1$ = SHA1$(opad$ + innerHash$) ' Final HMAC-SHA1 result
End Function

Function TOTP$ (secretKey$)
    Dim timeStep As Long
    Dim timeValue As String
    Dim hmac As String
    Dim offset As Integer
    Dim otp As Long
    Dim b32d As String

    ' Step 1: Get the current time step (current time divided by 30 seconds)
    timeStep = Int(TimeStamp(Date$, Timer + MyTimeZone) / 30)
    timeValue = Str$(timeStep) ' Convert time step to string

    ' Step 2: Calculate the HMAC-SHA1 hash using the secret key and time value
    hmac = HMAC_SHA1$(DecodeBase32$(secretKey$, ""), timeValue)

    ' Step 3: Extract the dynamic offset and truncate the hash
    offset = Asc(Mid$(hmac, Len(hmac), 1)) And 15
    otp = Val("&H" + Mid$(hmac, offset + 1, 8)) And &H7FFFFFFF
    otp = otp Mod 1000000 ' Generate a 6-digit OTP

    ' Step 4: Convert the OTP to a 6-digit string and return it
    TOTP$ = Right$("000000" + LTrim$(Str$(otp)), 6)
End Function



Function SHA1$ (message$)
    ' Step 1: Message Padding
    Dim paddedMessage As String
    Dim originalLength As Long

    originalLength = Len(message$) * 8 ' Original length in bits
    paddedMessage$ = message$ + Chr$(128) ' Append '1' bit as 0x80
    While (Len(paddedMessage$) Mod 64) <> 56
        paddedMessage$ = paddedMessage$ + Chr$(0) ' Append '0' bits
    Wend

    ' Append original length as 64-bit big-endian integer
    paddedMessage$ = paddedMessage$ + MKL$(0) + MKL$(originalLength)

    ' Step 2: Process each 512-bit block
    Dim h0 As Long, h1 As Long, h2 As Long, h3 As Long, h4 As Long
    Dim a As Long, b As Long, c As Long, d As Long, e As Long
    Dim temp As Long

    h0 = &H67452301: h1 = &HEFCDAB89: h2 = &H98BADCFE: h3 = &H10325476: h4 = &HC3D2E1F0

    ' Additional processing logic goes here...

    ' Step 3: Final Output
    SHA1$ = Hex$(h0) + Hex$(h1) + Hex$(h2) + Hex$(h3) + Hex$(h4)
End Function


Function GenerateTOTP$ (secretKey$)
    Dim timeStep As Long
    Dim decodedKey As String
    Dim hmacResult As String
    Dim offset As Integer
    Dim binaryCode As Long
    Dim otp As Integer
    Dim otpStr As String

    ' Step 1: Get the time step
    timeStep = GetTimeStep

    ' Step 2: Decode the Base32 secret key
    decodedKey$ = DecodeBase32$(secretKey$, "")

    ' Step 3: Generate HMAC-SHA1
    hmacResult$ = HMAC_SHA1$(decodedKey$, MKL$(timeStep))

    ' Step 4: Extract dynamic binary code
    offset = Asc(Mid$(hmacResult$, Len(hmacResult$), 1)) And &HF
    binaryCode = (Asc(Mid$(hmacResult$, offset + 1, 1)) And &H7F) * &H1000000
    binaryCode = binaryCode Or (Asc(Mid$(hmacResult$, offset + 2, 1)) * &H10000)
    binaryCode = binaryCode Or (Asc(Mid$(hmacResult$, offset + 3, 1)) * &H100)
    binaryCode = binaryCode Or (Asc(Mid$(hmacResult$, offset + 4, 1)))

    ' Step 5: Generate the OTP code
    otp = binaryCode Mod 1000000 ' 6-digit code
    otpStr = Right$("000000" + LTrim$(Str$(otp)), 6)

    GenerateTOTP$ = otpStr
End Function


Function TimeStamp## (d$, t##) 'date and timer
    'Based on Unix Epoch time, which starts at year 1970.
    Dim l As _Integer64, l1 As _Integer64, m As _Integer64
    Dim d As _Integer64, y As _Integer64, i As _Integer64
    Dim s As _Float

    l = InStr(d$, "-")
    l1 = InStr(l + 1, d$, "-")
    m = Val(Left$(d$, l))
    d = Val(Mid$(d$, l + 1))
    y = Val(Mid$(d$, l1 + 1))
    If y < 1970 Then 'calculate shit backwards
        Select Case m 'turn the day backwards for the month
            Case 1, 3, 5, 7, 8, 10, 12: d = 31 - d '31 days
            Case 2: d = 28 - d 'special 28 or 29.
            Case 4, 6, 9, 11: d = 30 - d '30 days
        End Select
        If y Mod 4 = 0 And m < 3 Then 'check for normal leap year, and we're before it...
            d = d + 1 'assume we had a leap year, subtract another day
            If y Mod 100 = 0 And y Mod 400 <> 0 Then d = d - 1 'not a leap year if year is divisible by 100 and not 400
        End If

        'then count the months that passed after the current month
        For i = m + 1 To 12
            Select Case i
                Case 2: d = d + 28
                Case 3, 5, 7, 8, 10, 12: d = d + 31
                Case 4, 6, 9, 11: d = d + 30
            End Select
        Next

        'we should now have the entered year calculated.  Now lets add in for each year from this point to 1970
        d = d + 365 * (1969 - y) '365 days per each standard year
        For i = 1968 To y + 1 Step -4 'from 1968 onwards,backwards, skipping the current year (which we handled previously in the FOR loop)
            d = d + 1 'subtract an extra day every leap year
            If (i Mod 100) = 0 And (i Mod 400) <> 0 Then d = d - 1 'but skipping every year divisible by 100, but not 400
        Next
        s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
        TimeStamp## = -(s## + 24 * 60 * 60 - t##)
        Exit Function
    Else
        y = y - 1970
    End If

    For i = 1 To m 'for this year,
        Select Case i 'Add the number of days for each previous month passed
            Case 1: d = d 'January doestn't have any carry over days.
            Case 2, 4, 6, 8, 9, 11: d = d + 31
            Case 3 'Feb might be a leap year
                If (y Mod 4) = 2 Then 'if this year is divisible by 4 (starting in 1972)
                    d = d + 29 'its a leap year
                    If (y Mod 100) = 30 And (y Mod 400) <> 30 Then 'unless..
                        d = d - 1 'the year is divisible by 100, and not divisible by 400
                    End If
                Else 'year not divisible by 4, no worries
                    d = d + 28
                End If
            Case 5, 7, 10, 12: d = d + 30
        End Select
    Next
    d = (d - 1) + 365 * y 'current month days passed + 365 days per each standard year
    For i = 2 To y - 1 Step 4 'from 1972 onwards, skipping the current year (which we handled previously in the FOR loopp)
        d = d + 1 'add an extra day every leap year
        If (i Mod 100) = 30 And (i Mod 400) <> 30 Then d = d - 1 'but skiping every year divisible by 100, but not 400
    Next
    s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
    TimeStamp## = (s## + t##)
End Function






Function EncodeBase32$ (text$)
    ' Step 1: Convert the string to binary representation
    binaryString$ = ""
    For i = 1 To Len(text$)
        char$ = Mid$(text$, i, 1)
        asciiCode = Asc(char$)
        binaryString$ = binaryString$ + Right$("00000000" + _Bin$(asciiCode), 8)
    Next

    ' Step 2: Separate every 5 bits and pad if necessary
    paddedBinaryString$ = binaryString$
    While Len(paddedBinaryString$) Mod 5 <> 0
        paddedBinaryString$ = paddedBinaryString$ + "0"
    Wend

    ' Step 3: Convert each 5-bit segment to the corresponding Base32 character
    base32Table$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
    result$ = ""
    For i = 1 To Len(paddedBinaryString$) Step 5
        fiveBits$ = Mid$(paddedBinaryString$, i, 5)
        index = Val("&B" + fiveBits$) + 1 ' Convert binary to decimal
        result$ = result$ + Mid$(base32Table$, index, 1)
    Next

    ' Step 4: Pad the result to a multiple of 8 characters with "="
    While Len(result$) Mod 8 <> 0
        result$ = result$ + "="
    Wend

    EncodeBase32$ = result$
End Function

Function DecodeBase32$ (encoded$, decoded$)
    ' Step 1: Create a Base32 table for reverse lookup
    base32Table$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"

    ' Step 2: Remove any padding characters (=)
    encoded$ = Left$(encoded$, InStr(encoded$, "=") - 1)

    ' Step 3: Convert each Base32 character back to its 5-bit binary representation
    binaryString$ = ""
    For i = 1 To Len(encoded$)
        char$ = Mid$(encoded$, i, 1)
        index = InStr(base32Table$, char$) - 1
        binaryString$ = binaryString$ + Right$("00000" + _Bin$(index), 5)
    Next

    ' Step 4: Convert every 8 bits of the binary string back to its ASCII character
    decoded$ = ""
    For i = 1 To Len(binaryString$) Step 8
        eightBits$ = Mid$(binaryString$, i, 8)
        If Len(eightBits$) = 8 Then
            asciiCode = Val("&B" + eightBits$)
            decoded$ = decoded$ + Chr$(asciiCode)
        End If
    Next
    DecodeBase32$ = decoded$
End Function
3 out of 2 people have trouble with fractions

Reply


Messages In This Thread
SHA1 and TOTP - by Ra7eN - 08-21-2024, 01:35 AM
RE: SHA1 and TOTP - by TerryRitchie - 08-21-2024, 01:48 AM
RE: SHA1 and TOTP - by Ra7eN - 08-21-2024, 02:13 AM
RE: SHA1 and TOTP - by SMcNeill - 08-21-2024, 03:47 AM
RE: SHA1 and TOTP - by RhoSigma - 08-21-2024, 10:44 AM
RE: SHA1 and TOTP - by DSMan195276 - 08-21-2024, 04:19 AM
RE: SHA1 and TOTP - by Ra7eN - 08-21-2024, 05:14 PM
RE: SHA1 and TOTP - by Ra7eN - 08-21-2024, 09:44 PM
RE: SHA1 and TOTP - by Ra7eN - 08-22-2024, 12:01 AM
RE: SHA1 and TOTP - by Ra7eN - 08-22-2024, 12:09 AM
RE: SHA1 and TOTP - by Ra7eN - 08-22-2024, 12:25 AM
RE: SHA1 and TOTP - by SpriggsySpriggs - 08-22-2024, 11:29 AM
RE: SHA1 and TOTP - by Ra7eN - 08-22-2024, 11:37 AM
RE: SHA1 and TOTP - by DSMan195276 - 08-22-2024, 12:13 PM
RE: SHA1 and TOTP - by Ra7eN - 08-22-2024, 11:41 PM
RE: SHA1 and TOTP - by DSMan195276 - 08-23-2024, 12:32 AM
RE: SHA1 and TOTP - by Ra7eN - 08-23-2024, 12:43 AM
RE: SHA1 and TOTP - by DSMan195276 - 08-23-2024, 06:30 AM
RE: SHA1 and TOTP - by Ra7eN - 08-24-2024, 12:38 AM
RE: SHA1 and TOTP - by Kernelpanic - 08-24-2024, 08:37 PM



Users browsing this thread: 15 Guest(s)