import pyotp import qrcode import io from PyQt6.QtGui import QPixmap, QImage def generate_secret() -> str: return pyotp.random_base32() def get_totp(secret: str) -> pyotp.TOTP: return pyotp.TOTP(secret) def verify_code(secret: str, code: str) -> bool: if not secret or not code: return False totp = pyotp.TOTP(secret) return totp.verify(code.strip(), valid_window=1) def get_current_code(secret: str) -> str: return pyotp.TOTP(secret).now() def time_remaining() -> int: """Secondes restantes avant rotation du code TOTP.""" import time return 30 - (int(time.time()) % 30) def get_provisioning_uri(secret: str, account: str = "WGSecure", issuer: str = "WGSecure") -> str: totp = pyotp.TOTP(secret) return totp.provisioning_uri(name=account, issuer_name=issuer) def generate_qr_pixmap(secret: str, account: str = "WGSecure") -> QPixmap: uri = get_provisioning_uri(secret, account) qr = qrcode.QRCode(box_size=6, border=2) qr.add_data(uri) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") buf = io.BytesIO() img.save(buf, format="PNG") buf.seek(0) data = buf.read() qimage = QImage.fromData(data) return QPixmap.fromImage(qimage)