OSDN Git Service

Fixed header.
[epg/epg.git] / pgg-epg.el
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
5
6 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: PGP, GnuPG, Gnus
8
9 ;; This file is part of EasyPG.
10
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)
14 ;; any later version.
15
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.
20
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.
25
26 ;;; Commentary:
27
28 ;; To use, add (setq pgg-scheme 'epg) to your ~/.gnus.
29
30 ;;; Code:
31
32 (require 'epg)
33 (eval-when-compile (require 'pgg))
34
35 (defvar pgg-epg-secret-key-id-list nil)
36
37 (defun pgg-epg-passphrase-callback (context key-id ignore)
38   (if (eq key-id 'SYM)
39       (epg-passphrase-callback-function context key-id nil)
40     (let* ((entry (assoc key-id epg-user-id-alist))
41            (passphrase
42             (pgg-read-passphrase
43              (format "GnuPG passphrase for %s: "
44                      (if entry
45                          (cdr entry)
46                        key-id))
47              (if (eq key-id 'PIN)
48                  "PIN"
49                key-id))))
50       (when passphrase
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)))))
55
56 (defvar inhibit-redisplay)
57 (defun pgg-epg-encrypt-region (start end recipients &optional sign passphrase)
58   "This function is for internal use only.
59
60 Encrypt the current region between START and END.
61
62 If optional argument SIGN is non-nil, do a combined sign and encrypt.
63
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
68         cipher)
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)
72     (save-excursion
73       (set-buffer (get-buffer-create pgg-output-buffer))
74       (erase-buffer)
75       (set-buffer (get-buffer-create pgg-errors-buffer))
76       (erase-buffer))
77     (condition-case error
78         (setq cipher
79               (epg-encrypt-string context
80                                   (buffer-substring start end)
81                                   (mapcar
82                                    (lambda (recipient)
83                                      (car (epg-list-keys recipient)))
84                                    (if pgg-encrypt-for-me
85                                        (cons pgg-default-user-id recipients)
86                                      recipients))
87                                   sign t)
88               pgg-epg-secret-key-id-list nil)
89       (error
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))))
94     (save-excursion
95       (set-buffer (get-buffer-create pgg-output-buffer))
96       (insert cipher))
97     t))
98
99 (defun pgg-epg-encrypt-symmetric-region (start end &optional passphrase)
100   "This function is for internal use only.
101
102 Encrypt the current region between START and END with symmetric cipher.
103
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))
107
108 (defun pgg-epg-decrypt-region (start end &optional passphrase)
109   "This function is for internal use only.
110
111 Decrypt the current region between START and END.
112
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
117         plain)
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)
121     (save-excursion
122       (set-buffer (get-buffer-create pgg-output-buffer))
123       (erase-buffer)
124       (set-buffer (get-buffer-create pgg-errors-buffer))
125       (erase-buffer))
126     (condition-case error
127         (setq plain
128               (decode-coding-string
129                (epg-decrypt-string context (buffer-substring start end))
130                'raw-text)
131               pgg-epg-secret-key-id-list nil)
132       (error
133        (while pgg-epg-secret-key-id-list
134          (pgg-remove-passphrase-from-cache (car pgg-epg-secret-key-id-list))
135          (setq pgg-epg-secret-key-id-list (cdr pgg-epg-secret-key-id-list)))
136        (signal (car error) (cdr error))))
137     (save-excursion
138       (set-buffer (get-buffer-create pgg-output-buffer))
139       (insert plain))
140     t))
141
142 (defun pgg-epg-sign-region (start end &optional cleartext passphrase)
143   "This function is for internal use only.
144
145 Make detached signature from text between START and END.
146
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
151         signature)
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     (save-excursion
156       (set-buffer (get-buffer-create pgg-output-buffer))
157       (erase-buffer)
158       (set-buffer (get-buffer-create pgg-errors-buffer))
159       (erase-buffer))
160     (condition-case error
161         (setq signature
162               (epg-sign-string context
163                                (buffer-substring start end)
164                                (if cleartext
165                                    'clearsign
166                                  'detached))
167               pgg-epg-secret-key-id-list nil)
168       (error
169        (while pgg-epg-secret-key-id-list
170          (pgg-remove-passphrase-from-cache (car pgg-epg-secret-key-id-list))
171          (setq pgg-epg-secret-key-id-list (cdr pgg-epg-secret-key-id-list)))
172        (signal (car error) (cdr error))))
173     (save-excursion
174       (set-buffer (get-buffer-create pgg-output-buffer))
175       (insert signature))
176     t))
177
178 (defvar pgg-epg-signatures nil)
179
180 (defun pgg-epg-verify-region (start end &optional signature)
181   "This function is for internal use only.
182
183 Verify region between START and END as the detached signature SIGNATURE."
184   (let ((context (epg-make-context))
185         (inhibit-redisplay t))          ;Gnus users don't like flickering
186     (epg-context-set-armor context t)
187     (epg-context-set-textmode context pgg-text-mode)
188     (save-excursion
189       (set-buffer (get-buffer-create pgg-output-buffer))
190       (erase-buffer)
191       (set-buffer (get-buffer-create pgg-errors-buffer))
192       (erase-buffer))
193     (if signature
194         (epg-verify-string context
195                            (with-temp-buffer
196                              (insert-file-contents signature)
197                              (buffer-string))
198                            (buffer-substring start end))
199       (epg-verify-string context (buffer-substring start end)))
200     (save-excursion
201       (set-buffer (get-buffer-create pgg-errors-buffer))
202       (make-local-variable 'pgg-epg-signatures)
203       (setq pgg-epg-signatures (epg-context-result-for context 'verify))
204       (insert (epg-verify-result-to-string pgg-epg-signatures)))
205     t))
206
207 (defun pgg-epg-insert-key ()
208   "This function is for internal use only.
209
210 Insert public key at point."
211   (let ((context (epg-make-context))
212         (inhibit-redisplay t)           ;Gnus users don't like flickering
213         )
214     (epg-context-set-armor context t)
215     (epg-context-set-textmode context pgg-text-mode)
216     (save-excursion
217       (set-buffer (get-buffer-create pgg-output-buffer))
218       (erase-buffer)
219       (set-buffer (get-buffer-create pgg-errors-buffer))
220       (erase-buffer))
221     (insert (epg-export-keys-to-string context pgg-default-user-id))))
222
223 (defun pgg-epg-snarf-keys-region (start end)
224   "This function is for internal use only.
225
226 Add all public keys in region between START and END to the keyring."
227   (let ((context (epg-make-context))
228         (inhibit-redisplay t)           ;Gnus users don't like flickering
229         )
230     (epg-context-set-armor context t)
231     (epg-context-set-textmode context pgg-text-mode)
232     (save-excursion
233       (set-buffer (get-buffer-create pgg-output-buffer))
234       (erase-buffer)
235       (set-buffer (get-buffer-create pgg-errors-buffer))
236       (erase-buffer))
237     (epg-import-keys-from-string context (buffer-substring start end))))
238
239 (eval-when-compile
240   (autoload 'mml2015-gpg-pretty-print-fpr "mml2015"))
241 (defun mml2015-gpg-extract-signature-details ()
242   (if pgg-epg-signatures
243       (let* ((expired (eq (epg-signature-status (car pgg-epg-signatures))
244                           'key-expired))
245              (signer (cons (epg-signature-key-id (car pgg-epg-signatures))
246                            (cdr (assoc (epg-signature-key-id
247                                         (car pgg-epg-signatures))
248                                        epg-user-id-alist))))
249              (fprint (epg-signature-fingerprint (car pgg-epg-signatures)))
250              (trust-good-enough-p
251               (memq (epg-signature-validity (car pgg-epg-signatures))
252                     '(marginal fully ultimate))))
253         (cond ((and signer fprint)
254                (concat (cdr signer)
255                        (unless trust-good-enough-p
256                          (concat "\nUntrusted, Fingerprint: "
257                                  (mml2015-gpg-pretty-print-fpr fprint)))
258                        (when expired
259                          (format "\nWARNING: Signature from expired key (%s)"
260                                  (car signer)))))
261               (t
262                "From unknown user")))
263     "From unknown user"))
264
265 (provide 'pgg-epg)
266
267 ;;; pgg-epg.el ends here