Skip to content

Instantly share code, notes, and snippets.

@M0r13n
Last active April 19, 2025 12:20
Show Gist options
  • Save M0r13n/9da20bfa2f7313e2bc473d279c6a5a06 to your computer and use it in GitHub Desktop.
Save M0r13n/9da20bfa2f7313e2bc473d279c6a5a06 to your computer and use it in GitHub Desktop.
Basic HMAC-based One-Time Password Algorithm in Python
# Basic HMAC-based One-Time Password Algorithm in Python
# Based on RFC 4226 and RFC 6238
import base64
import datetime
import hashlib
import struct
import time
def dt(hmac_result: bytes) -> int:
# Generate a 4-byte string (Dynamic Truncation) and return it as a 31 bit number
offset = hmac_result[-1] & 0xf
bin_code = (hmac_result[offset] & 0x7f) << 24 \
| (hmac_result[offset + 1] & 0xff) << 16 \
| (hmac_result[offset + 2] & 0xff) << 8 \
| (hmac_result[offset + 3] & 0xff)
return bin_code
def hmac_sha1(key: bytes, message: bytes) -> bytes:
# Standard HMAC-SHA1 implementation
block_size = 64
if len(key) > block_size:
key = hashlib.sha1(key).digest()
key = key + b'\x00' * (block_size - len(key))
o_key_pad = bytes(x ^ 0x5c for x in key)
i_key_pad = bytes(x ^ 0x36 for x in key)
return hashlib.sha1(o_key_pad + hashlib.sha1(i_key_pad + message).digest()).digest()
def hotp(key: bytes, counter: int, digits: int = 6) -> int:
# HMAC-based One-Time Password Algorithm
counter_bytes = struct.pack('>Q', counter) # 8-byte counter
hmac_result = hmac_sha1(key, counter_bytes)
return int(dt(hmac_result) % (10 ** digits))
def totp(key: bytes, time_step: int = 30, digits: int = 6) -> int:
# Time-based One-Time Password Algorithm
counter = int(time.time() // time_step)
return hotp(key, counter, digits)
def main() -> None:
base32_key = "JBSWY3DPEHPK3PXP"
key = base64.b32decode(base32_key)
while True:
current_time = time.time()
time_step = 30
seconds_remaining = time_step - (current_time % time_step)
token = totp(key)
print(f'Token at {datetime.datetime.now()}: {token:06d}')
time.sleep(seconds_remaining)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment