{"thread":{"id":"60316","subject":"gpg.ssh.defaultKeyCommand docs bug?","startedAt":"2023-10-06T17:15:06Z","lastAt":"2023-10-11T23:41:35Z","messageCount":4,"participants":["matthew sporleder","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"482746","messageId":"CAHKF-AvUxH1Ar3Xijjb4_8N+_kssPHZVHqQSAE9kDGRfTYHyxw@mail.gmail.com","threadId":"60316","inReplyTo":null,"subject":"gpg.ssh.defaultKeyCommand docs bug?","fromName":"matthew sporleder","fromEmail":"msporleder@gmail.com","sentAt":"2023-10-06T17:14:49Z","receivedAt":"2023-10-06T17:15:06Z","isPatch":false,"sender":{"key":"msporleder@gmail.com","avatar":null},"body":"https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgsshdefaultKeyCommand\n\nThis command that will be run when user.signingkey is not set and a\nssh signature is requested. On successful exit a valid ssh public key\nprefixed with key:: is expected in the first line of its output. This\nallows for a script doing a dynamic lookup of the correct public key\nwhen it is impractical to statically configure user.signingKey. For\nexample when keys or SSH Certificates are rotated frequently or\nselection of the right key depends on external factors unknown to git.\n\n---\n\nThe command does not actually work (for me, git version 2.42.0) with\nkey:: prefixed.\n\nIt only works if I cat the public key as-is.\n\nI only figured this out because the docs previously said it took the\nformat of ssh-add -L, which also doesn't not contain key::.\n\nI am using this script for my \"dynamic\" key discovery:\n#!/bin/sh\nf=$(ssh -G $(git remote get-url $(git remote|head -1)|awk -F':' '{\nprint $1 }') |grep -E '^identityfile'|sed 's#^identityfile ##g')\ncat $(eval realpath ${f}.pub)\n\nThanks,\nMatt\n"},{"id":"482902","messageId":"20231009204341.GB3281325@coredump.intra.peff.net","threadId":"60316","inReplyTo":"CAHKF-AvUxH1Ar3Xijjb4_8N+_kssPHZVHqQSAE9kDGRfTYHyxw@mail.gmail.com","subject":"Re: gpg.ssh.defaultKeyCommand docs bug?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-10-09T20:43:41Z","receivedAt":"2023-10-09T20:43:51Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"[+cc Fabian, who wrote this code]\n\nOn Fri, Oct 06, 2023 at 01:14:49PM -0400, matthew sporleder wrote:\n\n> https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgsshdefaultKeyCommand\n> \n> This command that will be run when user.signingkey is not set and a\n> ssh signature is requested. On successful exit a valid ssh public key\n> prefixed with key:: is expected in the first line of its output. This\n> allows for a script doing a dynamic lookup of the correct public key\n> when it is impractical to statically configure user.signingKey. For\n> example when keys or SSH Certificates are rotated frequently or\n> selection of the right key depends on external factors unknown to git.\n> \n> ---\n> \n> The command does not actually work (for me, git version 2.42.0) with\n> key:: prefixed.\n> \n> It only works if I cat the public key as-is.\n> \n> I only figured this out because the docs previously said it took the\n> format of ssh-add -L, which also doesn't not contain key::.\n> \n> I am using this script for my \"dynamic\" key discovery:\n> #!/bin/sh\n> f=$(ssh -G $(git remote get-url $(git remote|head -1)|awk -F':' '{\n> print $1 }') |grep -E '^identityfile'|sed 's#^identityfile ##g')\n> cat $(eval realpath ${f}.pub)\n\nI'm not very familiar with this part of Git, but looking at the code\nwhich parses the output of gpg.ssh.defaultKeyCommand, it splits it by\nline and then calls is_literal_ssh_key() on it, which is:\n\n  static int is_literal_ssh_key(const char *string, const char **key)\n  {\n          if (skip_prefix(string, \"key::\", key))\n                  return 1;\n          if (starts_with(string, \"ssh-\")) {\n                  *key = string;\n                  return 1;\n          }\n          return 0;\n  }\n\nSo your script works because the pub file starts with \"ssh-rsa\" or\nsimilar (and so would \"ssh-add -L\" output).\n\nThe user.signingKey docs say:\n\n  For backward compatibility, a raw key which begins with \"ssh-\", such\n  as \"ssh-rsa XXXXXX identifier\", is treated as \"key::ssh-rsa XXXXXX\n  identifier\", but this form is deprecated; use the key:: form instead.\n\nFrom reading the commit messages here, I guess this is about supporting\nnon-ssh key types (e.g., my TPM-based key is ecdsa-sha2-nistp256 in the\n\"ssh-add -L\" output). But I'm not sure who is supposed to be put \"key::\"\nthere.\n\nYou said it \"does not actually work\" with \"key::\" prefixed. What\nhappens? In the signing code we make a similar call to\nis_literal_ssh_key() that wills trip off the \"key::\" prefix, so I'd\nexpect it work. But I could also believe there is a bug. :)\n\n-Peff\n"},{"id":"483065","messageId":"CAHKF-AsjY_P6mbAs7KWcgL39KbLbu9OE9XiLabghhTn-f0ybzQ@mail.gmail.com","threadId":"60316","inReplyTo":"20231009204341.GB3281325@coredump.intra.peff.net","subject":"Re: gpg.ssh.defaultKeyCommand docs bug?","fromName":"matthew sporleder","fromEmail":"msporleder@gmail.com","sentAt":"2023-10-11T18:16:27Z","receivedAt":"2023-10-11T18:17:41Z","isPatch":false,"sender":{"key":"msporleder@gmail.com","avatar":null},"body":"On Mon, Oct 9, 2023 at 4:43 PM Jeff King <peff@peff.net> wrote:\n>\n> [+cc Fabian, who wrote this code]\n>\n> On Fri, Oct 06, 2023 at 01:14:49PM -0400, matthew sporleder wrote:\n>\n> > https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgsshdefaultKeyCommand\n> >\n> > This command that will be run when user.signingkey is not set and a\n> > ssh signature is requested. On successful exit a valid ssh public key\n> > prefixed with key:: is expected in the first line of its output. This\n> > allows for a script doing a dynamic lookup of the correct public key\n> > when it is impractical to statically configure user.signingKey. For\n> > example when keys or SSH Certificates are rotated frequently or\n> > selection of the right key depends on external factors unknown to git.\n> >\n> > ---\n> >\n> > The command does not actually work (for me, git version 2.42.0) with\n> > key:: prefixed.\n> >\n> > It only works if I cat the public key as-is.\n> >\n> > I only figured this out because the docs previously said it took the\n> > format of ssh-add -L, which also doesn't not contain key::.\n> >\n> > I am using this script for my \"dynamic\" key discovery:\n> > #!/bin/sh\n> > f=$(ssh -G $(git remote get-url $(git remote|head -1)|awk -F':' '{\n> > print $1 }') |grep -E '^identityfile'|sed 's#^identityfile ##g')\n> > cat $(eval realpath ${f}.pub)\n>\n> I'm not very familiar with this part of Git, but looking at the code\n> which parses the output of gpg.ssh.defaultKeyCommand, it splits it by\n> line and then calls is_literal_ssh_key() on it, which is:\n>\n>   static int is_literal_ssh_key(const char *string, const char **key)\n>   {\n>           if (skip_prefix(string, \"key::\", key))\n>                   return 1;\n>           if (starts_with(string, \"ssh-\")) {\n>                   *key = string;\n>                   return 1;\n>           }\n>           return 0;\n>   }\n>\n> So your script works because the pub file starts with \"ssh-rsa\" or\n> similar (and so would \"ssh-add -L\" output).\n>\n> The user.signingKey docs say:\n>\n>   For backward compatibility, a raw key which begins with \"ssh-\", such\n>   as \"ssh-rsa XXXXXX identifier\", is treated as \"key::ssh-rsa XXXXXX\n>   identifier\", but this form is deprecated; use the key:: form instead.\n>\n> From reading the commit messages here, I guess this is about supporting\n> non-ssh key types (e.g., my TPM-based key is ecdsa-sha2-nistp256 in the\n> \"ssh-add -L\" output). But I'm not sure who is supposed to be put \"key::\"\n> there.\n>\n> You said it \"does not actually work\" with \"key::\" prefixed. What\n> happens? In the signing code we make a similar call to\n> is_literal_ssh_key() that wills trip off the \"key::\" prefix, so I'd\n> expect it work. But I could also believe there is a bug. :)\n>\n> -Peff\n\nIt gave very confusing errors!\n\nkey::ssh-rsa ABC123 me@localhost (no new line)\nerror: Load key \"....: invalid format?\n\nkey::ABC123 (yes new line)\nerror: Couldn't load public key ...: No such file or directory?\n\nkey::ssh-rsa ABC123 me@localhost (yes new line)\nworks, I think\n\nssh-rsa ABC123 me@localhost (yes new line)\nworks (the script I provided)\n"},{"id":"483121","messageId":"20231011234131.GO518221@coredump.intra.peff.net","threadId":"60316","inReplyTo":"CAHKF-AsjY_P6mbAs7KWcgL39KbLbu9OE9XiLabghhTn-f0ybzQ@mail.gmail.com","subject":"Re: gpg.ssh.defaultKeyCommand docs bug?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-10-11T23:41:31Z","receivedAt":"2023-10-11T23:41:35Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Oct 11, 2023 at 02:16:27PM -0400, matthew sporleder wrote:\n\n> It gave very confusing errors!\n> \n> key::ssh-rsa ABC123 me@localhost (no new line)\n> error: Load key \"....: invalid format?\n\nIt's hard to say without seeing the whole output, but I suspect this is\nactually coming from ssh, not Git. We just dump the output into a\ntempfile and feed it to \"ssh-keygen -f\".\n\nThough I'd think we would see the same issue with user.signingKey in\nthat case.\n\nSo I'm not sure what's going on here (I haven't set up ssh signing to\nplay with yet).\n\n> key::ABC123 (yes new line)\n> error: Couldn't load public key ...: No such file or directory?\n\nThat one makes sense to me. The \"ssh-rsa\" part is important, because\nwithout it, ssh-keygen has no idea what format it is in.\n\n> key::ssh-rsa ABC123 me@localhost (yes new line)\n> works, I think\n\nThis is the recommended format.\n\n> ssh-rsa ABC123 me@localhost (yes new line)\n> works (the script I provided)\n\nAnd this is the historical one.\n\nSo I don't think the documentation is _wrong_ here, but I agree that it\nis a bit on the confusing side (especially understanding that \"key::\"\ncame later, and that raw \"ssh-rsa\" is deprecated, which is only\nmentioned in user.signingKey, not gpg.ssh.defaultKeyCommand.\n\nAnd I'm still not sure what's going on with your no-new-line example,\nwhich I'd have expected to work.\n\n-Peff\n"}]}