GPG Key with SSH Support

A single GPG primary key can certify three separate subkeys for signing, encryption, and authentication. Using an authentication subkey with SSH eliminates the need for a separate SSH keypair — the same OpenPGP key that signs Git commits and encrypts email also logs you into servers.

The workflow below creates a locked-down, single-purpose key hierarchy: an offline primary certification key and three rotated subkeys (sign, encrypt, authenticate). The 13-month expiration provides a one-month renewal window.

Create the primary key

gpg --expert --full-generate-key

Interactive choices:

  1. Key type: ECC (set your own capabilities)
  2. Capabilities: Toggle Sign off (S), then finish (Q)
    • The primary key should only certify; signing is delegated to a subkey.
  3. Curve: Curve 25519
  4. Expiration: 13m (13 months)
  5. Name: Your real name
  6. Email: Primary email address
  7. Comment: Leave empty — comments leak metadata and are unnecessary.

Edit the key and add subkeys

gpg --expert --edit-key $KEYID

Add UIDs

adduid

Enter name and email; leave comment empty. Repeat for each identity you want certified.

Add a signing subkey

addkey
  • Type: ECC (sign only)
  • Curve: Curve 25519
  • Expire: 13m

Add an authentication subkey

addkey
  • Type: ECC (set your own capabilities)
  • Toggle Sign off (S)
  • Toggle Authenticate on (A)
  • Finish (Q)
  • Curve: Curve 25519
  • Expire: 13m

Add an encryption subkey

addkey
  • Type: ECC (encrypt only)
  • Curve: Curve 25519
  • Expire: 13m

Save

save

Remove the primary key for offline storage

The primary key is only needed to certify new subkeys, add UIDs, or extend expirations. Keep it offline; the subkeys handle day-to-day operations.

# Export everything
gpg --armor --export-secret-key $KEYID > $KEYID.asc
gpg --export-secret-subkeys $KEYID > subkeys.gpg
 
# Delete all secret keys from the local keyring
gpg --delete-secret-keys $KEYID
 
# Re-import only the subkeys
gpg --import subkeys.gpg
 
# Verify
gpg --list-keys
gpg --list-secret-keys
 
# Cleanup
rm subkeys.gpg

Store $KEYID.asc on an encrypted, offline drive. You will need it to rotate subkeys next year.

Export the authentication subkey to SSH

  1. Find the authentication subkey’s keygrip:

    gpg --list-secret-keys --with-keygrip

    Look for the subkey marked [A].

  2. Add the keygrip to ~/.gnupg/sshcontrol (one per line):

    # ~/.gnupg/sshcontrol
    0123456789ABCDEF0123456789ABCDEF01234567
    
  3. Ensure gpg-agent is configured to emulate ssh-agent:

    # ~/.gnupg/gpg-agent.conf
    enable-ssh-support

    Then restart the agent: gpgconf --kill gpg-agent

  4. Export the SSH public key:

    gpg --export-ssh-key $KEYID > ~/.ssh/id_${KEYID}.pub
  5. Use it:

    • Reference with IdentityFile ~/.ssh/id_${KEYID}.pub in ~/.ssh/config
    • Or append the contents to a host’s ~/.ssh/authorized_keys

Note: The IdentityFile points to the public key file when using gpg-agent; the private key material stays in GPG’s keyring.

Operational notes

  • Rotation: Subkeys expire in 13 months. Before expiry, import the offline primary, extend subkey expirations (gpg --expert --edit-key $KEYID, then expire for each subkey), re-export subkeys, delete local secrets, and re-import.
  • Revocation: Generate a revocation certificate when the primary is created and store it offline with the primary key.
  • Backup: $KEYID.asc is a full backup of all secret keys. Guard it accordingly.
  • Git: Git can use the GPG authentication subkey for SSH transport and the signing subkey for commit signing — see git-on-windows-sshcommand for Windows-specific quoting issues.

See also

  • python — scripting language often used with GPG for automation
  • shell-stabilization — SSH connections often need stabilization too

Sources