49 lines
1.2 KiB
Python
49 lines
1.2 KiB
Python
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)
|