Reported by: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net>
Date: Fri, 16 May 2025 03:57:02 UTC
Severity: normal
Found in version 30.1
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> To: bug-gnu-emacs <at> gnu.org, bugs <at> gnus.org Subject: 30.1; mml: Produce Unobtrusive Signatures Date: Thu, 15 May 2025 23:56:25 -0400
[Message part 1 (text/plain, inline)]
Package: emacs,gnus Version: 30.1 I'm running emacs 30.1 on debian. When sending cleartext mail, i want to be able to produce an "Unobtrusive Signature" using OpenPGP as described in https://datatracker.ietf.org/doc/draft-gallagher-email-unobtrusive-signatures/ Those kinds of signatures provide end-to-end cryptographic protection for headers (based on https://datatracker.ietf.org/doc/draft-ietf-lamps-header-protection/ ) as well as the message body, and are less likely to inflict bad UX or bad rendering on recipients using legacy MUAs compared to PGP/MIME (or inline PGP, for that matter). These three patches appear to do the trick for me. I'm not an elisp guru or a gnus expert. I'm happy to hear any feedback about how they could be improved. Regards, --dkg
[0001-mml-Pass-likely-headers-through-to-mml-sec-functions.patch (text/x-diff, inline)]
From 81c3e7f5de0bbb24bbd2a2b43a103fb83c530f6d Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 21:49:32 -0400 Subject: [PATCH 1/3] mml: Pass likely headers through to mml-sec functions By pre-computing the likely headers for an outbound message, and passing them along as a tag in mml-parse, we create an opportunity to provide Header Protection as described in https://datatracker.ietf.org/doc/draft-ietf-lamps-header-protection/ Signed-off-by: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> --- lisp/gnus/mml.el | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 51d8d2c3769..11a8de7c011 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -265,6 +265,8 @@ part. This is for the internal use, you should never modify the value.") (apply #'mml-insert-tag secure-mode `(,@tags + ,"likely-headers" + ,(mml-get-likely-headers) ,(if keyfile "keyfile") ,keyfile ,@(apply #'append @@ -492,6 +494,21 @@ If MML is non-nil, return the buffer up till the correspondent mml tag." (declare-function libxml-parse-html-region "xml.c" (start end &optional base-url discard-comments)) +(defun mml-get-likely-headers () + "Get likely final headers from the existing message" + (save-excursion + (save-restriction + (message-narrow-to-headers-or-head) + (let ((x (buffer-substring (point-min) (point-max)))) + (with-temp-buffer + (insert x) + (message-remove-header "Bcc") + (message-remove-header message-ignored-mail-headers t) + (mail-encode-encoded-word-buffer) + (message-cleanup-headers) + (buffer-string) + ))))) + (defun mml-generate-mime (&optional multipart-type content-type) "Generate a MIME message based on the current MML document. MULTIPART-TYPE defaults to \"mixed\", but can also -- 2.47.2
[0002-mml-Enable-production-of-Unobtrusive-Signatures-via-.patch (text/x-diff, inline)]
From 75f8c5c936deafea1ee44edad5e0f530ec6c4dfc Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 21:54:06 -0400 Subject: [PATCH 2/3] mml: Enable production of Unobtrusive Signatures via epg https://datatracker.ietf.org/doc/draft-gallagher-email-invisible-signatures/ describes a mechanism to produce cleartext signatures over MIME messages that are less likely to cause problems than traditional PGP/MIME. With this patch, it's possible to produce those signatures with: (mml-secure-message "unobtrusive" 'sign) This patch only works with epg, not with mailcrypt or pgg, because epg is what i'm familiar with and what i can easily test. Signed-off-by: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> --- lisp/gnus/mml-sec.el | 6 ++++++ lisp/gnus/mml2015.el | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 8dffcf872f3..6fb82836e9a 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -34,6 +34,7 @@ (autoload 'mail-strip-quoted-names "mail-utils") (autoload 'mml2015-sign "mml2015") (autoload 'mml2015-encrypt "mml2015") +(autoload 'mml-unobtrusive-sign "mml2015") (autoload 'mml1991-sign "mml1991") (autoload 'mml1991-encrypt "mml1991") (autoload 'message-fetch-field "message") @@ -56,6 +57,7 @@ '(("smime" mml-smime-sign-buffer mml-smime-sign-query) ("pgp" mml-pgp-sign-buffer list) ("pgpauto" mml-pgpauto-sign-buffer list) + ("unobtrusive" mml-unobtrusive-sign-buffer list) ("pgpmime" mml-pgpmime-sign-buffer list)) "Alist of MIME signer functions.") @@ -198,6 +200,10 @@ You can also customize or set `mml-signencrypt-style-alist' instead." (or (mml2015-sign cont) (error "Signing failed... inspect message logs for errors"))) +(defun mml-unobtrusive-sign-buffer (cont) + (or (mml-unobtrusive-sign cont) + (error "Signing failed... inspect message logs for errors"))) + (defun mml-pgpmime-encrypt-buffer (cont &optional sign) (or (mml2015-encrypt cont sign) (error "Encryption failed... inspect message logs for errors"))) diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el index a46aa68f56a..646fb018a31 100644 --- a/lisp/gnus/mml2015.el +++ b/lisp/gnus/mml2015.el @@ -25,6 +25,9 @@ ;; RFC 2015 is updated by RFC 3156, this file should be compatible ;; with both. +;; This is also capable of producing unobtrusive signatures based on +;; draft-gallagher-email-unobtrusive-signatures + ;;; Code: (eval-when-compile (require 'cl-lib)) @@ -945,6 +948,42 @@ If set, it overrides the setting of `mml2015-sign-with-sender'." (insert (format "--%s--\n" boundary)) (goto-char (point-max)))) +;;; Unobtrusive Signatures, see: +;;; https://datatracker.ietf.org/doc/draft-gallagher-email-unobtrusive-signatures/ + +; convert ASCII-armored PGP SIGNATURE block to base64-encoded with FWS +; at the start of each line: +(defun pgpsig-armor-to-wrapped-b64 (s) + (string-join + (string-split + (string-trim-right + (string-trim-left s "-----BEGIN PGP SIGNATURE-----\n\\(?:[^\n]+\n\\)*\n") + "\n\\(?:=....\n\\)?-----END PGP SIGNATURE-----\n?") + "\n") + "\n ")) + +(defun mml-unobtrusive-sign (cont) + (goto-char (point-min)) + (insert (cdr (assq 'likely-headers cont))) + (re-search-forward "^Content-Type: [^\n]*\\(\n[ \t][^\n]*$\\)*") + (insert "; hp=\"clear\"") + (re-search-forward "^") + (let* ((pair (mml-secure-epg-sign 'OpenPGP t)) + (signature (car pair))) + (unless (stringp signature) + (error "Signature failed")) + (goto-char (point-min)) + (insert (format "Sig: t=p; b=%s\n" + (pgpsig-armor-to-wrapped-b64 signature))) + (let ((boundary (mml-compute-boundary cont))) + (goto-char (point-min)) + (insert (format "Content-Type: multipart/mixed; boundary=\"%s\";\n" + boundary)) + (insert (format "\n--%s\n" boundary)) + (goto-char (point-max)) + (insert (format "\n--%s--\n" boundary)) + (goto-char (point-max))))) + ;;; General wrapper (autoload 'gnus-buffer-live-p "gnus-util") -- 2.47.2
[0003-mml-Add-C-c-RET-s-u-to-make-Unobtrusive-Signature.patch (text/x-diff, inline)]
From f03c16ddedaa0b7a39692629ab61e7c3b3e06201 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> Date: Thu, 15 May 2025 22:03:25 -0400 Subject: [PATCH 3/3] mml: Add C-c RET s u to make Unobtrusive Signature This adds to the default keymap to make it relatively easy to make an Unobtrusive Signature when sending mail. Signed-off-by: Daniel Kahn Gillmor <dkg <at> fifthhorseman.net> --- lisp/gnus/mml-sec.el | 5 +++++ lisp/gnus/mml.el | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 6fb82836e9a..9b703abd5f4 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -285,6 +285,11 @@ Use METHOD if given. Else use `mml-secure-method' or (interactive nil mml-mode) (mml-secure-part "pgpmime" 'sign)) +(defun mml-secure-sign-unobtrusive () + "Add MML tags to unobtrusively sign this MML part." + (interactive nil mml-mode) + (mml-secure-part "unobtrusive" 'sign)) + (defun mml-secure-sign-smime () "Add MML tags to S/MIME sign this MML part." (interactive nil mml-mode) diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index 11a8de7c011..7d849335154 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -1178,11 +1178,13 @@ If HANDLES is non-nil, use it instead reparsing the buffer." "s" (define-keymap "p" #'mml-secure-message-sign-pgpmime "o" #'mml-secure-message-sign-pgp - "s" #'mml-secure-message-sign-smime) + "s" #'mml-secure-message-sign-smime + "u" #'mml-secure-message-sign-unobtrusive) "S" (define-keymap "p" #'mml-secure-sign-pgpmime "o" #'mml-secure-sign-pgp - "s" #'mml-secure-sign-smime) + "s" #'mml-secure-sign-smime + "u" #'mml-secure-message-sign-unobtrusive) "c" (define-keymap "p" #'mml-secure-message-encrypt-pgpmime "o" #'mml-secure-message-encrypt-pgp -- 2.47.2
[signature.asc (application/pgp-signature, inline)]
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.