Subject: Re: [PATCH] Add commit & tag signing/verification via SSH keys using ssh-keygen

From: "brian m. carlson" <[email-masked]>
Date: Tue, 6 Jul 2021 14:44:36 +0000

On 2021-07-06 at 08:19:53, Fabian Stelzer via GitGitGadget wrote:
> From: Fabian Stelzer <[email-masked]>
> 
> set gpg.format = ssh and user.signingkey to a ssh public key string (like from an
> authorized_keys file) and commits/tags can be signed using the private
> key from your ssh-agent.
> 
> Verification uses a allowed_signers_file (see ssh-keygen(1)) which
> defaults to .gitsigners but can be set via gpg.ssh.allowedsigners
> A possible gpg.ssh.revocationfile is also passed to ssh-keygen on
> verification.
> 
> needs openssh>8.2p1

Usually we'll want to write the explanation here in full sentences with
typical capitalization.

> Signed-off-by: Fabian Stelzer <[email-masked]>
> ---
>     RFC: Add commit & tag signing/verification via SSH keys using ssh-keygen
>     
>     Support for using private keyfiles directly is still missing and i'm
>     unsure on how to configure it or if the pubkey in the signingkey field
>     is such a good idea. A SSH Fingerprint as signingkey would be nicer, but
>     key lookup would be quite cumbersome. Maybe storing the fingerprint in
>     signingkey and then have a gpg.ssh.$FINGERPRINT.publickey/privatekeyfile
>     setting? As a default we could get the first ssh key from ssh-add and
>     store it in the config to avoid unintentional changes of the used
>     signing key. I've started with some tests for SSH Signing but having
>     static private keyfiles would make this a lot easier. So still on my
>     TODO.

I think user.signingKey could be helpful for signing here.  That could
be a file name, not just a fingerprint, although we'd probably want to
have support for tilde expansion.  You could add an additional option,
gpg.ssh.keyring, that specifies the signatures to verify.  That would be
named the same thing as a potential option of gpg.openpgp.keyring,
which would be convenient.  Also, gpg.ssh.revokedKeyring could maybe be
the name for revoked keys?

>     This feature makes git signing much more accessible to the average user.
>     Usually they have a SSH Key for pushing code already. Using it for
>     signing commits allows us to verify not only the transport but the
>     pushed code as well. The allowed_signers file could be kept in the
>     repository if all receives are verified (allowing only useris with valid
>     signatures to add/change them) or outside if generated/managed
>     differently. Tools like gitolite could optionally generate and enforce
>     them from the already existing user ssh keys for example.
>     
>     In our corporate environemnt we use PIV x509 Certs on Yubikeys for email
>     signing/encryption and ssh keys which i think is quite common (at least
>     for the email part). This way we can establish the correct trust for the
>     SSH Keys without setting up a separate GPG Infrastructure (which is
>     still quite painful for users) or implementing x509 signing support for
>     git (which lacks good forwarding mechanisms). Using ssh agent forwarding
>     makes this feature easily usable in todays development environments
>     where code is often checked out in remote VMs / containers.

I think some of this rationale would work well in the commit message,
especially the part about the fact that using an SSH key may be easier
for users and the fact that it can be well supported by smart cards.
Those are compelling arguments about why this is a desirable change, and
should be in the commit message.

I haven't looked too deeply at the intricacies of the change, but I'm in
favor of it.  I would, however, like to see some tests here, including
for commits, tags, and push certificates.  Note that you'll probably
need to run the testsuite both with and without
GIT_TEST_DEFAULT_HASH=sha256 to verify everything works.

> diff --git a/Documentation/config/gpg.txt b/Documentation/config/gpg.txt
> index d94025cb368..fd71bd782ec 100644
> --- a/Documentation/config/gpg.txt
> +++ b/Documentation/config/gpg.txt
> @@ -11,13 +11,13 @@ gpg.program::
>  
>  gpg.format::
>  	Specifies which key format to use when signing with `--gpg-sign`.
> -	Default is "openpgp" and another possible value is "x509".
> +	Default is "openpgp". Other possible values are "x509", "ssh".
>  
>  gpg.<format>.program::
>  	Use this to customize the program used for the signing format you
>  	chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still
>  	be used as a legacy synonym for `gpg.openpgp.program`. The default
> -	value for `gpg.x509.program` is "gpgsm".
> +	value for `gpg.x509.program` is "gpgsm" and `gpg.ssh.program` is "ssh-keygen".
>  
>  gpg.minTrustLevel::
>  	Specifies a minimum trust level for signature verification.  If
> @@ -27,6 +27,15 @@ gpg.minTrustLevel::
>  	with at least `undefined` trust.  Setting this option overrides
>  	the required trust-level for all operations.  Supported values,
>  	in increasing order of significance:
> +
> +gpg.ssh.allowedSigners::
> +	A file containing all valid SSH signing principals. 
> +	Similar to an .ssh/authorized_keys file. See ssh-keygen(1) for details.
> +	Defaults to .gitsigners

We probably don't want to store this in the repository.  If OpenSSH has
a standard location for this, then we can default to that; otherwise, we
should pick something in .ssh or in $XDG_CONFIG_HOME/git.
-- 
brian m. carlson (he/him or they/them)
Toronto, Ontario, CA