Skip to content

Share a Secret

Share an encrypted secret with a teammate so they can decrypt it with their own GPG key.

Sharing moves a public key between keyrings, then adds that key’s fingerprint to the secret’s recipient set. Your teammate exports their public key; you import it; you share the secret to their fingerprint. dotsecenv re-encrypts the secret to both keys and appends the new entry to the vault.

  • dotsecenv configured with at least one secret (Your First Secret)
  • Your teammate’s GPG public key
  1. Get your teammate’s public key

    Your teammate exports their public key and sends you the file (chat, email, key server). Public keys are safe to share.

    Terminal window
    # Teammate runs this
    gpg --armor --export teammate@example.com > teammate-public.asc
  2. Import their public key into your keyring

    Terminal window
    gpg --import teammate-public.asc

    Read off their fingerprint (the 40-character hex string):

    Terminal window
    gpg --list-keys teammate@example.com
  3. Share the secret to their fingerprint

    secret share re-encrypts the secret to the new recipient and adds their identity to the vault automatically:

    Terminal window
    dotsecenv secret share API_KEY TEAMMATE_FINGERPRINT

    Share into every vault that already holds the secret with --all:

    Terminal window
    dotsecenv secret share API_KEY TEAMMATE_FINGERPRINT --all
  4. Verify the recipient set

    The teammate’s identity now appears in the vault, and their fingerprint is on the secret’s recipient list. Plain vault describe lists identities and secret keys:

    Terminal window
    dotsecenv vault describe
    Vault 1 (~/.config/dotsecenv/vault):
    Identities:
    - Alice <alice@example.com> (YOUR_FINGERPRINT)
    - Bob <bob@example.com> (TEAMMATE_FINGERPRINT)
    Secrets:
    - API_KEY

    The per-entry recipient set lives in the available_to field, which --all --json exposes (newest entry first):

    Terminal window
    dotsecenv secret get API_KEY --all --json | jq '.[0].available_to'
    # ["YOUR_FINGERPRINT", "TEAMMATE_FINGERPRINT"]
  5. Send the vault

    The latest entry is encrypted for both of you. Commit and push the vault, or hand the file over directly:

    Terminal window
    git add vault
    git commit -m "Share API_KEY with teammate"
    git push
  6. Teammate decrypts with their own key

    On their machine, your teammate pulls the vault, logs in by fingerprint, and reads the secret:

    Terminal window
    git pull
    dotsecenv init config
    dotsecenv login THEIR_FINGERPRINT
    dotsecenv secret get API_KEY
  • The latest entry is encrypted to both your key and your teammate’s key.
  • Either of you decrypts it independently with your own private key.
  • The teammate’s fingerprint appears in the secret’s available_to set.
Terminal window
dotsecenv secret share prod::DATABASE_PASSWORD TEAMMATE_FINGERPRINT

Run secret share once per recipient. Each call adds that identity automatically:

Terminal window
dotsecenv secret share API_KEY ALICE_FINGERPRINT
dotsecenv secret share API_KEY BOB_FINGERPRINT

In production every identity holds only its own private key. Bob exports his public key, Alice imports it and shares to his fingerprint, and neither laptop ever sees the other’s secret key. Example 02 reproduces this with two isolated GNUPGHOME directories so the access-control boundary stays honest.


When you share a secret, dotsecenv:

  1. Decrypts the current value with your GPG key.
  2. Generates a fresh random session key (AES-256-GCM).
  3. Encrypts the value with the session key.
  4. Encrypts the session key once per authorized identity.
  5. Appends the new entry to the vault.

The previous entry is untouched. A new one is appended. That is the append-only design, and it is why revocation cannot reach back into history.


“Key not found”

The public key is not in your keyring. Import it and confirm:

Terminal window
gpg --list-keys FINGERPRINT

If it is missing, ask your teammate to send their public key again.

Teammate can’t decrypt

Confirm they are logging in with the fingerprint that is on the recipient set:

Terminal window
# Teammate runs:
gpg --list-secret-keys --keyid-format long

The fingerprint must match the one in the secret’s available_to set exactly.