This commit is contained in:
jpmvaz
2026-09-13 20:03:24 +01:00
commit 0ebb8e7f4b
270 changed files with 23789 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
"""Time-based one-time passwords (TOTP, RFC 6238) using only the standard
library. Compatible with Google Authenticator, Authy, 1Password, etc."""
import base64
import hashlib
import hmac
import secrets
import struct
import time
from urllib.parse import quote
ISSUER = "MartinhalApprovalFlow"
def new_secret() -> str:
"""A new base32 secret to enroll in an authenticator app."""
return base64.b32encode(secrets.token_bytes(20)).decode()
def _code_at(secret: str, counter: int) -> str:
key = base64.b32decode(secret + "=" * (-len(secret) % 8), casefold=True)
digest = hmac.new(key, struct.pack(">Q", counter), hashlib.sha1).digest()
offset = digest[-1] & 15
number = (struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7FFFFFFF) % 1_000_000
return f"{number:06d}"
def verify(secret: str, code: str) -> bool:
"""Check a 6-digit code, allowing one 30s step of clock drift each way."""
code = (code or "").strip().replace(" ", "")
if not (secret and code.isdigit() and len(code) == 6):
return False
counter = int(time.time() // 30)
return any(hmac.compare_digest(_code_at(secret, counter + drift), code)
for drift in (-1, 0, 1))
def otpauth_uri(username: str, secret: str) -> str:
"""URI encoded as a QR code for authenticator apps."""
return (f"otpauth://totp/{quote(ISSUER)}:{quote(username)}"
f"?secret={secret}&issuer={quote(ISSUER)}&algorithm=SHA1&digits=6&period=30")