Files
2026-09-13 12:15:36 -07:00
..
2026-09-13 12:15:36 -07:00
2026-09-13 12:15:36 -07:00
2026-09-13 12:15:36 -07:00

PortalCam for macOS (mac2)

Native macOS companion app (PortalCam.app) and CoreMediaIO Camera Extension (CamExtension) for streaming high-definition video and audio from Portal TV.

Security Architecture

PortalCam uses a channel-bound, zero-knowledge authentication scheme to pair with Portal TV without sending secrets over the network or exposing connections to Man-in-the-Middle (MITM) proxies:

  1. Self-Signed ECDSA P-256 TLS:
    • Portal TV serves all endpoints over HTTPS via an on-device generated ECDSA NIST P-256 (secp256r1) certificate.
  2. Channel-Bound SRP-6a Handshake (RFC 5054):
    • Initiation: User clicks Pair in the app. The app calls POST https://<portal-ip>:5654/auth/srp/init over an ephemeral TLS session.
    • Channel Binding: The app extracts the presented leaf TLS certificate DER and computes: \mathbf{tls\_hash} = \text{SHA256}(\text{cert\_der})
    • Proof M_1 Generation: The user enters the 6-digit PIN displayed on the TV. The client computes: M_1 = \text{SHA256}(\text{pad256}(A) \parallel \text{pad256}(B) \parallel K \parallel s \parallel \mathbf{tls\_hash}) and submits it to POST https://<portal-ip>:5654/auth/srp/verify.
    • Mutual Proof M_2 Verification: The Portal TV verifies M_1 against its own certificate hash. If verified, it returns server proof M_2: M_2 = \text{SHA256}(\text{pad256}(A) \parallel M_1 \parallel K \parallel \mathbf{tls\_hash}) along with a random 256-bit bearer token.
    • Client Verification: The app verifies M_2 to confirm the Portal independently knows the shared secret before trusting the server.

Why Active MITM Attacks Cannot Succeed

If an attacker deploys a rogue proxy:

  1. The rogue proxy presents a substitute TLS certificate C_{\text{rogue}} to the Mac.
  2. The Mac computes M_1 using \text{SHA256}(C_{\text{rogue}}).
  3. The Portal verifies M_1 using \text{SHA256}(C_{\text{portal}}).
  4. Because the certificate fingerprints differ, M_1 verification fails on the Portal TV.
  5. The attacker cannot forge M_1 or M_2 without knowing the ephemeral PIN, which is displayed solely on the physical TV screen and never leaves the room.

Certificate Pinning & Keychain Storage

Once pairing succeeds:

  • The 256-bit bearer token and the certificate's SHA-256 fingerprint are saved in the macOS Data Protection Keychain under access group ENT9X9U544.com.kovtash.portalcam:
    • portalAuthToken — Bearer auth token
    • portalPinnedCertSha256 — Hex SHA-256 digest of the server's ECDSA certificate
  • A fallback copy is mirrored into the shared App Group UserDefaults (ENT9X9U544.com.kovtash.portalcam) for seamless access by the sandboxed camera extension.
  • PortalPinnedSessionDelegate evaluates all subsequent HTTPS requests (/video.h264, /audio.aac, /control/*). Any TLS certificate mismatch aborts the connection immediately.

Building and Installing

cd mac2/PortalCam
xcodebuild -scheme PortalCam -configuration Debug build -derivedDataPath ./build
killall PortalCam 2>/dev/null || true
cp -R ./build/Build/Products/Debug/PortalCam.app /Applications/
open /Applications/PortalCam.app