You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ntfy的Vaultwarden远程解锁方案设计评审:防止受入侵主机暴露.env密码

Stack Overflow Style Answer

Great question—your home lab setup already has strong security guardrails, and fixing the key leakage gap just needs a targeted tweak to your secret handling workflow. Let’s walk through a practical, cryptographically sound solution that checks all your boxes:


Core Strategy: Shamir's Secret Sharing + Ephemeral Session Encryption

The main flaw in your current design is that P2 travels in a form an attacker can intercept and reuse. We’ll fix this by:

  1. Using Shamir's Secret Sharing (SSS) to split your GPG password into mathematically dependent shares (not just concatenated strings)
  2. Encrypting the mobile share with a one-time session key during transmission, so even intercepted data is useless to an attacker

Step 1: Reconfigure Secret Splitting

Ditch the simple P1 + P2 concatenation. Instead:

  • Generate your GPG password, then split it into a 2-of-2 Shamir secret share pair (S1 and S2)
    • S1: Store this locally on your host. For extra security, encrypt it with your host’s TPM (if available) or set file permissions to 600 (it’s completely useless on its own)
    • S2: Store this only in your phone’s secure storage (e.g., your device’s keychain or a trusted mobile password manager)

Unlike concatenated strings, SSS requires both shares to reconstruct the original secret—one share gives zero actionable information about the password.

Step 2: Host-Side Unlock Initiation

When your host boots up:

  1. Launch your Cloudflared-proxied Python HTTP server
  2. Generate a unique session ID and random challenge string (for Ed25519 authentication)
  3. Create a one-time AES-256 session key (never reuse this for future unlocks)
  4. Encrypt the AES session key with your phone’s ECC/RSA public key (stored on the host)
  5. Send all three items (encrypted AES key, session ID, challenge) to your private ntfy topic

Step 3: Phone-Side Authorization & Encrypted Response

When your phone gets the ntfy alert:

  1. Confirm the ntfy topic is valid (use ntfy’s built-in password protection for your private channel)
  2. Use your Ed25519 private key to sign the challenge + session ID (blocks replay attacks)
  3. Decrypt the AES session key with your phone’s private key
  4. Encrypt your S2 share with the AES session key
  5. Send back the signed challenge, encrypted S2, and matching session ID to your host’s HTTP endpoint

Step 4: Host-Side Verification & Secret Reconstruction

On the host:

  1. Validate the incoming session ID matches the one you sent (blocks stale/replayed requests)
  2. Verify the Ed25519 signature using your stored public key (ensures only your phone can authorize)
  3. Decrypt S2 with the one-time AES session key
  4. Combine S1 (local) and S2 (decrypted) via Shamir’s algorithm to reconstruct the GPG password only in memory
  5. Decrypt your .env file in memory (never write decrypted content to disk) using the GPG password
  6. Launch Vaultwarden by passing the decrypted environment variables directly via the process’s environment (avoid command-line args—use Python’s subprocess.run() with the env parameter to keep secrets out of ps output)
  7. Immediately wipe all sensitive data from memory: overwrite variables holding the GPG password, AES key, S2, and decrypted .env values (in Python, use ctypes to zero out memory or explicitly overwrite strings)

Extra Hardening Tips

  • TPM Protection for S1: If your Linux host has a TPM 2.0 module, encrypt S1 with it—this ensures S1 can only be decrypted on the physical host, adding a layer if an attacker exfiltrates your disk.
  • Session Timeouts: Set a 5-minute timeout on your unlock script. If no valid response comes in, wipe all temporary data and shut down the HTTP server.
  • Script Permissions: Make your unlock script owned by root with permissions 700—no other user should read or execute it.
  • Process Isolation: Run Vaultwarden as a dedicated non-root user, and keep the unlock script running with minimal privileges only long enough to launch the service.

Why This Meets Your Requirements

  1. Remote Approval via ntfy: The flow uses ntfy to trigger and coordinate the unlock request, requiring your explicit phone action.
  2. Strong Device Authentication: The Ed25519 challenge-response ensures only your phone (holding the private key) can authorize an unlock.
  3. No Persistent Full Secret: The host never stores or retains the full GPG password—S2 is only decrypted in memory temporarily, and the AES session key is discarded immediately.
  4. Resilient to Host Compromise: Even if an attacker gains root access and monitors traffic/memory:
    • They can steal S1, but it’s useless without S2
    • They can intercept encrypted S2 and the encrypted session key, but can’t decrypt either without your phone’s private keys
    • Each unlock uses a new session key, so captured data from one session can’t be reused for future unlocks

内容的提问来源于stack exchange,提问作者Pandofla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 12:38:12