Skip to main content
Version: 1.0

Sharing Cryptographic Model

SyVault supports sharing credentials between users without ever exposing plaintext data to the server. All sharing operations are built on ECDH P-256 ephemeral key exchange with ECDSA-authenticated envelopes, ensuring forward secrecy and sender verification.

Key Infrastructure

Every SyVault user has a long-term ECDH P-256 keypair:

  • Public key: stored on the server (65 bytes, SEC1 uncompressed format). Available to any member of the same organization.
  • Private key: encrypted with the user's Encryption Key using AES-256-GCM with AAD syvault.ecdh-private-key.v1 and stored on the server. Decrypted client-side only.

One-Time Share: Cryptographic Flow

When Alice shares a single record with Bob:

  1. Alice generates an ephemeral ECDH P-256 keypair (ephemeral_pk, ephemeral_sk). This keypair is used exactly once for forward secrecy.

  2. Alice performs ECDH key agreement: raw_shared_secret = ECDH(ephemeral_sk, bob_pk).

  3. Alice derives a wrapping key using HKDF-SHA256:

    wrapping_key = HKDF-SHA256(
    ikm = raw_shared_secret,
    info = "syvault.share.v1.wrap:<alice_pk>:<bob_pk>",
    L = 32
    )
  4. Alice signs the exchange to authenticate herself:

    signature = ECDSA-P256(alice_sk, ephemeral_pk || bob_pk)
  5. Alice encrypts the record DEK with the wrapping key:

    encrypted_dek = AES-256-GCM(
    key = wrapping_key,
    aad = ephemeral_pk || alice_pk,
    plaintext = record_dek
    )
  6. Alice sends a ShareEnvelope to the server:

    {
    "ephemeral_public_key": "<65 bytes>",
    "sender_public_key": "<alice's 65-byte public key>",
    "sender_signature": "<ECDSA signature>",
    "encrypted_key": "<wrapped DEK>",
    "kem_algorithm": 1
    }
  7. Alice's ephemeral private key is immediately zeroized. It never leaves memory and is never stored.

When Bob retrieves the share:

  1. Bob verifies Alice's signature: ECDSA-Verify(alice_pk, ephemeral_pk || bob_pk, signature). If verification fails, the share is rejected (MITM detection).

  2. Bob performs ECDH: raw_shared_secret = ECDH(bob_sk, ephemeral_pk).

  3. Bob derives the same wrapping key using identical HKDF parameters.

  4. Bob decrypts the record DEK using AES-256-GCM with the same AAD.

  5. Bob decrypts the record payload using the DEK with AAD syvault.record.{id}.payload.v1.

info

The server never sees the plaintext DEK or the record contents. It stores only the ShareEnvelope, which contains an ephemeral public key, a signature, and an encrypted blob.

Why Ephemeral Keys?

Each share uses a fresh ephemeral keypair, providing forward secrecy: even if Bob's long-term private key is later compromised, past shares cannot be decrypted because the ephemeral private key no longer exists. The ephemeral key is generated, used once for ECDH, and zeroized within the same function scope.

Why ECDSA Authentication?

Without sender authentication, a malicious server could mount a MITM attack: replace Alice's ephemeral public key with the server's own, intercept the DEK, and re-encrypt it for Bob. Alice's ECDSA signature over ephemeral_pk || bob_pk binds the ephemeral key to the exchange, making MITM detectable.

warning

The ECDSA verification step is critical. Skipping it would allow a compromised server to intercept shared secrets. SyVault clients reject any share envelope with an invalid or missing signature.

Team Folder Sharing

Team shared folders work through a similar mechanism but at the folder level:

  1. When a shared folder is created, a random Folder Key is generated.
  2. The Folder Key is wrapped for each team member individually using the ECDH-based wrap_key_for_sharing mechanism described above.
  3. Records within the shared folder have their DEKs wrapped by the Folder Key instead of a personal Vault Key.
  4. When a member is added to the team, the Folder Key is re-wrapped for the new member.
  5. When a member is removed, the Folder Key is rotated (new random key generated), all record DEKs are re-wrapped under the new Folder Key, and the new Folder Key is wrapped for each remaining member.

This ensures that former team members cannot decrypt any data added after their removal, even if they retained a copy of the old Folder Key.

One-time share links (for sharing with users outside the organization or without a SyVault account) use a variant of the sharing model:

  1. The record DEK is encrypted with a random share key.
  2. The share key is encoded in the URL fragment (#key=...), which is never sent to the server.
  3. The encrypted DEK and encrypted payload are stored on the server with a unique share ID.
  4. The recipient opens the link, the client extracts the key from the fragment, and decrypts locally.
  5. After first access (or expiry), the server deletes the encrypted data.

The AAD string syvault.share.one-time.v1 is used for one-time share encryption.