Skip to content

Commit

Permalink
Merge branch 'fs/ssh-signing' into seen
Browse files Browse the repository at this point in the history
Use ssh public crypto for object and push-cert signing.

* fs/ssh-signing:
  ssh signing: test that gpg fails for unknown keys
  ssh signing: tests for logs, tags & push certs
  ssh signing: duplicate t7510 tests for commits
  ssh signing: verify signatures using ssh-keygen
  ssh signing: provide a textual signing_key_id
  ssh signing: retrieve a default key from ssh-agent
  ssh signing: add ssh key format and signing code
  ssh signing: add test prereqs
  ssh signing: preliminary refactoring and clean-up
  • Loading branch information
gitster committed Oct 4, 2021
2 parents e78453e + 1bfb57f commit eea5288
Show file tree
Hide file tree
Showing 15 changed files with 1,341 additions and 66 deletions.
45 changes: 43 additions & 2 deletions Documentation/config/gpg.txt
Expand Up @@ -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
Expand All @@ -33,3 +33,44 @@ gpg.minTrustLevel::
* `marginal`
* `fully`
* `ultimate`

gpg.ssh.defaultKeyCommand:
This command that will be run when user.signingkey is not set and a ssh
signature is requested. On successful exit a valid ssh public key is
expected in the first line of its output. To automatically use the first
available key from your ssh-agent set this to "ssh-add -L".

gpg.ssh.allowedSignersFile::
A file containing ssh public keys which you are willing to trust.
The file consists of one or more lines of principals followed by an ssh
public key.
e.g.: user1@example.com,user2@example.com ssh-rsa AAAAX1...
See ssh-keygen(1) "ALLOWED SIGNERS" for details.
The principal is only used to identify the key and is available when
verifying a signature.
+
SSH has no concept of trust levels like gpg does. To be able to differentiate
between valid signatures and trusted signatures the trust level of a signature
verification is set to `fully` when the public key is present in the allowedSignersFile.
Therefore to only mark fully trusted keys as verified set gpg.minTrustLevel to `fully`.
Otherwise valid but untrusted signatures will still verify but show no principal
name of the signer.
+
This file can be set to a location outside of the repository and every developer
maintains their own trust store. A central repository server could generate this
file automatically from ssh keys with push access to verify the code against.
In a corporate setting this file is probably generated at a global location
from automation that already handles developer ssh keys.
+
A repository that only allows signed commits can store the file
in the repository itself using a path relative to the top-level of the working tree.
This way only committers with an already valid key can add or change keys in the keyring.
+
Using a SSH CA key with the cert-authority option
(see ssh-keygen(1) "CERTIFICATES") is also valid.

gpg.ssh.revocationFile::
Either a SSH KRL or a list of revoked public keys (without the principal prefix).
See ssh-keygen(1) for details.
If a public key is found in this file then it will always be treated
as having trust level "never" and signatures will show as invalid.
7 changes: 7 additions & 0 deletions Documentation/config/user.txt
Expand Up @@ -36,3 +36,10 @@ user.signingKey::
commit, you can override the default selection with this variable.
This option is passed unchanged to gpg's --local-user parameter,
so you may specify a key using any method that gpg supports.
If gpg.format is set to "ssh" this can contain the literal ssh public
key (e.g.: "ssh-rsa XXXXXX identifier") or a file which contains it and
corresponds to the private key used for signing. The private key
needs to be available via ssh-agent. Alternatively it can be set to
a file containing a private key directly. If not set git will call
gpg.ssh.defaultKeyCommand (e.g.: "ssh-add -L") and try to use the first
key available.
4 changes: 4 additions & 0 deletions builtin/receive-pack.c
Expand Up @@ -132,6 +132,10 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
{
int status = parse_hide_refs_config(var, value, "receive");

if (status)
return status;

status = git_gpg_config(var, value, NULL);
if (status)
return status;

Expand Down
6 changes: 3 additions & 3 deletions fmt-merge-msg.c
Expand Up @@ -528,11 +528,11 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
buf = payload.buf;
len = payload.len;
if (check_signature(payload.buf, payload.len, sig.buf,
sig.len, &sigc) &&
!sigc.gpg_output)
sig.len, &sigc) &&
!sigc.output)
strbuf_addstr(&sig, "gpg verification failed.\n");
else
strbuf_addstr(&sig, sigc.gpg_output);
strbuf_addstr(&sig, sigc.output);
}
signature_check_clear(&sigc);

Expand Down

0 comments on commit eea5288

Please sign in to comment.