vpn/backend/security.py
2026-09-23 01:19:36 +00:00

33 lines
942 B
Python

from __future__ import annotations
import hashlib
import hmac
import re
from cryptography.fernet import Fernet
DEVICE_UA_RE = re.compile(r"^vpnapp/v(?P<major>\d+)\.(?P<minor>\d+)/(?P<device>[0-9a-fA-F-]{36})$")
class SecretBox:
def __init__(self, key: str) -> None:
self._fernet = Fernet(key.encode("ascii"))
def seal(self, value: str) -> str:
return self._fernet.encrypt(value.encode("utf-8")).decode("ascii")
def open(self, value: str) -> str:
return self._fernet.decrypt(value.encode("ascii")).decode("utf-8")
def token_hash(token: str) -> str:
return hashlib.sha256(token.encode("utf-8")).hexdigest()
def token_matches(token: str, expected_hash: str) -> bool:
return hmac.compare_digest(token_hash(token), expected_hash)
def parse_user_agent(user_agent: str) -> str | None:
match = DEVICE_UA_RE.fullmatch(user_agent.strip())
return match.group("device") if match else None