1 ;;; pgg-epg.el --- Gnus' PGG backend of EasyPG.
2 ;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
3 ;; 2005, 2006 Free Software Foundation, Inc.
4 ;; Copyright (C) 2006 Daiki Ueno
6 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: PGP, GnuPG, Gnus
9 ;; This file is part of EasyPG.
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
28 ;; To use, add (setq pgg-scheme 'epg) to your ~/.gnus.
33 (eval-when-compile (require 'pgg))
35 (defvar pgg-epg-secret-key-id-list nil)
37 (defun pgg-epg-passphrase-callback (context key-id ignore)
39 (epg-passphrase-callback-function context key-id nil)
40 (let* ((entry (assoc key-id epg-user-id-alist))
43 (format "GnuPG passphrase for %s: "
51 (pgg-add-passphrase-to-cache key-id passphrase)
52 (setq pgg-epg-secret-key-id-list
53 (cons key-id pgg-epg-secret-key-id-list))
54 (copy-sequence passphrase)))))
56 (defvar inhibit-redisplay)
57 (defun pgg-epg-encrypt-region (start end recipients &optional sign passphrase)
58 "This function is for internal use only.
60 Encrypt the current region between START and END.
62 If optional argument SIGN is non-nil, do a combined sign and encrypt.
64 If optional PASSPHRASE is not specified, it will be obtained from the
65 passphrase cache or user."
66 (let ((context (epg-make-context))
67 (inhibit-redisplay t) ;Gnus users don't like flickering
69 (epg-context-set-armor context t)
70 (epg-context-set-textmode context pgg-text-mode)
71 (epg-context-set-passphrase-callback context #'pgg-epg-passphrase-callback)
73 (set-buffer (get-buffer-create pgg-output-buffer))
75 (set-buffer (get-buffer-create pgg-errors-buffer))
79 (epg-encrypt-string context
80 (buffer-substring start end)
83 (car (epg-list-keys context recipient)))
84 (if pgg-encrypt-for-me
85 (cons pgg-default-user-id recipients)
88 pgg-epg-secret-key-id-list nil)
90 (while pgg-epg-secret-key-id-list
91 (pgg-remove-passphrase-from-cache (car pgg-epg-secret-key-id-list))
92 (setq pgg-epg-secret-key-id-list (cdr pgg-epg-secret-key-id-list)))
93 (signal (car error) (cdr error))))
95 (set-buffer (get-buffer-create pgg-output-buffer))
99 (defun pgg-epg-encrypt-symmetric-region (start end &optional passphrase)
100 "This function is for internal use only.
102 Encrypt the current region between START and END with symmetric cipher.
104 If optional PASSPHRASE is not specified, it will be obtained from the
105 passphrase cache or user."
106 (pgg-epg-encrypt-region start end nil))
108 (defun pgg-epg-decrypt-region (start end &optional passphrase)
109 "This function is for internal use only.
111 Decrypt the current region between START and END.
113 If optional PASSPHRASE is not specified, it will be obtained from the
114 passphrase cache or user."
115 (let ((context (epg-make-context))
116 (inhibit-redisplay t) ;Gnus users don't like flickering
118 (epg-context-set-armor context t)
119 (epg-context-set-textmode context pgg-text-mode)
120 (epg-context-set-passphrase-callback context #'pgg-epg-passphrase-callback)
122 (set-buffer (get-buffer-create pgg-output-buffer))
124 (set-buffer (get-buffer-create pgg-errors-buffer))
126 (condition-case error
128 (epg-decrypt-string context (buffer-substring start end))
129 pgg-epg-secret-key-id-list nil)
131 (while pgg-epg-secret-key-id-list
132 (pgg-remove-passphrase-from-cache (car pgg-epg-secret-key-id-list))
133 (setq pgg-epg-secret-key-id-list (cdr pgg-epg-secret-key-id-list)))
134 (signal (car error) (cdr error))))
136 (setq plain (decode-coding-string plain 'raw-text)))
138 (set-buffer (get-buffer-create pgg-output-buffer))
142 (defun pgg-epg-sign-region (start end &optional cleartext passphrase)
143 "This function is for internal use only.
145 Make detached signature from text between START and END.
147 If optional PASSPHRASE is not specified, it will be obtained from the
148 passphrase cache or user."
149 (let ((context (epg-make-context))
150 (inhibit-redisplay t) ;Gnus users don't like flickering
152 (epg-context-set-armor context t)
153 (epg-context-set-textmode context pgg-text-mode)
154 (epg-context-set-passphrase-callback context #'pgg-epg-passphrase-callback)
155 (epg-context-set-signers
157 (list (car (epg-list-keys context pgg-default-user-id t))))
159 (set-buffer (get-buffer-create pgg-output-buffer))
161 (set-buffer (get-buffer-create pgg-errors-buffer))
163 (condition-case error
165 (epg-sign-string context
166 (buffer-substring start end)
170 pgg-epg-secret-key-id-list nil)
172 (while pgg-epg-secret-key-id-list
173 (pgg-remove-passphrase-from-cache (car pgg-epg-secret-key-id-list))
174 (setq pgg-epg-secret-key-id-list (cdr pgg-epg-secret-key-id-list)))
175 (signal (car error) (cdr error))))
177 (set-buffer (get-buffer-create pgg-output-buffer))
181 (defvar pgg-epg-signatures nil)
183 (defun pgg-epg-verify-region (start end &optional signature)
184 "This function is for internal use only.
186 Verify region between START and END as the detached signature SIGNATURE."
187 (let ((context (epg-make-context))
188 (inhibit-redisplay t)) ;Gnus users don't like flickering
189 (epg-context-set-armor context t)
190 (epg-context-set-textmode context pgg-text-mode)
192 (set-buffer (get-buffer-create pgg-output-buffer))
194 (set-buffer (get-buffer-create pgg-errors-buffer))
197 (epg-verify-string context
199 (insert-file-contents signature)
201 (buffer-substring start end))
202 (epg-verify-string context (buffer-substring start end)))
204 (set-buffer (get-buffer-create pgg-errors-buffer))
205 (make-local-variable 'pgg-epg-signatures)
206 (setq pgg-epg-signatures (epg-context-result-for context 'verify))
207 (insert (epg-verify-result-to-string pgg-epg-signatures)))
210 (defun pgg-epg-insert-key ()
211 "This function is for internal use only.
213 Insert public key at point."
214 (let ((context (epg-make-context))
215 (inhibit-redisplay t) ;Gnus users don't like flickering
217 (epg-context-set-armor context t)
218 (epg-context-set-textmode context pgg-text-mode)
220 (set-buffer (get-buffer-create pgg-output-buffer))
222 (set-buffer (get-buffer-create pgg-errors-buffer))
224 (insert (epg-export-keys-to-string context pgg-default-user-id))))
226 (defun pgg-epg-snarf-keys-region (start end)
227 "This function is for internal use only.
229 Add all public keys in region between START and END to the keyring."
230 (let ((context (epg-make-context))
231 (inhibit-redisplay t) ;Gnus users don't like flickering
233 (epg-context-set-armor context t)
234 (epg-context-set-textmode context pgg-text-mode)
236 (set-buffer (get-buffer-create pgg-output-buffer))
238 (set-buffer (get-buffer-create pgg-errors-buffer))
240 (epg-import-keys-from-string context (buffer-substring start end))))
243 (autoload 'mml2015-gpg-pretty-print-fpr "mml2015"))
244 (defun mml2015-gpg-extract-signature-details ()
245 (if pgg-epg-signatures
246 (let* ((expired (eq (epg-signature-status (car pgg-epg-signatures))
248 (signer (cons (epg-signature-key-id (car pgg-epg-signatures))
249 (cdr (assoc (epg-signature-key-id
250 (car pgg-epg-signatures))
251 epg-user-id-alist))))
252 (fprint (epg-signature-fingerprint (car pgg-epg-signatures)))
254 (memq (epg-signature-validity (car pgg-epg-signatures))
255 '(marginal fully ultimate))))
256 (cond ((and signer fprint)
258 (unless trust-good-enough-p
259 (concat "\nUntrusted, Fingerprint: "
260 (mml2015-gpg-pretty-print-fpr fprint)))
262 (format "\nWARNING: Signature from expired key (%s)"
265 "From unknown user")))
266 "From unknown user"))
268 (defun pgg-epg-lookup-key (string &optional type)
269 "Search keys associated with STRING."
270 (mapcar (lambda (key)
271 (epg-sub-key-id (car (epg-key-sub-key-list key))))
272 (epg-list-keys (epg-make-context) string (not (null type)))))
276 ;;; pgg-epg.el ends here