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
To reply to this bug, email your comments to 78448 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org, bugs <at> gnus.org
:bug#78448
; Package emacs,gnus
.
(Fri, 16 May 2025 03:57:03 GMT) Full text and rfc822 format available.Daniel Kahn Gillmor <dkg <at> fifthhorseman.net>
:bug-gnu-emacs <at> gnu.org, bugs <at> gnus.org
.
(Fri, 16 May 2025 03:57:03 GMT) Full text and rfc822 format available.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.