{"thread":{"id":"63289","subject":"How to gpg signed email patches?","startedAt":"2025-04-13T19:17:27Z","lastAt":"2025-04-14T19:12:20Z","messageCount":10,"participants":["Klaus Frank","Matt Hunter","brian m. carlson","Konstantin Ryabitsev","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"516060","messageId":"fx2ofmmhkjmjqfqya5e3qvmovvmpnjepteqobcz4eia5sw64bg@yquuljpwok3f","threadId":"63289","inReplyTo":null,"subject":"How to gpg signed email patches?","fromName":"Klaus Frank","fromEmail":"vger.kernel.org@frank.fyi","sentAt":"2025-04-13T19:17:26Z","receivedAt":"2025-04-13T19:17:27Z","isPatch":false,"sender":{"key":"vger.kernel.org@frank.fyi","avatar":null},"body":"Hi,\n\nhow do I get \"git send-email\" to send the patches gpg signed? I tried\nfirst signing the commit but after spending time looking into the\ndocumentation I couldn't work out how to do it. All I discovered so far\nis that the \"git send-email\" appears to be using \"git format-patch\"\ninternally and that's where it currently gets lost.\n\nSadly none of the man pages I looked at so far mentions anything about\ngpg signing in this regards. Not even \"git am\" does.\n\nIdeally I'd like to have \"git send-email\" send my patches gpg-signed to\nensure authenticity and integrity.\n\nI also considered alternatives like using my MTA to GPG-Sign these mails\nhowever as the \"git am\" documentation also didn't mention gpg signing I\nrefrained from it to avoid breaking it and causing issues for anyone\nreceiving that patch. Same for sending it using \"git pack\".\n\nIs this currently a limitation or am I just doing it wrong?\n\nSincerely,\nKlaus Frank\n"},{"id":"516062","messageId":"D95V0Z9YMEX2.3J99CE4F6ZP8S@lfurio.us","threadId":"63289","inReplyTo":"fx2ofmmhkjmjqfqya5e3qvmovvmpnjepteqobcz4eia5sw64bg@yquuljpwok3f","subject":"Re: How to gpg signed email patches?","fromName":"Matt Hunter","fromEmail":"m@lfurio.us","sentAt":"2025-04-13T22:21:46Z","receivedAt":"2025-04-13T22:21:53Z","isPatch":false,"sender":{"key":"m@lfurio.us","avatar":"https://avatars.githubusercontent.com/u/14925125?v=4"},"body":"Hi\n\nOn Sun Apr 13, 2025 at 3:17 PM EDT, Klaus Frank wrote:\n> how do I get \"git send-email\" to send the patches gpg signed? I tried\n> first signing the commit but after spending time looking into the\n> documentation I couldn't work out how to do it. All I discovered so far\n> is that the \"git send-email\" appears to be using \"git format-patch\"\n> internally and that's where it currently gets lost.\n\nThere's a conceptual issue with mailing patches from signed commits.\nOnce your patch recipient goes to apply it to their branch, they are\nrecorded as the \"committer\" identity of the new commit object.  This\nwould break the validity of any existing signature.\n\nThis is likely the reason by the related git tools (format-patch, am)\nignore this information.\n\nYou may have also noticed that commands like git-rebase and\ngit-cherry-pick will drop signatures from commits as well, since they\nare being replayed onto a different history, changing the commit data.\n"},{"id":"516063","messageId":"Z_xAOmQm0e_WE2Dd@tapette.crustytoothpaste.net","threadId":"63289","inReplyTo":"fx2ofmmhkjmjqfqya5e3qvmovvmpnjepteqobcz4eia5sw64bg@yquuljpwok3f","subject":"Re: How to gpg signed email patches?","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-04-13T22:52:42Z","receivedAt":"2025-04-13T22:52:50Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-04-13 at 19:17:26, Klaus Frank wrote:\n> Hi,\n\nHi,\n\n> how do I get \"git send-email\" to send the patches gpg signed? I tried\n> first signing the commit but after spending time looking into the\n> documentation I couldn't work out how to do it. All I discovered so far\n> is that the \"git send-email\" appears to be using \"git format-patch\"\n> internally and that's where it currently gets lost.\n> \n> Sadly none of the man pages I looked at so far mentions anything about\n> gpg signing in this regards. Not even \"git am\" does.\n> \n> Ideally I'd like to have \"git send-email\" send my patches gpg-signed to\n> ensure authenticity and integrity.\n> \n> I also considered alternatives like using my MTA to GPG-Sign these mails\n> however as the \"git am\" documentation also didn't mention gpg signing I\n> refrained from it to avoid breaking it and causing issues for anyone\n> receiving that patch. Same for sending it using \"git pack\".\n> \n> Is this currently a limitation or am I just doing it wrong?\n\nI don't think Git supports this out of the box.  The proper way to do\nthis would be via PGP/MIME, since clearsigning the patches would result\nin them not applying properly (due to the dashes being escaped).\n\nMore notably, I've had problems applying patches that are signed using\nPGP/MIME because `git am` doesn't seem to understand how to extract the\ndata in all cases (maybe it does in some cases, but I haven't tested).\nAs a practical matter, signing PGP/MIME requires that the enclosing body\nbe encoded as either quoted-printable (recommended) or base64 (not\nrecommended because plain text as base64 tends to be a sign of spam)\nbecause that prevents breakage from intervening mail servers and\nthat can introduce some trickiness in extracting the text without\nparsing the MIME structure.\n\nI know that Git definitely does not know how to verify those signatures,\nthough, so many people would end up not verifying them.\n\nThe discussion on the list in the past has generally not been in favour\nof this approach, since the assumption is that the patch is accepted\nbased on whether it is good or not and not whether it is authentic.  I\nacknowledge that there are workflows where authenticity is useful,\nthough, so I would not be opposed to seeing patches to implement this,\nbut I'm afraid that it has yet to be implemented.\n\nAn alternative approach, which has also been discussed (and which I\nmight end up sending a patch for at some point), is including committer,\nsignature, and base commit data in email headers to allow reconstructing\nthe exact commit with a valid signature.  Whether the maintainer chooses\nto keep that signature is of course up to them, but this would allow\nthe commit to be verified using the normal mechanism.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"516064","messageId":"fba4f0a0-3ca8-455c-bfb8-70118de89fad@frank.fyi","threadId":"63289","inReplyTo":"D95V0Z9YMEX2.3J99CE4F6ZP8S@lfurio.us","subject":"Re: How to gpg signed email patches?","fromName":"Klaus Frank","fromEmail":"vger.kernel.org@frank.fyi","sentAt":"2025-04-13T23:12:14Z","receivedAt":"2025-04-13T23:12:16Z","isPatch":false,"sender":{"key":"vger.kernel.org@frank.fyi","avatar":null},"body":"On 2025-04-14 00:21:46, Matt Hunter wrote:\n> Hi\n> There's a conceptual issue with mailing patches from signed commits.\n> Once your patch recipient goes to apply it to their branch, they are\n> recorded as the \"committer\" identity of the new commit object.  This\n> would break the validity of any existing signature.\n\nYou're right on that part. However even though it would be nice to\nget the signed commit into the public repo my main focus here was\nmore to ensure integrity and authenticity until it is processed by\nthe project maintainers. E.g. it didn't get mangled by some thing on\nthe way and I wasn't impersonated by someone else. E.g. I was\nmainly focusing on allowing the ones accepting my patch to know it\nis from me and it hasn't been tampered with on the way. E.g. by a mail\nserver screwing with the mail content or some middle box that inserted\nor rewrote parts of the message...\n\n> This is likely the reason by the related git tools (format-patch, am)\n> ignore this information.\nOk, how do others deal with that scenario then? Not an issue?\n> You may have also noticed that commands like git-rebase and\n> git-cherry-pick will drop signatures from commits as well, since they\n> are being replayed onto a different history, changing the commit data.\n\nTrue, but thouse commands to not pass information through a\nlossy and \"tampery\" media like email. It stays local. My main focus\nwas on the transfer from my git repo to the (git repo of) other\ndevs on the project. And lesser on it being preserved after the\nmerge.\n\nWhen a project uses a forge like github or gitlab this is basically\nnot such an issue because of TLS and having to have a\nuser account on it (and it preserving the pgp signature up until the\nlast click before being merged in)\n\n"},{"id":"516065","messageId":"0709104c-c951-42be-9300-a0aa9f9eea6c@frank.fyi","threadId":"63289","inReplyTo":"Z_xAOmQm0e_WE2Dd@tapette.crustytoothpaste.net","subject":"Re: How to gpg signed email patches?","fromName":"Klaus Frank","fromEmail":"vger.kernel.org@frank.fyi","sentAt":"2025-04-14T00:23:02Z","receivedAt":"2025-04-14T00:23:03Z","isPatch":false,"sender":{"key":"vger.kernel.org@frank.fyi","avatar":null},"body":"On 2025-04-14 00:52:42, brian m. carlson wrote:\n> On 2025-04-13 at 19:17:26, Klaus Frank wrote:\n>> Hi,\n>>\n>> I don't think Git supports this out of the box.  The proper way to do\n>> this would be via PGP/MIME, since clearsigning the patches would result\n>> in them not applying properly (due to the dashes being escaped).\nBut if \"git am\" would support pgp clearsigning it could just easily \nreverse that, no?\nBut I've to admit I didn't fully look into all of the escape rules and their\nreversability yet. Is RFC 4880 Section-7 the correct one for clearsign\nand RFC 3156 Section-5 the correct one for PGP/MIME?\n>> More notably, I've had problems applying patches that are signed using\n>> PGP/MIME because `git am` doesn't seem to understand how to extract the\n>> data in all cases (maybe it does in some cases, but I haven't tested).\n>> As a practical matter, signing PGP/MIME requires that the enclosing body\n>> be encoded as either quoted-printable (recommended) or base64 (not\n>> recommended because plain text as base64 tends to be a sign of spam)\n>> because that prevents breakage from intervening mail servers and\n>> that can introduce some trickiness in extracting the text without\n>> parsing the MIME structure.\n>>\n>> I know that Git definitely does not know how to verify those signatures,\n>> though, so many people would end up not verifying them.\n\nYea, then better just not include them for now.\nIncluding them sounds like a shitty move towards or better\nagainst the other developers. Kinda but not quite maliciouse compliance\nstyle. :/\n\n>> The discussion on the list in the past has generally not been in favour\n>> of this approach, since the assumption is that the patch is accepted\n>> based on whether it is good or not and not whether it is authentic.  I\n>> acknowledge that there are workflows where authenticity is useful,\n>> though, so I would not be opposed to seeing patches to implement this,\n>> but I'm afraid that it has yet to be implemented.\nThat may be, however the signature also shows if it has been damaged\nin transit and that is at least in my eyes a very valuable information.\n(And maybe in the near future to mandate everyone signs (or even\nencrypt) their contributions in order to easily ban \"vibe coders\")\n>> An alternative approach, which has also been discussed (and which I\n>> might end up sending a patch for at some point), is including committer,\n>> signature, and base commit data in email headers to allow reconstructing\n>> the exact commit with a valid signature.  Whether the maintainer chooses\n>> to keep that signature is of course up to them, but this would allow\n>> the commit to be verified using the normal mechanism.\n\nThat sounds also good compared to what I scetched up so far.\nThis is what I was thinking about btw (nothing special really):\n\nOn the sender side:\n1. \"git format-patch\"/\"git send-email\" sees that the commit{s} is/are \nsigned or it was executed with an explicit flag to sign (similar to \ngit-commit \"-S[<key-id>], --gpg-sign[=<key-id>], --no-gpg-sign\")\n2. Either \"git format-patch\":\n  a. Somehow embedds the commit signature as plain text [Your suggestion].\n  b. Does \"gpg --sign --clear-sign --include-key-block\" the entire \nemail (Or [rfc4880#section-7]).\n  c. When \"--inline\" is specified {multipart message} it creates a \ndetached signature (\"gpg --sign --detach-sign --include-key-block \n--armor\") and attach it as a 3rd \"application/pgp-signature\" part to the \nmultipart-message (or [RFC3156#Section-5] instead of literally \"just\" \nattaching an additional .sig file to the mail)\n3. Send the mail\nAlso \"git format-patch\" propably should support these gpg commandline \nproperties: `--homedir`, `--keyring`, `--primary-keyring`, \n`--refresh-keys`, `--armor`, `--no-armor`.\n\nOn the receiver side when running e.g. \"git am\":\nOn a mail without a signature\n=> Fallback to current behaviour accept (maybe have an optional \nconfigurable warning message). And have an option to enforce signatures \n(fail if enforced and missing).\nOn a mail with a signature:\na. If nothing else specified default to e.g. `gpg --verify --batch \n--auto-key-import --auto-key-retrieve --tofu-default-policy=\"auto\" \n--trust-model=\"tofu+pgp\"` (marginally trust all keys and build a web of \ntrust; Maybe on a dedicated gpg-homedir/keyring)\nb. If operating on the users generic gpg-homedir/keyring or explicitly \nspecified use `--tofu-default-policy=\"unknown\"` instead of \"auto\". This \nwill still import and validate keys from the signatures [depending on \nuser system config also from keyserver, ldap, ... but disabled by \ndefault] but any key the user didn't touch themselves will be considered \n\"unknown\" trusted and therefore won't be used for extending the web of \ntrust.\nc. also have flags for these gpg commandline properties: `--homedir`, \n`--keyring`, `--primary-keyring`, `--refresh-keys`.\nd. maybe also add pgp-encryption support (to also accept e.g. patches \nfor zero days?). All that would be needed for that is \"git am\" would \nhave to tell gpg to try to decript the message and similar \"git \nformat-patch\" would need one to encrypt.\n\n\nSincerely,\nKlaus Frank\n\n"},{"id":"516067","messageId":"Z_xbUDk7ra1-d_gH@tapette.crustytoothpaste.net","threadId":"63289","inReplyTo":"0709104c-c951-42be-9300-a0aa9f9eea6c@frank.fyi","subject":"Re: How to gpg signed email patches?","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-04-14T00:48:16Z","receivedAt":"2025-04-14T00:48:18Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-04-14 at 00:23:02, Klaus Frank wrote:\n> But if \"git am\" would support pgp clearsigning it could just easily reverse\n> that, no?\n\nYes, but not everybody has GnuPG installed on their system.  It doesn't\ncome by default on macOS and people will want to parse the emails and\napply the patches nonetheless.\n\n> But I've to admit I didn't fully look into all of the escape rules and their\n> reversability yet. Is RFC 4880 Section-7 the correct one for clearsign\n> and RFC 3156 Section-5 the correct one for PGP/MIME?\n\nYes, although RFC 9580 has superseded RFC 4880.\n\n> That may be, however the signature also shows if it has been damaged\n> in transit and that is at least in my eyes a very valuable information.\n> (And maybe in the near future to mandate everyone signs (or even\n> encrypt) their contributions in order to easily ban \"vibe coders\")\n\nI agree that it detects patches that have been damaged in transit, which\nis valuable, but it also throws a bunch of complexity into the process.\n\n> > > An alternative approach, which has also been discussed (and which I\n> > > might end up sending a patch for at some point), is including committer,\n> > > signature, and base commit data in email headers to allow reconstructing\n> > > the exact commit with a valid signature.  Whether the maintainer chooses\n> > > to keep that signature is of course up to them, but this would allow\n> > > the commit to be verified using the normal mechanism.\n> \n> That sounds also good compared to what I scetched up so far.\n> This is what I was thinking about btw (nothing special really):\n\nMy approach also has the benefit that it works for SSH commit\nsignatures, which PGP/MIME and S/MIME do not.  I think many people find\nSSH signatures to be easier to use than OpenPGP or X.509 and SSH signing\nis easier to do when one's working in a remote dev environment (just\nforward your agent).\n\n> On the sender side:\n> 1. \"git format-patch\"/\"git send-email\" sees that the commit{s} is/are signed\n> or it was executed with an explicit flag to sign (similar to git-commit\n> \"-S[<key-id>], --gpg-sign[=<key-id>], --no-gpg-sign\")\n> 2. Either \"git format-patch\":\n>   a. Somehow embedds the commit signature as plain text [Your suggestion].\n>   b. Does \"gpg --sign --clear-sign --include-key-block\" the entire email (Or\n> [rfc4880#section-7]).\n>   c. When \"--inline\" is specified {multipart message} it creates a detached\n> signature (\"gpg --sign --detach-sign --include-key-block --armor\") and\n> attach it as a 3rd \"application/pgp-signature\" part to the multipart-message\n> (or [RFC3156#Section-5] instead of literally \"just\" attaching an additional\n> .sig file to the mail)\n\nThis isn't the entirety of how it works.  I believe the headers of the\ninternal part (e.g., Content-Type and Content-Transfer-Encoding) are\nalso signed in PGP/MIME; that is, it's the entire body part, headers and\nall.\n\n> 3. Send the mail\n> Also \"git format-patch\" propably should support these gpg commandline\n> properties: `--homedir`, `--keyring`, `--primary-keyring`, `--refresh-keys`,\n> `--armor`, `--no-armor`.\n\nThose arguments are really better left to a script that runs as\n`gpg.program`.  There are other implementations of that software that\nonly support the bare minimum options (e.g., smimesign) and we want to\nminimize the functionality that needs to be supported.  I have, for\ninstance, used a custom script to include a signature from the\nenvironment that was generated on another machine.\n\nThat's another advantage to my approach: it avoids the necessity for\nadditional options to be supported.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"516068","messageId":"20250413-dancing-acoustic-marten-cc7a7d@lemur","threadId":"63289","inReplyTo":"fx2ofmmhkjmjqfqya5e3qvmovvmpnjepteqobcz4eia5sw64bg@yquuljpwok3f","subject":"Re: How to gpg signed email patches?","fromName":"Konstantin Ryabitsev","fromEmail":"konstantin@linuxfoundation.org","sentAt":"2025-04-14T01:34:56Z","receivedAt":"2025-04-14T01:35:00Z","isPatch":false,"sender":{"key":"konstantin@linuxfoundation.org","avatar":"https://gravatar.com/avatar/7cb8827c6de56e1bd2dea16508c6708aa43feed3bf3813bcdacecdf96ceadd79?d=mp&s=160"},"body":"On Sun, Apr 13, 2025 at 07:17:26PM +0000, Klaus Frank wrote:\n> how do I get \"git send-email\" to send the patches gpg signed?\n\nYou have to step back and ask what is the end-goal? Do you want\nrepudiation/attestation for your own patches, or do you want to be able to\nverify that the patches sent to you by contributors are tamper-evident?\n\nOn the kernel side of things, we've been using patatt [1], which supports PGP,\nSSH, and ed25519-signing of patches via a dedicated custom header, a-la DKIM.\n\n[1] https://github.com/mricon/patatt/blob/main/README.rst\n\n-K\n"},{"id":"516105","messageId":"xmqq34easrlo.fsf@gitster.g","threadId":"63289","inReplyTo":"20250413-dancing-acoustic-marten-cc7a7d@lemur","subject":"Re: How to gpg signed email patches?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-14T15:14:11Z","receivedAt":"2025-04-14T15:14:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Konstantin Ryabitsev <konstantin@linuxfoundation.org> writes:\n\n> On Sun, Apr 13, 2025 at 07:17:26PM +0000, Klaus Frank wrote:\n>> how do I get \"git send-email\" to send the patches gpg signed?\n>\n> You have to step back and ask what is the end-goal? Do you want\n> repudiation/attestation for your own patches, or do you want to be able to\n> verify that the patches sent to you by contributors are tamper-evident?\n\nExcellent question.  These are probably both addressed by signed\ne-mails, but quite different from what object-level signing\n(e.g. \"git commit --signed\") aims at.\n\n> On the kernel side of things, we've been using patatt [1], which supports PGP,\n> SSH, and ed25519-signing of patches via a dedicated custom header, a-la DKIM.\n>\n> [1] https://github.com/mricon/patatt/blob/main/README.rst\n>\n> -K\n\n"},{"id":"516115","messageId":"xmqqfriar9bw.fsf@gitster.g","threadId":"63289","inReplyTo":"D95V0Z9YMEX2.3J99CE4F6ZP8S@lfurio.us","subject":"Re: How to gpg signed email patches?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-14T16:34:11Z","receivedAt":"2025-04-14T16:34:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Matt Hunter\" <m@lfurio.us> writes:\n\n> Hi\n>\n> On Sun Apr 13, 2025 at 3:17 PM EDT, Klaus Frank wrote:\n>> how do I get \"git send-email\" to send the patches gpg signed? I tried\n>> first signing the commit but after spending time looking into the\n>> documentation I couldn't work out how to do it. All I discovered so far\n>> is that the \"git send-email\" appears to be using \"git format-patch\"\n>> internally and that's where it currently gets lost.\n>\n> There's a conceptual issue with mailing patches from signed commits.\n> Once your patch recipient goes to apply it to their branch, they are\n> recorded as the \"committer\" identity of the new commit object.  This\n> would break the validity of any existing signature.\n>\n> This is likely the reason by the related git tools (format-patch, am)\n> ignore this information.\n>\n> You may have also noticed that commands like git-rebase and\n> git-cherry-pick will drop signatures from commits as well, since they\n> are being replayed onto a different history, changing the commit data.\n\nVery well said.  Protecting the e-mail with GPG is a job for\nMUA/MSA, that is independent from signature used to sign objects\nlike commits and tags, so the signature over objects cannot be\nreused by programs like send-email.\n\nBut send-email may not have an option to wrap its payload in s-mime\nor pgp, which can be a separate project worth looking into.\n\nThanks.\n\n\n"},{"id":"516120","messageId":"xmqqa58ir20e.fsf@gitster.g","threadId":"63289","inReplyTo":"Z_xAOmQm0e_WE2Dd@tapette.crustytoothpaste.net","subject":"Re: How to gpg signed email patches?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-04-14T19:12:17Z","receivedAt":"2025-04-14T19:12:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> I know that Git definitely does not know how to verify those signatures,\n> though, so many people would end up not verifying them.\n\n\nTrue that many people would end up not verifying them, but I do not\nthink Git has much to do with that.\n\nSome contributors seem to send PGP signed patches to this list (and\nI once mildly asked them not to, but these days I simply do not\ncare), and if I had their public keys marked as trusted, my\nmail-reading environment would do the verification for me totally\noutside Git (as this part of the workflow is not about Git, but\nabout communicating over authenticated and cryptographically\nprotected messages, whose contents happen to be patches), and I'll\njust \"git am\" knowing that the patch is from the contributor who has\naccess to that trusted key.\n\nThe \"key\" (no pun intended) in the above is \"if I had\" part.  The\noverhead of retrieving, validating, and keeping the key for a\ncontributor becomes worth it only after the contributor turns out to\nbe very prolific one.  The Web of trust, while was very attractive\nas a concept, is not so convenient to maintain well enough to be\nrelied on as an infrastructure.\n\n\n\n\n"}]}