refactor: modularize auth transport and markdown
Testing / remote-protocol-compat (0.9.5) (push) Successful in 1m4s
Testing / test (push) Successful in 1m22s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 1m7s
Package Extension / package-extension (push) Successful in 1m1s
Build & Publish Package / publish (push) Successful in 1m5s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 1m4s
Testing / test (push) Successful in 1m22s
Testing / remote-protocol-compat (0.9.3) (push) Successful in 1m7s
Package Extension / package-extension (push) Successful in 1m1s
Build & Publish Package / publish (push) Successful in 1m5s
- Split auth into focused package modules for agent keys, file keys, signing, and post-quantum transport helpers while keeping the public browser_cli.auth import surface intact. - Move transport encoding internals into a package with separate codec and binary-hoisting helpers, preserving browser_cli.transport compatibility. - Extract remote TCP auth/socket helpers and serve challenge setup out of the runtime paths to make connection handling easier to reason about. - Move the extension markdown extractor into a dedicated content/markdown folder with separate root selection, code normalization, renderer, and utils. - Centralize CLI Rich rendering helpers for tab/window tree and table output, and add rendering tests for the shared builders. - Remove local typing ignores in SDK/decorator/script plumbing and bump the package and extension version to 0.15.3.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""File-based Ed25519 keys and authorized_keys helpers."""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
||||
from cryptography.hazmat.primitives.serialization import (
|
||||
Encoding,
|
||||
NoEncryption,
|
||||
PrivateFormat,
|
||||
PublicFormat,
|
||||
load_pem_private_key,
|
||||
)
|
||||
|
||||
from browser_cli.auth.agent import AgentKey
|
||||
|
||||
def generate_keypair() -> tuple[bytes, str]:
|
||||
"""Return (private_key_pem_bytes, public_key_hex)."""
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
pem = private_key.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption())
|
||||
public_hex = private_key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw).hex()
|
||||
return pem, public_hex
|
||||
|
||||
def load_private_key(path: Path) -> Ed25519PrivateKey:
|
||||
return load_pem_private_key(path.read_bytes(), password=None)
|
||||
|
||||
def public_key_hex(key: Ed25519PrivateKey | AgentKey) -> str:
|
||||
if isinstance(key, AgentKey):
|
||||
return key.pubkey_bytes.hex()
|
||||
return key.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw).hex()
|
||||
|
||||
def load_authorized_keys_with_names(path: Path) -> list[tuple[str, str]]:
|
||||
"""Return list of (pubkey_hex, name) pairs. Name is empty string if not set."""
|
||||
if not path.exists():
|
||||
return []
|
||||
result = []
|
||||
for line in path.read_text(encoding="utf-8").splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
parts = line.split(None, 1)
|
||||
pubkey = parts[0]
|
||||
name = parts[1].strip() if len(parts) > 1 else ""
|
||||
result.append((pubkey, name))
|
||||
return result
|
||||
|
||||
def load_authorized_keys(path: Path) -> list[str]:
|
||||
return [pubkey for pubkey, _name in load_authorized_keys_with_names(path)]
|
||||
|
||||
def add_authorized_key(path: Path, pub_hex: str, name: str = "") -> bool:
|
||||
"""Append pub_hex to authorized_keys. Returns False if already present."""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
existing = {pubkey for pubkey, _name in load_authorized_keys_with_names(path)}
|
||||
if pub_hex in existing:
|
||||
return False
|
||||
line = (f"{pub_hex} {name}".rstrip()) + "\n"
|
||||
with open(path, "a", encoding="utf-8") as file:
|
||||
file.write(line)
|
||||
return True
|
||||
Reference in New Issue
Block a user