Skip to content

Harden gitconfig with portable SSH commit + tag signing#16

Open
akan72 wants to merge 2 commits into
mainfrom
akan72/gitconfig-hardening
Open

Harden gitconfig with portable SSH commit + tag signing#16
akan72 wants to merge 2 commits into
mainfrom
akan72/gitconfig-hardening

Conversation

@akan72
Copy link
Copy Markdown
Owner

@akan72 akan72 commented May 29, 2026

Summary

Harden gitconfig with SSH-based commit + tag signing, resolved at sign-time so the same config works across machines without per-host edits.

  • gpg.format = ssh — sign with SSH keys instead of GPG (no keyring to manage)
  • gpg.ssh.defaultKeyCommand — pulls the first key from whichever ssh-agent is exposed on the current machine, rather than hardcoding ~/.ssh/id_ed25519.pub
  • user.signingkey left unset (resolved by defaultKeyCommand)
  • commit.gpgsign = true and tag.gpgsign = true — signed by default; GitHub shows the Verified badge
[gpg]
    format = ssh

[gpg "ssh"]
    defaultKeyCommand = sh -c 'printf "key::%s\n" "$(ssh-add -L | head -n1)"'

[commit]
    gpgsign = true

[tag]
    gpgsign = true

Why dynamic resolution (vs hardcoded path)

A previous version of this PR set user.signingkey = ~/.ssh/id_ed25519.pub. That path doesn't exist on every machine (e.g. the current laptop only has ~/.ssh/id_rsa.pub), so signing would silently fail at commit time.

defaultKeyCommand resolves the key at sign-time by reading from ssh-agent, which means:

  • Portable across machines with different key paths (id_rsa, id_ed25519, id_ed25519_sk, …) — no per-host override file.
  • Works with hardware-resident keys (YubiKey ed25519-sk, 1Password's SSH agent) where there may be no .pub file on disk at all.
  • Survives switching agents (macOS system agent → 1Password agent) without any gitconfig change — just change SSH_AUTH_SOCK.

The key:: prefix is required: git's source (gpg-interface.c) explicitly searches the command output for that literal substring. Many tutorials show bare ssh-add -L | head -n1, which actually does not work in modern git. The printf wrapper adds the prefix.

Action required after merge + re-assimilate

  1. Confirm the key ssh-add -L | head -n1 returns is the one you want for signing.
  2. Upload that key to GitHub as a Signing key (Settings → SSH and GPG keys → New SSH key → type Signing). This is a separate registration from the existing Authentication key, even if it's the same key string.
  3. On any remote host (e.g. EC2), ensure the same key is present in the agent there (or use ForwardAgent).

Why & alternatives

Change Why Alternatives
commit.gpgsign = true Signed commits prove authenticity; GitHub shows "Verified". Skip if no signing key — would break commits.
tag.gpgsign = true Tags are part of the release trust chain. Lower priority — skip if tags don't matter.
gpg.format = ssh SSH keys reuse the auth key; no separate GPG keyring to manage. Stick with GPG if already working (wider tool support outside Git).
defaultKeyCommand = ssh-add -L | head -n1 Portable; works with hardware-resident keys. (a) Hardcode user.signingkey = ~/.ssh/<file>.pub — simpler but fragile across machines. (b) [includeIf] per-host override — more moving parts.

akan72 added 2 commits May 29, 2026 15:08
- Enable SSH-based signing (gpg.format = ssh) using the existing ~/.ssh/id_ed25519
  key — no GPG keyring needed, works identically on remote hosts (e.g. EC2)
- Pin user.signingkey to ~/.ssh/id_ed25519.pub so the key is explicit, not ambient
- Set commit.gpgsign = true and tag.gpgsign = true so commits and tags are signed
  by default and show GitHub's Verified badge

Note: upload ~/.ssh/id_ed25519.pub to GitHub as a *signing* key for verification.
Drop the hardcoded `signingkey = ~/.ssh/id_ed25519.pub` in favor of
`gpg.ssh.defaultKeyCommand = sh -c 'printf "key::%s\n" "$(ssh-add -L | head -n1)"'`
so the same gitconfig works on any machine without per-host edits.

Why:
- Hardcoded path breaks on machines without that exact file (e.g. the
  current laptop has only ~/.ssh/id_rsa.pub, so the previous form would
  silently fail at commit time).
- ssh-add -L returns whatever the active ssh-agent exposes — including
  hardware-resident keys (YubiKey ed25519-sk, 1Password's SSH agent)
  where no .pub file exists on disk.
- git's source (gpg-interface.c) explicitly searches defaultKeyCommand
  output for the literal "key::" prefix; the printf wrapper adds it
  (many tutorials show bare `ssh-add -L | head -n1`, which doesn't
  actually work in modern git).

Operational requirement: whichever key ssh-add -L returns on a given
machine must be uploaded to GitHub as a *Signing* key (separate from
the Authentication key registration). Confirm with:
  ssh-add -L | head -n1
@akan72 akan72 changed the title Harden gitconfig with SSH commit + tag signing Harden gitconfig with portable SSH commit + tag signing Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant