Re: gpg.ssh.defaultKeyCommand docs bug?
- From
- matthew sporleder <msporleder@gmail.com>
- Date
- Oct 11, 2023, 18:16 UTC
- Message-ID
- <CAHKF-AsjY_P6mbAs7KWcgL39KbLbu9OE9XiLabghhTn-f0ybzQ@mail.gmail.com>
- In-Reply-To
- <20231009204341.GB3281325@coredump.intra.peff.net>
On Mon, Oct 9, 2023 at 4:43 PM Jeff King <peff@peff.net> wrote:
Show 66 quoted lines
>
> [+cc Fabian, who wrote this code]
>
> On Fri, Oct 06, 2023 at 01:14:49PM -0400, matthew sporleder wrote:
>
> > https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgsshdefaultKeyCommand
> >
> > 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
> > prefixed with key:: is expected in the first line of its output. This
> > allows for a script doing a dynamic lookup of the correct public key
> > when it is impractical to statically configure user.signingKey. For
> > example when keys or SSH Certificates are rotated frequently or
> > selection of the right key depends on external factors unknown to git.
> >
> > ---
> >
> > The command does not actually work (for me, git version 2.42.0) with
> > key:: prefixed.
> >
> > It only works if I cat the public key as-is.
> >
> > I only figured this out because the docs previously said it took the
> > format of ssh-add -L, which also doesn't not contain key::.
> >
> > I am using this script for my "dynamic" key discovery:
> > #!/bin/sh
> > f=$(ssh -G $(git remote get-url $(git remote|head -1)|awk -F':' '{
> > print $1 }') |grep -E '^identityfile'|sed 's#^identityfile ##g')
> > cat $(eval realpath ${f}.pub)
>
> I'm not very familiar with this part of Git, but looking at the code
> which parses the output of gpg.ssh.defaultKeyCommand, it splits it by
> line and then calls is_literal_ssh_key() on it, which is:
>
> static int is_literal_ssh_key(const char *string, const char **key)
> {
> if (skip_prefix(string, "key::", key))
> return 1;
> if (starts_with(string, "ssh-")) {
> *key = string;
> return 1;
> }
> return 0;
> }
>
> So your script works because the pub file starts with "ssh-rsa" or
> similar (and so would "ssh-add -L" output).
>
> The user.signingKey docs say:
>
> For backward compatibility, a raw key which begins with "ssh-", such
> as "ssh-rsa XXXXXX identifier", is treated as "key::ssh-rsa XXXXXX
> identifier", but this form is deprecated; use the key:: form instead.
>
> From reading the commit messages here, I guess this is about supporting
> non-ssh key types (e.g., my TPM-based key is ecdsa-sha2-nistp256 in the
> "ssh-add -L" output). But I'm not sure who is supposed to be put "key::"
> there.
>
> You said it "does not actually work" with "key::" prefixed. What
> happens? In the signing code we make a similar call to
> is_literal_ssh_key() that wills trip off the "key::" prefix, so I'd
> expect it work. But I could also believe there is a bug. :)
>
> -PeffIt gave very confusing errors!
key::ssh-rsa ABC123 me@localhost (no new line) error: Load key "....: invalid format?
key::ABC123 (yes new line) error: Couldn't load public key ...: No such file or directory?
key::ssh-rsa ABC123 me@localhost (yes new line) works, I think
ssh-rsa ABC123 me@localhost (yes new line) works (the script I provided)