← Writing

May 22, 2026

Your Gong Key Is Also Your SSH Key

The same P-256 key that signs your Gong identity works as a standard SSH key. Here is how to replace your ~/.ssh/id_rsa with a key that requires two physical devices to use.

Your SSH key is a file. ~/.ssh/id_ed25519 — 119 bytes of plaintext sitting on disk. Back up your home directory, or get code execution on your machine, and someone has it. Every server you have access to is now available to them.

Hardware tokens solve this. YubiKey, for example, stores the key in a chip and requires physical presence for every signature. But YubiKey requires USB, or a specific driver, or a PIN you have to remember. It doesn't work across machines without carrying the dongle.

Gong's approach is different. The key is never stored anywhere complete. It's split across two physical devices — your phone and your Gong key carrier. Any signature requires both to cooperate. Copying your disk gets you nothing. Stealing your carrier gets you nothing. Both must be physically present.


How It Works

When you enrolled on Gong, a P-256 keypair was generated. The private key was immediately split using Shamir's Secret Sharing into three shares: one in your iPhone's Secure Enclave, one in your Gong key carrier, one held locally. Any two of three reconstruct the key. One alone is useless.

The enrolled P-256 public key is also a valid SSH key. OpenSSH calls the format ecdsa-sha2-nistp256 — same key, same curve, same signature algorithm. The Gong SSH agent serves it over a Unix socket (SSH_AUTH_SOCK), exactly the interface every SSH client expects. No special client software required.

When you SSH to a server, the agent receives the sign request. Your carrier's LED flashes. Press the button. The BLE ceremony completes in about two seconds. SSH auth succeeds.


Prerequisites


Step 1 — Install the Agent

curl -fsSL https://gong.com/install/gong-ssh-agent -o ~/.local/bin/gong-ssh-agent
chmod +x ~/.local/bin/gong-ssh-agent

Or from source:

# The agent is in the gong-auth repo
cp gong-auth/scripts/gong-ssh-agent ~/.local/bin/
chmod +x ~/.local/bin/gong-ssh-agent

Install the Python dependency if not already present:

pip install cryptography

Step 2 — Start the Agent

gong-ssh-agent &

The agent reads your local share files, reconstructs the signing key in memory, opens a socket at ~/.gong/agent.sock, and starts listening. The master key bytes are wiped immediately after the P-256 signing key is derived. Only the derived key lives in memory.

Tell your shell to use it:

eval $(gong-ssh-agent --print-env)

To make this permanent, add to ~/.bashrc or ~/.zshrc:

export SSH_AUTH_SOCK="$HOME/.gong/agent.sock"

Verify it is running:

ssh-add -l
# 256 SHA256:gJQ0SqNxXM4llCMQ3DOBzg82uLBaFbzedKJ6jMuFtbs gong-ssh-agent (ECDSA)

Step 3 — Get Your Public Key

gong-ssh-agent --print-pubkey

Output:

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN... gong-key

This is a standard OpenSSH public key in authorized_keys format. The fingerprint matches what ssh-add -l shows. You can verify they correspond before deploying.


Step 4 — Deploy to Servers

Any Linux server:

gong-ssh-agent --print-pubkey | ssh user@server "cat >> ~/.ssh/authorized_keys"

GitHub — Settings → SSH and GPG keys → New SSH key. Paste the --print-pubkey output. Label it "Gong key".

GitLab, Bitbucket, SourceHut — same: account SSH settings, paste the key.

Multiple servers at once:

PUBKEY=$(gong-ssh-agent --print-pubkey)
for host in server1 server2 server3; do
  ssh user@$host "echo '$PUBKEY' >> ~/.ssh/authorized_keys"
done

The public key never changes unless you re-enroll. Add it once and it works for the lifetime of your identity.


Step 5 — Test Auth

ssh user@your-server

Watch your carrier. The LED flashes when a sign request arrives. Press the button. The connection establishes.

If the carrier is not nearby or the button is not pressed within ten seconds, the agent returns failure and SSH reports permission denied. This is by design.

For git:

git clone git@github.com:your-org/your-repo
# carrier LED flashes → press button → clone proceeds

Step 6 — Auto-Start

To start the agent automatically at login:

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/gong-ssh-agent.service << 'EOF'
[Unit]
Description=Gong SSH Agent

[Service]
Type=simple
ExecStart=%h/.local/bin/gong-ssh-agent
Restart=on-failure

[Install]
WantedBy=default.target
EOF

systemctl --user enable --now gong-ssh-agent

Check status:

systemctl --user status gong-ssh-agent

Audit Log

Every sign request is logged to ~/.gong/agent.log in append-only format:

2026-05-22T14:32:01  STARTED  key=ecdsa-sha2-nistp256  fingerprint=SHA256:gJQ0...
2026-05-22T14:32:15  SIGN_REQUEST  preview=4a3f1c...  APPROVED
2026-05-22T14:32:15  SIGN_OK  count=1  fingerprint=SHA256:gJQ0...

You have a complete record of every machine that used your key and when. The log does not contain the signed data — only a short preview for identification.


The Key Carrier

The carrier is a small device on your keychain. It holds one Shamir share of your master key, protected inside the nRF54L15 hardware crypto accelerator. The share never leaves the chip in plaintext.

The authentication flow takes about two seconds end to end:

1. SSH sends the sign request to the agent

2. Agent triggers the ceremony — your phone shows "SSH login — approve?"

3. Carrier LED flashes

4. You press the button

5. BLE exchange completes, signature returned

6. SSH reports authenticated

No carrier within BLE range, no auth. Carrier present but button not pressed within the timeout, no auth. Both conditions must be satisfied.

This is what hardware auth should feel like: invisible until you need it, unambiguous when you do.


Key Lifecycle

Your public key is stable. Adding it to a server once means it works for the lifetime of your identity. If you replace your phone, your carrier, or your laptop, the reconstruction ceremony produces the same key from any two surviving shares.

Remove a lost device from the enrollment set — the public key stays the same, every server you've added it to continues to work, and the lost device's share is no longer sufficient to reconstruct anything.

Same key for SSH. Same key for git commit signing. Same key for gong.com login. One enrollment covers all of it.