added happ crypt4 links
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import base64
|
||||
import logging
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
|
||||
|
||||
from config.settings import Settings
|
||||
|
||||
CRYPT4_PREFIX = "happ://crypt4/"
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _load_crypt4_public_key() -> Optional[RSAPublicKey]:
|
||||
"""Load and cache the happ crypt4 public key from the project root."""
|
||||
pem_path = Path(__file__).resolve().parent.parent.parent / "happ-crypt4.pem"
|
||||
try:
|
||||
pem_bytes = pem_path.read_bytes()
|
||||
key = serialization.load_pem_public_key(pem_bytes)
|
||||
return key if isinstance(key, RSAPublicKey) else None
|
||||
except FileNotFoundError:
|
||||
logging.error("Crypt4 public key file not found at %s", pem_path)
|
||||
except Exception as exc:
|
||||
logging.error("Failed to load crypt4 public key: %s", exc, exc_info=True)
|
||||
return None
|
||||
|
||||
|
||||
def _encrypt_raw_link(raw_link: str) -> Optional[str]:
|
||||
"""Encrypt the raw subscription URL with RSA PKCS#1 v1.5 and return base64 payload."""
|
||||
public_key = _load_crypt4_public_key()
|
||||
if not public_key:
|
||||
return None
|
||||
|
||||
try:
|
||||
encrypted = public_key.encrypt(raw_link.encode("utf-8"), padding.PKCS1v15())
|
||||
return base64.urlsafe_b64encode(encrypted).decode("utf-8")
|
||||
except Exception as exc:
|
||||
logging.error("Failed to encrypt config link with crypt4: %s", exc, exc_info=True)
|
||||
return None
|
||||
|
||||
|
||||
def prepare_config_links(settings: Settings, raw_link: Optional[str]) -> Tuple[Optional[str], Optional[str]]:
|
||||
"""
|
||||
Build the user-facing connection key and the URL for the connect button.
|
||||
|
||||
Returns (display_link, button_link). When CRYPT4 is enabled the display link
|
||||
is encrypted and prefixed with happ://crypt4/, and the button link is wrapped
|
||||
with CRYPT4_REDIRECT_URL if provided.
|
||||
"""
|
||||
if not raw_link:
|
||||
return None, None
|
||||
|
||||
cleaned = raw_link.strip()
|
||||
if not cleaned:
|
||||
return None, None
|
||||
|
||||
display_link = cleaned
|
||||
button_link = cleaned
|
||||
|
||||
if settings.CRYPT4_ENABLED:
|
||||
encrypted_payload = _encrypt_raw_link(cleaned)
|
||||
if encrypted_payload:
|
||||
display_link = f"{CRYPT4_PREFIX}{encrypted_payload}"
|
||||
button_link = display_link
|
||||
else:
|
||||
logging.error("CRYPT4_ENABLED is set but encryption failed; using raw link as fallback.")
|
||||
|
||||
redirect_base = (settings.CRYPT4_REDIRECT_URL or "").strip()
|
||||
if redirect_base and settings.CRYPT4_ENABLED and display_link:
|
||||
button_link = f"{redirect_base}{display_link}"
|
||||
|
||||
return display_link, button_link
|
||||
Reference in New Issue
Block a user