CallMeTechie
DE Login
Home Products Blog About Contact

RDP Credentials in the Vault

Remote Desktop · Updated 1 month ago

Credential vault

Storage

With credential_mode='user_only', only username_encrypted is set (the user enters the password locally). With credential_mode='full', username and password are encrypted. Encryption runs via src/utils/crypto.js:encrypt (AES-256-GCM with the server master key).

E2EE retrieval by the desktop client

Credentials are NEVER delivered in plaintext over the API. The flow:

  1. Client generates an ephemeral ECDH keypair (P-256), sends the public key with the connection request (GET /api/v1/client/rdp/:id/connection-info?ecdhPublicKey=<base64>).
  2. Server decrypts the credentials from the DB (AES-GCM with master key, server-side).
  3. Server calls ecdhEncrypt(credentialsJson, ecdhPublicKey):
    • Generates an ephemeral server ECDH keypair.
    • Derives an AES-256 key via HKDF-SHA256 (salt = clientPub || serverPub, info = 'gatecontrol-rdp-e2ee-v1').
    • AES-256-GCM encryption of the credentials JSON.
  4. Response contains {data, iv, authTag, serverPublicKey}.
  5. Client derives the same AES key from its private key + the received server public and decrypts.

Nuance: Android/Java clients supply public keys in X.509/SPKI format (91 bytes), Node clients supply raw uncompressed (65 bytes). ecdhEncrypt detects this and uses the same encoding for the HKDF salt that the client uses — otherwise the derived key would not be symmetric.

The RSA pubkey endpoint GET /api/v1/rdp/pubkey is a separate legacy path (no ECDH, but RSA-OAEP). Used for older client flows where the client, instead of a credentials download, performs a server-side encrypted blob operation.

Credential rotation

If credential_rotation_enabled=1, the cycle credential_rotation_days applies. GET /api/v1/rdp/rotation/pending lists routes whose credential_rotation_last + credential_rotation_days has elapsed:

WHERE credential_rotation_enabled = 1 AND (
  credential_rotation_last IS NULL
  OR datetime(credential_rotation_last, '+' || credential_rotation_days || ' days') < datetime('now')
)

The admin then sets new values via PATCH /api/v1/rdp/:id/credentials and confirms via POST /api/v1/rdp/:id/rotation/ack — this only sets credential_rotation_last = datetime('now') and marks the rotation cycle as completed.

On rotation of the server master key (when the AES-GCM key changes), all encrypted credentials become invalid. The admin sees them as "rotation pending" and must re-enter them.

Cookie Settings

We use cookies to improve your experience. Essential cookies are always active.

Privacy Policy
ESC
↑↓ navigate open esc close