1 ;;; epg.el --- the EasyPG Library
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
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.
31 (defcustom epg-gpg-program "gpg"
32 "The `gpg' executable."
36 (defvar epg-user-id nil
37 "GnuPG ID of your default identity.")
39 (defvar epg-user-id-alist nil
40 "An alist mapping from key ID to user ID.")
42 (defvar epg-read-point nil)
43 (defvar epg-pending-status-list nil)
44 (defvar epg-key-id nil)
45 (defvar epg-context nil)
46 (defvar epg-debug nil)
48 ;; from gnupg/include/cipher.h
49 (defconst epg-cipher-algorithm-alist
61 ;; from gnupg/include/cipher.h
62 (defconst epg-pubkey-algorithm-alist
70 ;; from gnupg/include/cipher.h
71 (defconst epg-digest-algorithm-alist
79 ;; from gnupg/include/cipher.h
80 (defconst epg-compress-algorithm-alist
86 (defconst epg-invalid-recipients-alist
87 '((0 . "No specific reason given")
89 (2 . "Ambigious specification")
90 (3 . "Wrong key usage")
95 (8 . "Policy mismatch")
96 (9 . "Not a secret key")
97 (10 . "Key not trusted")))
99 (defvar epg-key-validity-alist
112 (defvar epg-key-capablity-alist
116 (?a . authentication)))
118 (defvar epg-prompt-alist nil)
120 (defun epg-make-data-from-file (file)
121 "Make a data object from FILE."
124 (defun epg-make-data-from-string (string)
125 "Make a data object from STRING."
128 (defun epg-data-file (data)
129 "Return the file of DATA."
132 (defun epg-data-string (data)
133 "Return the string of DATA."
136 (defun epg-make-context (&optional protocol armor textmode include-certs)
137 "Return a context object."
138 (vector protocol armor textmode include-certs
139 #'epg-passphrase-callback-function
140 #'epg-progress-callback-function
143 (defun epg-context-protocol (context)
144 "Return the protocol used within the context."
147 (defun epg-context-armor (context)
148 "Return t if the output shouled be ASCII armored in the CONTEXT context."
151 (defun epg-context-textmode (context)
152 "Return t if canonical text mode should be used in the CONTEXT context."
155 (defun epg-context-include-certs (context)
156 "Return how many certificates should be included in an S/MIME signed
160 (defun epg-context-passphrase-callback (context)
161 "Return the function used to query passphrase."
164 (defun epg-context-progress-callback (context)
165 "Return the function which handles progress update."
168 (defun epg-context-signers (context)
169 "Return the list of key-id for singning."
172 (defun epg-context-process (context)
173 "Return the process object of `epg-gpg-program'.
174 This function is for internal use only."
177 (defun epg-context-output-file (context)
178 "Return the output file of `epg-gpg-program'.
179 This function is for internal use only."
182 (defun epg-context-result (context)
183 "Return the result of the previous cryptographic operation."
186 (defun epg-context-set-protocol (context protocol)
187 "Set the protocol used within the context."
188 (aset context 0 protocol))
190 (defun epg-context-set-armor (context armor)
191 "Specify if the output shouled be ASCII armored in the CONTEXT context."
192 (aset context 1 armor))
194 (defun epg-context-set-textmode (context textmode)
195 "Specify if canonical text mode should be used in the CONTEXT context."
196 (aset context 2 textmode))
198 (defun epg-context-set-include-certs (context include-certs)
199 "Set how many certificates should be included in an S/MIME signed message."
200 (aset context 3 include-certs))
202 (defun epg-context-set-passphrase-callback (context
204 "Set the function used to query passphrase."
205 (aset context 4 passphrase-callback))
207 (defun epg-context-set-progress-callback (context progress-callback)
208 "Set the function which handles progress update."
209 (aset context 5 progress-callback))
211 (defun epg-context-set-signers (context signers)
212 "Set the list of key-id for singning."
213 (aset context 6 signers))
215 (defun epg-context-set-process (context process)
216 "Set the process object of `epg-gpg-program'.
217 This function is for internal use only."
218 (aset context 7 process))
220 (defun epg-context-set-output-file (context output-file)
221 "Set the output file of `epg-gpg-program'.
222 This function is for internal use only."
223 (aset context 8 output-file))
225 (defun epg-context-set-result (context result)
226 "Set the result of the previous cryptographic operation."
227 (aset context 9 result))
229 (defun epg-make-signature (status key-id user-id)
230 "Return a signature object."
231 (vector status key-id user-id nil nil))
233 (defun epg-signature-status (signature)
234 "Return the status code of SIGNATURE."
237 (defun epg-signature-key-id (signature)
238 "Return the key-id of SIGNATURE."
241 (defun epg-signature-user-id (signature)
242 "Return the user-id of SIGNATURE."
245 (defun epg-signature-validity (signature)
246 "Return the validity of SIGNATURE."
249 (defun epg-signature-fingerprint (signature)
250 "Return the fingerprint of SIGNATURE."
253 (defun epg-signature-set-status (signature status)
254 "Set the status code of SIGNATURE."
255 (aset signature 0 status))
257 (defun epg-signature-set-key-id (signature key-id)
258 "Set the key-id of SIGNATURE."
259 (aset signature 1 key-id))
261 (defun epg-signature-set-user-id (signature user-id)
262 "Set the user-id of SIGNATURE."
263 (aset signature 2 user-id))
265 (defun epg-signature-set-validity (signature validity)
266 "Set the validity of SIGNATURE."
267 (aset signature 3 validity))
269 (defun epg-signature-set-fingerprint (signature fingerprint)
270 "Set the fingerprint of SIGNATURE."
271 (aset signature 4 fingerprint))
273 (defun epg-make-key (owner-trust)
274 "Return a key object."
275 (vector owner-trust nil nil))
277 (defun epg-key-owner-trust (key)
278 "Return the owner trust of KEY."
281 (defun epg-key-sub-key-list (key)
282 "Return the sub key list of KEY."
285 (defun epg-key-user-id-list (key)
286 "Return the user ID list of KEY."
289 (defun epg-key-set-sub-key-list (key sub-key-list)
290 "Set the sub key list of KEY."
291 (aset key 1 sub-key-list))
293 (defun epg-key-set-user-id-list (key user-id-list)
294 "Set the user ID list of KEY."
295 (aset key 2 user-id-list))
297 (defun epg-make-sub-key (validity capability secret algorithm length id
298 creation-time expiration-time)
299 "Return a sub key object."
300 (vector validity capability secret algorithm length id creation-time
301 expiration-time nil))
303 (defun epg-sub-key-validity (sub-key)
304 "Return the validity of SUB-KEY."
307 (defun epg-sub-key-capability (sub-key)
308 "Return the capability of SUB-KEY."
311 (defun epg-sub-key-secret (sub-key)
312 "Return non-nil if SUB-KEY is a secret key."
315 (defun epg-sub-key-algorithm (sub-key)
316 "Return the algorithm of SUB-KEY."
319 (defun epg-sub-key-length (sub-key)
320 "Return the length of SUB-KEY."
323 (defun epg-sub-key-id (sub-key)
324 "Return the ID of SUB-KEY."
327 (defun epg-sub-key-creation-time (sub-key)
328 "Return the creation time of SUB-KEY."
331 (defun epg-sub-key-expiration-time (sub-key)
332 "Return the expiration time of SUB-KEY."
335 (defun epg-sub-key-fingerprint (sub-key)
336 "Return the fingerprint of SUB-KEY."
339 (defun epg-sub-key-set-fingerprint (sub-key fingerprint)
340 "Set the fingerprint of SUB-KEY.
341 This function is for internal use only."
342 (aset sub-key 8 fingerprint))
344 (defun epg-make-user-id (validity name)
345 "Return a user ID object."
346 (vector validity name nil))
348 (defun epg-user-id-validity (user-id)
349 "Return the validity of USER-ID."
352 (defun epg-user-id-name (user-id)
353 "Return the name of USER-ID."
356 (defun epg-user-id-signature-list (user-id)
357 "Return the signature list of USER-ID."
360 (defun epg-user-id-set-signature-list (user-id signature-list)
361 "Set the signature list of USER-ID."
362 (aset user-id 2 signature-list))
364 (defun epg-context-result-for (context name)
365 (cdr (assq name (epg-context-result context))))
367 (defun epg-context-set-result-for (context name value)
368 (let* ((result (epg-context-result context))
369 (entry (assq name result)))
372 (epg-context-set-result context (cons (cons name value) result)))))
374 (defun epg-start (context args)
375 "Start `epg-gpg-program' in a subprocess with given ARGS."
376 (let* ((args (append (list "--no-tty"
380 (if (epg-context-armor context) '("--armor"))
381 (if (epg-context-textmode context) '("--textmode"))
382 (if (epg-context-output-file context)
383 (list "--output" (epg-context-output-file context)))
385 (coding-system-for-write 'binary)
386 process-connection-type
387 (orig-mode (default-file-modes))
388 (buffer (generate-new-buffer " *epg*"))
390 (with-current-buffer buffer
391 (make-local-variable 'epg-read-point)
392 (setq epg-read-point (point-min))
393 (make-local-variable 'epg-pending-status-list)
394 (setq epg-pending-status-list nil)
395 (make-local-variable 'epg-key-id)
396 (setq epg-key-id nil)
397 (make-local-variable 'epg-context)
398 (setq epg-context context))
401 (set-default-file-modes 448)
403 (apply #'start-process "epg" buffer epg-gpg-program args)))
404 (set-default-file-modes orig-mode))
405 (set-process-filter process #'epg-process-filter)
406 (epg-context-set-process context process)))
408 (defun epg-process-filter (process input)
411 (set-buffer (get-buffer-create " *epg-debug*"))
412 (goto-char (point-max))
414 (if (buffer-live-p (process-buffer process))
416 (set-buffer (process-buffer process))
417 (goto-char (point-max))
419 (goto-char epg-read-point)
421 (while (looking-at ".*\n") ;the input line is finished
423 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
424 (let* ((status (match-string 1))
425 (string (match-string 2))
426 (symbol (intern-soft (concat "epg-status-" status))))
427 (if (member status epg-pending-status-list)
428 (setq epg-pending-status-list nil))
431 (funcall symbol process string)))))
433 (setq epg-read-point (point)))))
435 (defun epg-read-output (context)
437 (if (fboundp 'set-buffer-multibyte)
438 (set-buffer-multibyte nil))
439 (if (file-exists-p (epg-context-output-file context))
440 (let ((coding-system-for-read (if (epg-context-textmode context)
443 (insert-file-contents (epg-context-output-file context))
446 (defun epg-wait-for-status (context status-list)
447 (with-current-buffer (process-buffer (epg-context-process context))
448 (setq epg-pending-status-list status-list)
449 (while (and (eq (process-status (epg-context-process context)) 'run)
450 epg-pending-status-list)
451 (accept-process-output (epg-context-process context) 1))))
453 (defun epg-wait-for-completion (context)
454 (if (eq (process-status (epg-context-process context)) 'run)
455 (process-send-eof (epg-context-process context)))
456 (while (eq (process-status (epg-context-process context)) 'run)
457 ;; We can't use accept-process-output instead of sit-for here
458 ;; because it may cause an interrupt during the sentinel execution.
461 (defun epg-reset (context)
462 (if (and (epg-context-process context)
463 (buffer-live-p (process-buffer (epg-context-process context))))
464 (kill-buffer (process-buffer (epg-context-process context))))
465 (epg-context-set-process context nil))
467 (defun epg-delete-output-file (context)
468 (if (and (epg-context-output-file context)
469 (file-exists-p (epg-context-output-file context)))
470 (delete-file (epg-context-output-file context))))
472 (defun epg-status-USERID_HINT (process string)
473 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
474 (let* ((key-id (match-string 1 string))
475 (user-id (match-string 2 string))
476 (entry (assoc key-id epg-user-id-alist)))
478 (setcdr entry user-id)
479 (setq epg-user-id-alist (cons (cons key-id user-id)
480 epg-user-id-alist))))))
482 (defun epg-status-NEED_PASSPHRASE (process string)
483 (if (string-match "\\`\\([^ ]+\\)" string)
484 (setq epg-key-id (match-string 1 string))))
486 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
487 (setq epg-key-id 'SYM))
489 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
490 (setq epg-key-id 'PIN))
492 (defun epg-status-GET_HIDDEN (process string)
494 (funcall (if (consp (epg-context-passphrase-callback epg-context))
495 (car (epg-context-passphrase-callback epg-context))
496 (epg-context-passphrase-callback epg-context))
498 (if (consp (epg-context-passphrase-callback epg-context))
499 (cdr (epg-context-passphrase-callback epg-context)))))
504 (setq string (concat passphrase "\n"))
505 (fillarray passphrase 0)
506 (setq passphrase nil)
507 (process-send-string process string))
509 (fillarray string 0))))))
511 (defun epg-status-GET_BOOL (process string)
512 (let ((entry (assoc string epg-prompt-alist)))
513 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
514 (process-send-string process "y\n")
515 (process-send-string process "n\n"))))
517 (defun epg-status-GET_LINE (process string)
518 (let* ((entry (assoc string epg-prompt-alist))
519 (string (read-string (if entry (cdr entry) (concat string ": ")))))
520 (process-send-string process (concat string "\n"))))
522 (defun epg-status-GOODSIG (process string)
523 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
524 (epg-context-set-result-for
527 (cons (epg-make-signature 'good
528 (match-string 1 string)
529 (match-string 2 string))
530 (epg-context-result-for epg-context 'verify)))))
532 (defun epg-status-EXPSIG (process string)
533 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
534 (epg-context-set-result-for
537 (cons (epg-make-signature 'expired
538 (match-string 1 string)
539 (match-string 2 string))
540 (epg-context-result-for epg-context 'verify)))))
542 (defun epg-status-EXPKEYSIG (process string)
543 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
544 (epg-context-set-result-for
547 (cons (epg-make-signature 'expired-key
548 (match-string 1 string)
549 (match-string 2 string))
550 (epg-context-result-for epg-context 'verify)))))
552 (defun epg-status-REVKEYSIG (process string)
553 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
554 (epg-context-set-result-for
557 (cons (epg-make-signature 'revoked-key
558 (match-string 1 string)
559 (match-string 2 string))
560 (epg-context-result-for epg-context 'verify)))))
562 (defun epg-status-BADSIG (process string)
563 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
564 (epg-context-set-result-for
567 (cons (epg-make-signature 'bad
568 (match-string 1 string)
569 (match-string 2 string))
570 (epg-context-result-for epg-context 'verify)))))
572 (defun epg-status-VALIDSIG (process string)
573 (let ((signature (car (epg-context-result-for epg-context 'verify))))
575 (eq (epg-signature-status signature) 'good)
576 (string-match "\\`\\([^ ]+\\) " string))
577 (epg-signature-set-fingerprint signature (match-string 1 string)))))
579 (defun epg-status-TRUST_UNDEFINED (process string)
580 (let ((signature (car (epg-context-result-for epg-context 'verify))))
582 (eq (epg-signature-status signature) 'good))
583 (epg-signature-set-validity signature 'undefined))))
585 (defun epg-status-TRUST_NEVER (process string)
586 (let ((signature (car (epg-context-result-for epg-context 'verify))))
588 (eq (epg-signature-status signature) 'good))
589 (epg-signature-set-validity signature 'never))))
591 (defun epg-status-TRUST_MARGINAL (process string)
592 (let ((signature (car (epg-context-result-for epg-context 'verify))))
594 (eq (epg-signature-status signature) 'marginal))
595 (epg-signature-set-validity signature 'marginal))))
597 (defun epg-status-TRUST_FULLY (process string)
598 (let ((signature (car (epg-context-result-for epg-context 'verify))))
600 (eq (epg-signature-status signature) 'good))
601 (epg-signature-set-validity signature 'full))))
603 (defun epg-status-TRUST_ULTIMATE (process string)
604 (let ((signature (car (epg-context-result-for epg-context 'verify))))
606 (eq (epg-signature-status signature) 'good))
607 (epg-signature-set-validity signature 'ultimate))))
609 (defun epg-status-PROGRESS (process string)
610 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
612 (funcall (if (consp (epg-context-progress-callback epg-context))
613 (car (epg-context-progress-callback epg-context))
614 (epg-context-progress-callback epg-context))
615 (match-string 1 string)
616 (match-string 2 string)
617 (string-to-number (match-string 3 string))
618 (string-to-number (match-string 4 string))
619 (if (consp (epg-context-progress-callback epg-context))
620 (cdr (epg-context-progress-callback epg-context))))))
622 (defun epg-status-DECRYPTION_FAILED (process string)
623 (epg-context-set-result-for
625 (cons 'decryption-failed
626 (epg-context-result-for epg-context 'error))))
628 (defun epg-status-NODATA (process string)
629 (epg-context-set-result-for
631 (cons (cons 'no-data (string-to-number string))
632 (epg-context-result-for epg-context 'error))))
634 (defun epg-status-UNEXPECTED (process string)
635 (epg-context-set-result-for
637 (cons (cons 'unexpected (string-to-number string))
638 (epg-context-result-for epg-context 'error))))
640 (defun epg-status-KEYEXPIRED (process string)
641 (epg-context-set-result-for
643 (cons (cons 'key-expired string)
644 (epg-context-result-for epg-context 'error))))
646 (defun epg-status-KEYREVOKED (process string)
647 (epg-context-set-result-for
650 (epg-context-result-for epg-context 'error))))
652 (defun epg-status-BADARMOR (process string)
653 (epg-context-set-result-for
656 (epg-context-result-for epg-context 'error))))
658 (defun epg-status-INV_RECP (process string)
659 (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
660 (epg-context-set-result-for
662 (cons (list 'invalid-recipient
663 (string-to-number (match-string 1 string))
664 (match-string 2 string))
665 (epg-context-result-for epg-context 'error)))))
667 (defun epg-status-NO_RECP (process string)
668 (epg-context-set-result-for
671 (epg-context-result-for epg-context 'error))))
673 (defun epg-passphrase-callback-function (key-id handback)
676 "Passphrase for symmetric encryption: "
678 "Passphrase for PIN: "
679 (let ((entry (assoc key-id epg-user-id-alist)))
681 (format "Passphrase for %s %s: " key-id (cdr entry))
682 (format "Passphrase for %s: " key-id)))))))
684 (defun epg-progress-callback-function (what char current total handback)
685 (message "%s: %d%%/%d%%" what current total))
687 (defun epg-configuration ()
688 "Return a list of internal configuration parameters of `epg-gpg-program'."
691 (apply #'call-process epg-gpg-program nil (list t nil) nil
692 '("--with-colons" "--list-config"))
693 (goto-char (point-min))
694 (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
695 (setq type (intern (match-string 1))
696 config (cons (cons type
698 '(pubkey cipher digest compress))
699 (mapcar #'string-to-number
700 (delete "" (split-string
707 (defun epg-list-keys-1 (name mode)
708 (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
709 "--fixed-list-mode" "--with-fingerprint"
711 (if mode "--list-secret-keys" "--list-keys"))
712 (if name (list name))))
713 keys string field index)
715 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
716 (goto-char (point-min))
717 (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
718 (setq keys (cons (make-vector 15 nil) keys)
719 string (match-string 0)
723 (string-match "\\([^:]+\\)?:" string index))
724 (setq index (match-end 0))
725 (aset (car keys) field (match-string 1 string))
726 (setq field (1+ field))))
729 (defun epg-make-sub-key-1 (line)
731 (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist))
733 (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
735 (member (aref line 0) '("sec" "ssb"))
736 (string-to-number (aref line 3))
737 (string-to-number (aref line 2))
742 (defun epg-list-keys (&optional name mode)
743 (let ((lines (epg-list-keys-1 name mode))
747 ((member (aref (car lines) 0) '("pub" "sec"))
749 (epg-key-set-sub-key-list
751 (nreverse (epg-key-sub-key-list (car keys))))
752 (epg-key-set-user-id-list
754 (nreverse (epg-key-user-id-list (car keys)))))
755 (setq keys (cons (epg-make-key
756 (cdr (assq (string-to-char (aref (car lines) 8))
757 epg-key-validity-alist)))
759 (epg-key-set-sub-key-list
761 (cons (epg-make-sub-key-1 (car lines))
762 (epg-key-sub-key-list (car keys)))))
763 ((member (aref (car lines) 0) '("sub" "ssb"))
764 (epg-key-set-sub-key-list
766 (cons (epg-make-sub-key-1 (car lines))
767 (epg-key-sub-key-list (car keys)))))
768 ((equal (aref (car lines) 0) "uid")
769 (epg-key-set-user-id-list
771 (cons (epg-make-user-id
772 (cdr (assq (string-to-char (aref (car lines) 1))
773 epg-key-validity-alist))
774 (aref (car lines) 9))
775 (epg-key-user-id-list (car keys)))))
776 ((equal (aref (car lines) 0) "fpr")
777 (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
778 (aref (car lines) 9))))
779 (setq lines (cdr lines)))
782 (if (fboundp 'make-temp-file)
783 (defalias 'epg-make-temp-file 'make-temp-file)
784 ;; stolen from poe.el.
785 (defun epg-make-temp-file (prefix)
786 "Create a temporary file.
787 The returned file name (created by appending some random characters at the end
788 of PREFIX, and expanding against `temporary-file-directory' if necessary),
789 is guaranteed to point to a newly created empty file.
790 You can then use `write-region' to write new data into the file."
791 (let (tempdir tempfile)
794 ;; First, create a temporary directory.
795 (while (condition-case ()
797 (setq tempdir (make-temp-name
799 (file-name-directory prefix)
801 ;; return nil or signal an error.
802 (make-directory tempdir))
804 (file-already-exists t)))
805 (set-file-modes tempdir 448)
806 ;; Second, create a temporary file in the tempdir.
807 ;; There *is* a race condition between `make-temp-name'
808 ;; and `write-region', but we don't care it since we are
809 ;; in a private directory now.
810 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
811 (write-region "" nil tempfile nil 'silent)
812 (set-file-modes tempfile 384)
813 ;; Finally, make a hard-link from the tempfile.
814 (while (condition-case ()
816 (setq file (make-temp-name prefix))
817 ;; return nil or signal an error.
818 (add-name-to-file tempfile file))
820 (file-already-exists t)))
822 ;; Cleanup the tempfile.
824 (file-exists-p tempfile)
825 (delete-file tempfile))
826 ;; Cleanup the tempdir.
828 (file-directory-p tempdir)
829 (delete-directory tempdir))))))
832 (defun epg-start-decrypt (context cipher)
833 "Initiate a decrypt operation on CIPHER.
834 CIPHER is a data object.
836 If you use this function, you will need to wait for the completion of
837 `epg-gpg-program' by using `epg-wait-for-completion' and call
838 `epg-reset' to clear a temporaly output file.
839 If you are unsure, use synchronous version of this function
840 `epg-decrypt-file' or `epg-decrypt-string' instead."
841 (unless (epg-data-file cipher)
842 (error "Not a file"))
843 (epg-context-set-result context nil)
844 (epg-start context (list "--decrypt" (epg-data-file cipher)))
845 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
848 (defun epg-decrypt-file (context cipher plain)
849 "Decrypt a file CIPHER and store the result to a file PLAIN.
850 If PLAIN is nil, it returns the result as a string."
854 (epg-context-set-output-file context plain)
855 (epg-context-set-output-file context
856 (epg-make-temp-file "epg-output")))
857 (epg-start-decrypt context (epg-make-data-from-file cipher))
858 (epg-wait-for-completion context)
859 (if (epg-context-result-for context 'error)
860 (error "Decrypt failed: %S"
861 (epg-context-result-for context 'error)))
863 (epg-read-output context)))
865 (epg-delete-output-file context))
866 (epg-reset context)))
869 (defun epg-decrypt-string (context cipher)
870 "Decrypt a string CIPHER and return the plain text."
871 (let ((input-file (epg-make-temp-file "epg-input"))
872 (coding-system-for-write 'binary))
875 (write-region cipher nil input-file)
876 (epg-context-set-output-file context
877 (epg-make-temp-file "epg-output"))
878 (epg-start-decrypt context (epg-make-data-from-file input-file))
879 (epg-wait-for-completion context)
880 (if (epg-context-result-for context 'error)
881 (error "Decrypt failed: %S"
882 (epg-context-result-for context 'error)))
883 (epg-read-output context))
884 (epg-delete-output-file context)
885 (if (file-exists-p input-file)
886 (delete-file input-file))
887 (epg-reset context))))
890 (defun epg-start-verify (context signature &optional signed-text)
891 "Initiate a verify operation on SIGNATURE.
892 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
894 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
895 For a normal or a clear text signature, SIGNED-TEXT should be nil.
897 If you use this function, you will need to wait for the completion of
898 `epg-gpg-program' by using `epg-wait-for-completion' and call
899 `epg-reset' to clear a temporaly output file.
900 If you are unsure, use synchronous version of this function
901 `epg-verify-file' or `epg-verify-string' instead."
902 (epg-context-set-result context nil)
904 ;; Detached signature.
905 (if (epg-data-file signed-text)
906 (epg-start context (list "--verify" (epg-data-file signature)
907 (epg-data-file signed-text)))
908 (epg-start context (list "--verify" (epg-data-file signature) "-"))
909 (if (eq (process-status (epg-context-process context)) 'run)
910 (process-send-string (epg-context-process context)
911 (epg-data-string signed-text))))
912 ;; Normal (or cleartext) signature.
913 (if (epg-data-file signature)
914 (epg-start context (list "--verify" (epg-data-file signature)))
915 (epg-start context (list "--verify"))
916 (if (eq (process-status (epg-context-process context)) 'run)
917 (process-send-string (epg-context-process context)
918 (epg-data-string signature))))))
921 (defun epg-verify-file (context signature &optional signed-text plain)
922 "Verify a file SIGNATURE.
923 SIGNED-TEXT and PLAIN are also a file if they are specified.
925 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
926 For a normal or a clear text signature, SIGNED-TEXT should be nil."
930 (epg-context-set-output-file context plain)
931 (epg-context-set-output-file context
932 (epg-make-temp-file "epg-output")))
934 (epg-start-verify context
935 (epg-make-data-from-file signature)
936 (epg-make-data-from-file signed-text))
937 (epg-start-verify context
938 (epg-make-data-from-file signature)))
939 (epg-wait-for-completion context)
941 (epg-read-output context)))
943 (epg-delete-output-file context))
944 (epg-reset context)))
947 (defun epg-verify-string (context signature &optional signed-text)
948 "Verify a string SIGNATURE.
949 SIGNED-TEXT is a string if it is specified.
951 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
952 For a normal or a clear text signature, SIGNED-TEXT should be nil."
953 (let ((coding-system-for-write 'binary)
957 (epg-context-set-output-file context
958 (epg-make-temp-file "epg-output"))
961 (setq input-file (epg-make-temp-file "epg-signature"))
962 (write-region signature nil input-file)
963 (epg-start-verify context
964 (epg-make-data-from-file input-file)
965 (epg-make-data-from-string signed-text)))
966 (epg-start-verify context (epg-make-data-from-string signature)))
967 (epg-wait-for-completion context)
968 (epg-read-output context))
969 (epg-delete-output-file context)
971 (file-exists-p input-file))
972 (delete-file input-file))
973 (epg-reset context))))
976 (defun epg-start-sign (context plain &optional mode)
977 "Initiate a sign operation on PLAIN.
978 PLAIN is a data object.
980 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
981 If MODE is t or 'detached, it makes a detached signature.
982 Otherwise, it makes a normal signature.
984 If you use this function, you will need to wait for the completion of
985 `epg-gpg-program' by using `epg-wait-for-completion' and call
986 `epg-reset' to clear a temporaly output file.
987 If you are unsure, use synchronous version of this function
988 `epg-sign-file' or `epg-sign-string' instead."
989 (epg-context-set-result context nil)
991 (append (list (if (eq mode 'clearsign)
993 (if (or (eq mode t) (eq mode 'detached))
997 (mapcar (lambda (signer)
999 (epg-context-signers context)))
1000 (if (epg-data-file plain)
1001 (list (epg-data-file plain)))))
1002 (epg-wait-for-status context '("BEGIN_SIGNING"))
1003 (if (and (epg-data-string plain)
1004 (eq (process-status (epg-context-process context)) 'run))
1005 (process-send-string (epg-context-process context)
1006 (epg-data-string plain))))
1009 (defun epg-sign-file (context plain signature &optional mode)
1010 "Sign a file PLAIN and store the result to a file SIGNATURE.
1011 If SIGNATURE is nil, it returns the result as a string.
1012 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1013 If MODE is t or 'detached, it makes a detached signature.
1014 Otherwise, it makes a normal signature."
1018 (epg-context-set-output-file context signature)
1019 (epg-context-set-output-file context
1020 (epg-make-temp-file "epg-output")))
1021 (epg-start-sign context (epg-make-data-from-file plain) mode)
1022 (epg-wait-for-completion context)
1023 (if (epg-context-result-for context 'error)
1024 (error "Sign failed: %S"
1025 (epg-context-result-for context 'error)))
1027 (epg-read-output context)))
1029 (epg-delete-output-file context))
1030 (epg-reset context)))
1033 (defun epg-sign-string (context plain &optional mode)
1034 "Sign a string PLAIN and return the output as string.
1035 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1036 If MODE is t or 'detached, it makes a detached signature.
1037 Otherwise, it makes a normal signature."
1040 (epg-context-set-output-file context
1041 (epg-make-temp-file "epg-output"))
1042 (epg-start-sign context (epg-make-data-from-string plain) mode)
1043 (epg-wait-for-completion context)
1044 (if (epg-context-result-for context 'error)
1045 (error "Sign failed: %S"
1046 (epg-context-result-for context 'error)))
1047 (epg-read-output context))
1048 (epg-delete-output-file context)
1049 (epg-reset context)))
1052 (defun epg-start-encrypt (context plain recipients
1053 &optional sign always-trust)
1054 "Initiate an encrypt operation on PLAIN.
1055 PLAIN is a data object.
1056 If RECIPIENTS is nil, it performs symmetric encryption.
1058 If you use this function, you will need to wait for the completion of
1059 `epg-gpg-program' by using `epg-wait-for-completion' and call
1060 `epg-reset' to clear a temporaly output file.
1061 If you are unsure, use synchronous version of this function
1062 `epg-encrypt-file' or `epg-encrypt-string' instead."
1063 (epg-context-set-result context nil)
1065 (append (if always-trust '("--always-trust"))
1066 (if recipients '("--encrypt") '("--symmetric"))
1070 (mapcar (lambda (signer)
1072 (epg-context-signers context)))))
1074 (mapcar (lambda (recipient)
1075 (list "-r" recipient))
1077 (if (epg-data-file plain)
1078 (list (epg-data-file plain)))))
1080 (epg-wait-for-status context '("BEGIN_SIGNING"))
1081 (if (null recipients)
1082 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
1083 (if (and (epg-data-string plain)
1084 (eq (process-status (epg-context-process context)) 'run))
1085 (process-send-string (epg-context-process context)
1086 (epg-data-string plain))))
1089 (defun epg-encrypt-file (context plain recipients
1090 cipher &optional sign always-trust)
1091 "Encrypt a file PLAIN and store the result to a file CIPHER.
1092 If CIPHER is nil, it returns the result as a string.
1093 If RECIPIENTS is nil, it performs symmetric encryption."
1097 (epg-context-set-output-file context cipher)
1098 (epg-context-set-output-file context
1099 (epg-make-temp-file "epg-output")))
1100 (epg-start-encrypt context (epg-make-data-from-file plain)
1101 recipients sign always-trust)
1102 (epg-wait-for-completion context)
1103 (if (epg-context-result-for context 'error)
1104 (error "Encrypt failed: %S"
1105 (epg-context-result-for context 'error)))
1107 (epg-read-output context)))
1109 (epg-delete-output-file context))
1110 (epg-reset context)))
1113 (defun epg-encrypt-string (context plain recipients
1114 &optional sign always-trust)
1115 "Encrypt a string PLAIN.
1116 If RECIPIENTS is nil, it performs symmetric encryption."
1119 (epg-context-set-output-file context
1120 (epg-make-temp-file "epg-output"))
1121 (epg-start-encrypt context (epg-make-data-from-string plain)
1122 recipients sign always-trust)
1123 (epg-wait-for-completion context)
1124 (if (epg-context-result-for context 'error)
1125 (error "Encrypt failed: %S"
1126 (epg-context-result-for context 'error)))
1127 (epg-read-output context))
1128 (epg-delete-output-file context)
1129 (epg-reset context)))
1132 (defun epg-start-export-keys (context pattern)
1133 "Initiate an export keys operation.
1135 If you use this function, you will need to wait for the completion of
1136 `epg-gpg-program' by using `epg-wait-for-completion' and call
1137 `epg-reset' to clear a temporaly output file.
1138 If you are unsure, use synchronous version of this function
1139 `epg-export-keys' instead."
1140 (epg-context-set-result context nil)
1141 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1142 (epg-start context (list "--export" pattern)))
1145 (defun epg-export-keys (context pattern)
1146 "Extract public keys matched with PATTERN and return them."
1149 (epg-start-export-keys context pattern)
1150 (epg-wait-for-completion context)
1151 (if (epg-context-result-for context 'error)
1152 (error "Export keys failed"))
1153 (epg-read-output context))
1154 (epg-reset context)))
1157 (defun epg-start-import-keys (context keys)
1158 "Initiate an import keys operation.
1159 KEYS is a data object.
1161 If you use this function, you will need to wait for the completion of
1162 `epg-gpg-program' by using `epg-wait-for-completion' and call
1163 `epg-reset' to clear a temporaly output file.
1164 If you are unsure, use synchronous version of this function
1165 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1166 (epg-context-set-result context nil)
1167 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1168 (epg-start context (append (list "--import") (epg-data-file keys)))
1169 (if (and (epg-data-string keys)
1170 (eq (process-status (epg-context-process context)) 'run))
1171 (process-send-string (epg-context-process context)
1172 (epg-data-string keys))))
1174 (defun epg-import-keys-1 (context keys)
1177 (epg-start-import-keys context keys)
1178 (epg-wait-for-completion context)
1179 (if (epg-context-result-for context 'error)
1180 (error "Import keys failed"))
1181 (epg-read-output context))
1182 (epg-reset context)))
1185 (defun epg-import-keys-from-file (context keys)
1186 "Add keys from a file KEYS."
1187 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1190 (defun epg-import-keys-from-string (context keys)
1191 "Add keys from a string KEYS."
1192 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1196 ;;; epg.el ends here