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 (defconst epg-version-number "0.0.0")
38 (defvar epg-user-id nil
39 "GnuPG ID of your default identity.")
41 (defvar epg-user-id-alist nil
42 "An alist mapping from key ID to user ID.")
44 (defvar epg-read-point nil)
45 (defvar epg-pending-status-list nil)
46 (defvar epg-key-id nil)
47 (defvar epg-context nil)
48 (defvar epg-debug nil)
50 ;; from gnupg/include/cipher.h
51 (defconst epg-cipher-algorithm-alist
63 ;; from gnupg/include/cipher.h
64 (defconst epg-pubkey-algorithm-alist
72 ;; from gnupg/include/cipher.h
73 (defconst epg-digest-algorithm-alist
81 ;; from gnupg/include/cipher.h
82 (defconst epg-compress-algorithm-alist
88 (defconst epg-invalid-recipients-alist
89 '((0 . "No specific reason given")
91 (2 . "Ambigious specification")
92 (3 . "Wrong key usage")
97 (8 . "Policy mismatch")
98 (9 . "Not a secret key")
99 (10 . "Key not trusted")))
101 (defconst epg-delete-problem-alist
102 '((1 . "No such key")
103 (2 . "Must delete secret key first")
104 (3 . "Ambigious specification")))
106 (defvar epg-key-validity-alist
119 (defvar epg-key-capablity-alist
123 (?a . authentication)))
125 (defvar epg-prompt-alist nil)
127 (defun epg-make-data-from-file (file)
128 "Make a data object from FILE."
131 (defun epg-make-data-from-string (string)
132 "Make a data object from STRING."
135 (defun epg-data-file (data)
136 "Return the file of DATA."
139 (defun epg-data-string (data)
140 "Return the string of DATA."
143 (defun epg-make-context (&optional protocol armor textmode include-certs
144 cipher-algorithm digest-algorithm
146 "Return a context object."
147 (vector protocol armor textmode include-certs
148 cipher-algorithm digest-algorithm compress-algorithm
149 #'epg-passphrase-callback-function
150 #'epg-progress-callback-function
153 (defun epg-context-protocol (context)
154 "Return the protocol used within CONTEXT."
157 (defun epg-context-armor (context)
158 "Return t if the output shouled be ASCII armored in CONTEXT."
161 (defun epg-context-textmode (context)
162 "Return t if canonical text mode should be used in CONTEXT."
165 (defun epg-context-include-certs (context)
166 "Return how many certificates should be included in an S/MIME signed
170 (defun epg-context-cipher-algorithm (context)
171 "Return the cipher algorithm in CONTEXT."
174 (defun epg-context-digest-algorithm (context)
175 "Return the digest algorithm in CONTEXT."
178 (defun epg-context-compress-algorithm (context)
179 "Return the compress algorithm in CONTEXT."
182 (defun epg-context-passphrase-callback (context)
183 "Return the function used to query passphrase."
186 (defun epg-context-progress-callback (context)
187 "Return the function which handles progress update."
190 (defun epg-context-signers (context)
191 "Return the list of key-id for singning."
194 (defun epg-context-process (context)
195 "Return the process object of `epg-gpg-program'.
196 This function is for internal use only."
199 (defun epg-context-output-file (context)
200 "Return the output file of `epg-gpg-program'.
201 This function is for internal use only."
204 (defun epg-context-result (context)
205 "Return the result of the previous cryptographic operation."
208 (defun epg-context-set-protocol (context protocol)
209 "Set the protocol used within CONTEXT."
210 (aset context 0 protocol))
212 (defun epg-context-set-armor (context armor)
213 "Specify if the output shouled be ASCII armored in CONTEXT."
214 (aset context 1 armor))
216 (defun epg-context-set-textmode (context textmode)
217 "Specify if canonical text mode should be used in CONTEXT."
218 (aset context 2 textmode))
220 (defun epg-context-set-include-certs (context include-certs)
221 "Set how many certificates should be included in an S/MIME signed message."
222 (aset context 3 include-certs))
224 (defun epg-context-set-cipher-algorithm (context cipher-algorithm)
225 "Set the cipher algorithm in CONTEXT."
226 (aset context 4 cipher-algorithm))
228 (defun epg-context-set-digest-algorithm (context digest-algorithm)
229 "Set the digest algorithm in CONTEXT."
230 (aset context 5 digest-algorithm))
232 (defun epg-context-set-compress-algorithm (context compress-algorithm)
233 "Set the compress algorithm in CONTEXT."
234 (aset context 6 compress-algorithm))
236 (defun epg-context-set-passphrase-callback (context
238 "Set the function used to query passphrase."
239 (aset context 7 passphrase-callback))
241 (defun epg-context-set-progress-callback (context progress-callback)
242 "Set the function which handles progress update."
243 (aset context 8 progress-callback))
245 (defun epg-context-set-signers (context signers)
246 "Set the list of key-id for singning."
247 (aset context 9 signers))
249 (defun epg-context-set-process (context process)
250 "Set the process object of `epg-gpg-program'.
251 This function is for internal use only."
252 (aset context 10 process))
254 (defun epg-context-set-output-file (context output-file)
255 "Set the output file of `epg-gpg-program'.
256 This function is for internal use only."
257 (aset context 11 output-file))
259 (defun epg-context-set-result (context result)
260 "Set the result of the previous cryptographic operation."
261 (aset context 12 result))
263 (defun epg-make-signature (status key-id user-id)
264 "Return a signature object."
265 (vector status key-id user-id nil nil))
267 (defun epg-signature-status (signature)
268 "Return the status code of SIGNATURE."
271 (defun epg-signature-key-id (signature)
272 "Return the key-id of SIGNATURE."
275 (defun epg-signature-user-id (signature)
276 "Return the user-id of SIGNATURE."
279 (defun epg-signature-validity (signature)
280 "Return the validity of SIGNATURE."
283 (defun epg-signature-fingerprint (signature)
284 "Return the fingerprint of SIGNATURE."
287 (defun epg-signature-set-status (signature status)
288 "Set the status code of SIGNATURE."
289 (aset signature 0 status))
291 (defun epg-signature-set-key-id (signature key-id)
292 "Set the key-id of SIGNATURE."
293 (aset signature 1 key-id))
295 (defun epg-signature-set-user-id (signature user-id)
296 "Set the user-id of SIGNATURE."
297 (aset signature 2 user-id))
299 (defun epg-signature-set-validity (signature validity)
300 "Set the validity of SIGNATURE."
301 (aset signature 3 validity))
303 (defun epg-signature-set-fingerprint (signature fingerprint)
304 "Set the fingerprint of SIGNATURE."
305 (aset signature 4 fingerprint))
307 (defun epg-make-key (owner-trust)
308 "Return a key object."
309 (vector owner-trust nil nil))
311 (defun epg-key-owner-trust (key)
312 "Return the owner trust of KEY."
315 (defun epg-key-sub-key-list (key)
316 "Return the sub key list of KEY."
319 (defun epg-key-user-id-list (key)
320 "Return the user ID list of KEY."
323 (defun epg-key-set-sub-key-list (key sub-key-list)
324 "Set the sub key list of KEY."
325 (aset key 1 sub-key-list))
327 (defun epg-key-set-user-id-list (key user-id-list)
328 "Set the user ID list of KEY."
329 (aset key 2 user-id-list))
331 (defun epg-make-sub-key (validity capability secret algorithm length id
332 creation-time expiration-time)
333 "Return a sub key object."
334 (vector validity capability secret algorithm length id creation-time
335 expiration-time nil))
337 (defun epg-sub-key-validity (sub-key)
338 "Return the validity of SUB-KEY."
341 (defun epg-sub-key-capability (sub-key)
342 "Return the capability of SUB-KEY."
345 (defun epg-sub-key-secret (sub-key)
346 "Return non-nil if SUB-KEY is a secret key."
349 (defun epg-sub-key-algorithm (sub-key)
350 "Return the algorithm of SUB-KEY."
353 (defun epg-sub-key-length (sub-key)
354 "Return the length of SUB-KEY."
357 (defun epg-sub-key-id (sub-key)
358 "Return the ID of SUB-KEY."
361 (defun epg-sub-key-creation-time (sub-key)
362 "Return the creation time of SUB-KEY."
365 (defun epg-sub-key-expiration-time (sub-key)
366 "Return the expiration time of SUB-KEY."
369 (defun epg-sub-key-fingerprint (sub-key)
370 "Return the fingerprint of SUB-KEY."
373 (defun epg-sub-key-set-fingerprint (sub-key fingerprint)
374 "Set the fingerprint of SUB-KEY.
375 This function is for internal use only."
376 (aset sub-key 8 fingerprint))
378 (defun epg-make-user-id (validity name)
379 "Return a user ID object."
380 (vector validity name nil))
382 (defun epg-user-id-validity (user-id)
383 "Return the validity of USER-ID."
386 (defun epg-user-id-name (user-id)
387 "Return the name of USER-ID."
390 (defun epg-user-id-signature-list (user-id)
391 "Return the signature list of USER-ID."
394 (defun epg-user-id-set-signature-list (user-id signature-list)
395 "Set the signature list of USER-ID."
396 (aset user-id 2 signature-list))
398 (defun epg-context-result-for (context name)
399 (cdr (assq name (epg-context-result context))))
401 (defun epg-context-set-result-for (context name value)
402 (let* ((result (epg-context-result context))
403 (entry (assq name result)))
406 (epg-context-set-result context (cons (cons name value) result)))))
408 (defun epg-start (context args)
409 "Start `epg-gpg-program' in a subprocess with given ARGS."
410 (let* ((args (append (list "--no-tty"
413 (if (epg-context-armor context) '("--armor"))
414 (if (epg-context-textmode context) '("--textmode"))
415 (if (epg-context-output-file context)
416 (list "--output" (epg-context-output-file context)))
418 (coding-system-for-write 'binary)
419 process-connection-type
420 (orig-mode (default-file-modes))
421 (buffer (generate-new-buffer " *epg*"))
425 (set-buffer (get-buffer-create " *epg-debug*"))
426 (goto-char (point-max))
427 (insert (format "%s %s\n" epg-gpg-program
428 (mapconcat #'identity args " ")))))
429 (with-current-buffer buffer
430 (make-local-variable 'epg-read-point)
431 (setq epg-read-point (point-min))
432 (make-local-variable 'epg-pending-status-list)
433 (setq epg-pending-status-list nil)
434 (make-local-variable 'epg-key-id)
435 (setq epg-key-id nil)
436 (make-local-variable 'epg-context)
437 (setq epg-context context))
440 (set-default-file-modes 448)
442 (apply #'start-process "epg" buffer epg-gpg-program args)))
443 (set-default-file-modes orig-mode))
444 (set-process-filter process #'epg-process-filter)
445 (epg-context-set-process context process)))
447 (defun epg-process-filter (process input)
450 (set-buffer (get-buffer-create " *epg-debug*"))
451 (goto-char (point-max))
453 (if (buffer-live-p (process-buffer process))
455 (set-buffer (process-buffer process))
456 (goto-char (point-max))
458 (goto-char epg-read-point)
460 (while (looking-at ".*\n") ;the input line finished
462 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
463 (let* ((status (match-string 1))
464 (string (match-string 2))
465 (symbol (intern-soft (concat "epg-status-" status))))
466 (if (member status epg-pending-status-list)
467 (setq epg-pending-status-list nil))
470 (funcall symbol process string))
472 (run-hook-with-args-until-success
473 (intern (concat "epg-after-status-" status "-function"))
477 (setq epg-read-point (point)))))
479 (defun epg-read-output (context)
481 (if (fboundp 'set-buffer-multibyte)
482 (set-buffer-multibyte nil))
483 (if (file-exists-p (epg-context-output-file context))
484 (let ((coding-system-for-read (if (epg-context-textmode context)
487 (insert-file-contents (epg-context-output-file context))
490 (defun epg-wait-for-status (context status-list)
491 (with-current-buffer (process-buffer (epg-context-process context))
492 (setq epg-pending-status-list status-list)
493 (while (and (eq (process-status (epg-context-process context)) 'run)
494 epg-pending-status-list)
495 (accept-process-output (epg-context-process context) 1))))
497 (defun epg-wait-for-completion (context &optional no-eof)
498 (if (and (not no-eof)
499 (eq (process-status (epg-context-process context)) 'run))
500 (process-send-eof (epg-context-process context)))
501 (while (eq (process-status (epg-context-process context)) 'run)
502 ;; We can't use accept-process-output instead of sit-for here
503 ;; because it may cause an interrupt during the sentinel execution.
506 (defun epg-reset (context)
507 (if (and (epg-context-process context)
508 (buffer-live-p (process-buffer (epg-context-process context))))
509 (kill-buffer (process-buffer (epg-context-process context))))
510 (epg-context-set-process context nil))
512 (defun epg-delete-output-file (context)
513 (if (and (epg-context-output-file context)
514 (file-exists-p (epg-context-output-file context)))
515 (delete-file (epg-context-output-file context))))
517 (defun epg-status-USERID_HINT (process string)
518 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
519 (let* ((key-id (match-string 1 string))
520 (user-id (match-string 2 string))
521 (entry (assoc key-id epg-user-id-alist)))
523 (setcdr entry user-id)
524 (setq epg-user-id-alist (cons (cons key-id user-id)
525 epg-user-id-alist))))))
527 (defun epg-status-NEED_PASSPHRASE (process string)
528 (if (string-match "\\`\\([^ ]+\\)" string)
529 (setq epg-key-id (match-string 1 string))))
531 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
532 (setq epg-key-id 'SYM))
534 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
535 (setq epg-key-id 'PIN))
537 (defun epg-status-GET_HIDDEN (process string)
539 (funcall (if (consp (epg-context-passphrase-callback epg-context))
540 (car (epg-context-passphrase-callback epg-context))
541 (epg-context-passphrase-callback epg-context))
542 (if (consp (epg-context-passphrase-callback epg-context))
543 (cdr (epg-context-passphrase-callback epg-context)))))
548 (setq string (concat passphrase "\n"))
549 (fillarray passphrase 0)
550 (setq passphrase nil)
551 (process-send-string process string))
553 (fillarray string 0))))))
555 (defun epg-status-GET_BOOL (process string)
556 (let ((entry (assoc string epg-prompt-alist)))
557 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
558 (process-send-string process "y\n")
559 (process-send-string process "n\n"))))
561 (defun epg-status-GET_LINE (process string)
562 (let* ((entry (assoc string epg-prompt-alist))
563 (string (read-string (if entry (cdr entry) (concat string ": ")))))
564 (process-send-string process (concat string "\n"))))
566 (defun epg-status-GOODSIG (process string)
567 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
568 (epg-context-set-result-for
571 (cons (epg-make-signature 'good
572 (match-string 1 string)
573 (match-string 2 string))
574 (epg-context-result-for epg-context 'verify)))))
576 (defun epg-status-EXPSIG (process string)
577 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
578 (epg-context-set-result-for
581 (cons (epg-make-signature 'expired
582 (match-string 1 string)
583 (match-string 2 string))
584 (epg-context-result-for epg-context 'verify)))))
586 (defun epg-status-EXPKEYSIG (process string)
587 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
588 (epg-context-set-result-for
591 (cons (epg-make-signature 'expired-key
592 (match-string 1 string)
593 (match-string 2 string))
594 (epg-context-result-for epg-context 'verify)))))
596 (defun epg-status-REVKEYSIG (process string)
597 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
598 (epg-context-set-result-for
601 (cons (epg-make-signature 'revoked-key
602 (match-string 1 string)
603 (match-string 2 string))
604 (epg-context-result-for epg-context 'verify)))))
606 (defun epg-status-BADSIG (process string)
607 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
608 (epg-context-set-result-for
611 (cons (epg-make-signature 'bad
612 (match-string 1 string)
613 (match-string 2 string))
614 (epg-context-result-for epg-context 'verify)))))
616 (defun epg-status-VALIDSIG (process string)
617 (let ((signature (car (epg-context-result-for epg-context 'verify))))
619 (eq (epg-signature-status signature) 'good)
620 (string-match "\\`\\([^ ]+\\) " string))
621 (epg-signature-set-fingerprint signature (match-string 1 string)))))
623 (defun epg-status-TRUST_UNDEFINED (process string)
624 (let ((signature (car (epg-context-result-for epg-context 'verify))))
626 (eq (epg-signature-status signature) 'good))
627 (epg-signature-set-validity signature 'undefined))))
629 (defun epg-status-TRUST_NEVER (process string)
630 (let ((signature (car (epg-context-result-for epg-context 'verify))))
632 (eq (epg-signature-status signature) 'good))
633 (epg-signature-set-validity signature 'never))))
635 (defun epg-status-TRUST_MARGINAL (process string)
636 (let ((signature (car (epg-context-result-for epg-context 'verify))))
638 (eq (epg-signature-status signature) 'marginal))
639 (epg-signature-set-validity signature 'marginal))))
641 (defun epg-status-TRUST_FULLY (process string)
642 (let ((signature (car (epg-context-result-for epg-context 'verify))))
644 (eq (epg-signature-status signature) 'good))
645 (epg-signature-set-validity signature 'full))))
647 (defun epg-status-TRUST_ULTIMATE (process string)
648 (let ((signature (car (epg-context-result-for epg-context 'verify))))
650 (eq (epg-signature-status signature) 'good))
651 (epg-signature-set-validity signature 'ultimate))))
653 (defun epg-status-PROGRESS (process string)
654 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
656 (funcall (if (consp (epg-context-progress-callback epg-context))
657 (car (epg-context-progress-callback epg-context))
658 (epg-context-progress-callback epg-context))
659 (match-string 1 string)
660 (match-string 2 string)
661 (string-to-number (match-string 3 string))
662 (string-to-number (match-string 4 string))
663 (if (consp (epg-context-progress-callback epg-context))
664 (cdr (epg-context-progress-callback epg-context))))))
666 (defun epg-status-DECRYPTION_FAILED (process string)
667 (epg-context-set-result-for
669 (cons 'decryption-failed
670 (epg-context-result-for epg-context 'error))))
672 (defun epg-status-NODATA (process string)
673 (epg-context-set-result-for
675 (cons (cons 'no-data (string-to-number string))
676 (epg-context-result-for epg-context 'error))))
678 (defun epg-status-UNEXPECTED (process string)
679 (epg-context-set-result-for
681 (cons (cons 'unexpected (string-to-number string))
682 (epg-context-result-for epg-context 'error))))
684 (defun epg-status-KEYEXPIRED (process string)
685 (epg-context-set-result-for
687 (cons (cons 'key-expired string)
688 (epg-context-result-for epg-context 'error))))
690 (defun epg-status-KEYREVOKED (process string)
691 (epg-context-set-result-for
694 (epg-context-result-for epg-context 'error))))
696 (defun epg-status-BADARMOR (process string)
697 (epg-context-set-result-for
700 (epg-context-result-for epg-context 'error))))
702 (defun epg-status-INV_RECP (process string)
703 (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
704 (epg-context-set-result-for
706 (cons (list 'invalid-recipient
707 (string-to-number (match-string 1 string))
708 (match-string 2 string))
709 (epg-context-result-for epg-context 'error)))))
711 (defun epg-status-NO_RECP (process string)
712 (epg-context-set-result-for
715 (epg-context-result-for epg-context 'error))))
717 (defun epg-status-DELETE_PROBLEM (process string)
718 (if (string-match "\\`\\([0-9]+\\)" string)
719 (epg-context-set-result-for
721 (cons (cons 'delete-problem (string-to-number (match-string 1 string)))
722 (epg-context-result-for epg-context 'error)))))
724 (defun epg-passphrase-callback-function (handback)
726 (if (eq epg-key-id 'SYM)
727 "Passphrase for symmetric encryption: "
728 (if (eq epg-key-id 'PIN)
729 "Passphrase for PIN: "
730 (let ((entry (assoc epg-key-id epg-user-id-alist)))
732 (format "Passphrase for %s %s: " epg-key-id (cdr entry))
733 (format "Passphrase for %s: " epg-key-id)))))))
735 (defun epg-progress-callback-function (what char current total handback)
736 (message "%s: %d%%/%d%%" what current total))
738 (defun epg-configuration ()
739 "Return a list of internal configuration parameters of `epg-gpg-program'."
742 (apply #'call-process epg-gpg-program nil (list t nil) nil
743 '("--with-colons" "--list-config"))
744 (goto-char (point-min))
745 (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
746 (setq type (intern (match-string 1))
747 config (cons (cons type
749 '(pubkey cipher digest compress))
750 (mapcar #'string-to-number
751 (delete "" (split-string
758 (defun epg-list-keys-1 (name mode)
759 (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
760 "--fixed-list-mode" "--with-fingerprint"
762 (if mode "--list-secret-keys" "--list-keys"))
763 (if name (list name))))
764 keys string field index)
766 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
767 (goto-char (point-min))
768 (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
769 (setq keys (cons (make-vector 15 nil) keys)
770 string (match-string 0)
774 (string-match "\\([^:]+\\)?:" string index))
775 (setq index (match-end 0))
776 (aset (car keys) field (match-string 1 string))
777 (setq field (1+ field))))
780 (defun epg-make-sub-key-1 (line)
783 (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
785 (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
787 (member (aref line 0) '("sec" "ssb"))
788 (string-to-number (aref line 3))
789 (string-to-number (aref line 2))
794 (defun epg-list-keys (&optional name mode)
795 (let ((lines (epg-list-keys-1 name mode))
799 ((member (aref (car lines) 0) '("pub" "sec"))
801 (epg-key-set-sub-key-list
803 (nreverse (epg-key-sub-key-list (car keys))))
804 (epg-key-set-user-id-list
806 (nreverse (epg-key-user-id-list (car keys)))))
807 (setq keys (cons (epg-make-key
808 (if (aref (car lines) 8)
809 (cdr (assq (string-to-char (aref (car lines) 8))
810 epg-key-validity-alist))))
812 (epg-key-set-sub-key-list
814 (cons (epg-make-sub-key-1 (car lines))
815 (epg-key-sub-key-list (car keys)))))
816 ((member (aref (car lines) 0) '("sub" "ssb"))
817 (epg-key-set-sub-key-list
819 (cons (epg-make-sub-key-1 (car lines))
820 (epg-key-sub-key-list (car keys)))))
821 ((equal (aref (car lines) 0) "uid")
822 (epg-key-set-user-id-list
824 (cons (epg-make-user-id
825 (if (aref (car lines) 1)
826 (cdr (assq (string-to-char (aref (car lines) 1))
827 epg-key-validity-alist)))
828 (aref (car lines) 9))
829 (epg-key-user-id-list (car keys)))))
830 ((equal (aref (car lines) 0) "fpr")
831 (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
832 (aref (car lines) 9))))
833 (setq lines (cdr lines)))
836 (if (fboundp 'make-temp-file)
837 (defalias 'epg-make-temp-file 'make-temp-file)
838 ;; stolen from poe.el.
839 (defun epg-make-temp-file (prefix)
840 "Create a temporary file.
841 The returned file name (created by appending some random characters at the end
842 of PREFIX, and expanding against `temporary-file-directory' if necessary),
843 is guaranteed to point to a newly created empty file.
844 You can then use `write-region' to write new data into the file."
845 (let (tempdir tempfile)
848 ;; First, create a temporary directory.
849 (while (condition-case ()
851 (setq tempdir (make-temp-name
853 (file-name-directory prefix)
855 ;; return nil or signal an error.
856 (make-directory tempdir))
858 (file-already-exists t)))
859 (set-file-modes tempdir 448)
860 ;; Second, create a temporary file in the tempdir.
861 ;; There *is* a race condition between `make-temp-name'
862 ;; and `write-region', but we don't care it since we are
863 ;; in a private directory now.
864 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
865 (write-region "" nil tempfile nil 'silent)
866 (set-file-modes tempfile 384)
867 ;; Finally, make a hard-link from the tempfile.
868 (while (condition-case ()
870 (setq file (make-temp-name prefix))
871 ;; return nil or signal an error.
872 (add-name-to-file tempfile file))
874 (file-already-exists t)))
876 ;; Cleanup the tempfile.
878 (file-exists-p tempfile)
879 (delete-file tempfile))
880 ;; Cleanup the tempdir.
882 (file-directory-p tempdir)
883 (delete-directory tempdir))))))
886 (defun epg-start-decrypt (context cipher)
887 "Initiate a decrypt operation on CIPHER.
888 CIPHER is a data object.
890 If you use this function, you will need to wait for the completion of
891 `epg-gpg-program' by using `epg-wait-for-completion' and call
892 `epg-reset' to clear a temporaly output file.
893 If you are unsure, use synchronous version of this function
894 `epg-decrypt-file' or `epg-decrypt-string' instead."
895 (unless (epg-data-file cipher)
896 (error "Not a file"))
897 (epg-context-set-result context nil)
898 (epg-start context (list "--decrypt" (epg-data-file cipher)))
899 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
902 (defun epg-decrypt-file (context cipher plain)
903 "Decrypt a file CIPHER and store the result to a file PLAIN.
904 If PLAIN is nil, it returns the result as a string."
908 (epg-context-set-output-file context plain)
909 (epg-context-set-output-file context
910 (epg-make-temp-file "epg-output")))
911 (epg-start-decrypt context (epg-make-data-from-file cipher))
912 (epg-wait-for-completion context t)
913 (if (epg-context-result-for context 'error)
914 (error "Decrypt failed: %S"
915 (epg-context-result-for context 'error)))
917 (epg-read-output context)))
919 (epg-delete-output-file context))
920 (epg-reset context)))
923 (defun epg-decrypt-string (context cipher)
924 "Decrypt a string CIPHER and return the plain text."
925 (let ((input-file (epg-make-temp-file "epg-input"))
926 (coding-system-for-write 'binary))
929 (write-region cipher nil input-file)
930 (epg-context-set-output-file context
931 (epg-make-temp-file "epg-output"))
932 (epg-start-decrypt context (epg-make-data-from-file input-file))
933 (epg-wait-for-completion context)
934 (if (epg-context-result-for context 'error)
935 (error "Decrypt failed: %S"
936 (epg-context-result-for context 'error)))
937 (epg-read-output context))
938 (epg-delete-output-file context)
939 (if (file-exists-p input-file)
940 (delete-file input-file))
941 (epg-reset context))))
944 (defun epg-start-verify (context signature &optional signed-text)
945 "Initiate a verify operation on SIGNATURE.
946 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
948 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
949 For a normal or a clear text signature, SIGNED-TEXT should be nil.
951 If you use this function, you will need to wait for the completion of
952 `epg-gpg-program' by using `epg-wait-for-completion' and call
953 `epg-reset' to clear a temporaly output file.
954 If you are unsure, use synchronous version of this function
955 `epg-verify-file' or `epg-verify-string' instead."
956 (epg-context-set-result context nil)
958 ;; Detached signature.
959 (if (epg-data-file signed-text)
960 (epg-start context (list "--verify" (epg-data-file signature)
961 (epg-data-file signed-text)))
962 (epg-start context (list "--verify" (epg-data-file signature) "-"))
963 (if (eq (process-status (epg-context-process context)) 'run)
964 (process-send-string (epg-context-process context)
965 (epg-data-string signed-text))))
966 ;; Normal (or cleartext) signature.
967 (if (epg-data-file signature)
968 (epg-start context (list "--verify" (epg-data-file signature)))
969 (epg-start context (list "--verify"))
970 (if (eq (process-status (epg-context-process context)) 'run)
971 (process-send-string (epg-context-process context)
972 (epg-data-string signature))))))
975 (defun epg-verify-file (context signature &optional signed-text plain)
976 "Verify a file SIGNATURE.
977 SIGNED-TEXT and PLAIN are also a file if they are specified.
979 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
980 For a normal or a clear text signature, SIGNED-TEXT should be nil."
984 (epg-context-set-output-file context plain)
985 (epg-context-set-output-file context
986 (epg-make-temp-file "epg-output")))
988 (epg-start-verify context
989 (epg-make-data-from-file signature)
990 (epg-make-data-from-file signed-text))
991 (epg-start-verify context
992 (epg-make-data-from-file signature)))
993 (epg-wait-for-completion context t)
995 (epg-read-output context)))
997 (epg-delete-output-file context))
998 (epg-reset context)))
1001 (defun epg-verify-string (context signature &optional signed-text)
1002 "Verify a string SIGNATURE.
1003 SIGNED-TEXT is a string if it is specified.
1005 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1006 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1007 (let ((coding-system-for-write 'binary)
1011 (epg-context-set-output-file context
1012 (epg-make-temp-file "epg-output"))
1015 (setq input-file (epg-make-temp-file "epg-signature"))
1016 (write-region signature nil input-file)
1017 (epg-start-verify context
1018 (epg-make-data-from-file input-file)
1019 (epg-make-data-from-string signed-text)))
1020 (epg-start-verify context (epg-make-data-from-string signature)))
1021 (epg-wait-for-completion context)
1022 (epg-read-output context))
1023 (epg-delete-output-file context)
1025 (file-exists-p input-file))
1026 (delete-file input-file))
1027 (epg-reset context))))
1030 (defun epg-start-sign (context plain &optional mode)
1031 "Initiate a sign operation on PLAIN.
1032 PLAIN is a data object.
1034 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1035 If MODE is t or 'detached, it makes a detached signature.
1036 Otherwise, it makes a normal signature.
1038 If you use this function, you will need to wait for the completion of
1039 `epg-gpg-program' by using `epg-wait-for-completion' and call
1040 `epg-reset' to clear a temporaly output file.
1041 If you are unsure, use synchronous version of this function
1042 `epg-sign-file' or `epg-sign-string' instead."
1043 (epg-context-set-result context nil)
1045 (append (list (if (eq mode 'clearsign)
1047 (if (or (eq mode t) (eq mode 'detached))
1051 (mapcar (lambda (signer)
1053 (epg-context-signers context)))
1054 (if (epg-data-file plain)
1055 (list (epg-data-file plain)))))
1056 (epg-wait-for-status context '("BEGIN_SIGNING"))
1057 (if (and (epg-data-string plain)
1058 (eq (process-status (epg-context-process context)) 'run))
1059 (process-send-string (epg-context-process context)
1060 (epg-data-string plain))))
1063 (defun epg-sign-file (context plain signature &optional mode)
1064 "Sign a file PLAIN and store the result to a file SIGNATURE.
1065 If SIGNATURE is nil, it returns the result as a string.
1066 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1067 If MODE is t or 'detached, it makes a detached signature.
1068 Otherwise, it makes a normal signature."
1072 (epg-context-set-output-file context signature)
1073 (epg-context-set-output-file context
1074 (epg-make-temp-file "epg-output")))
1075 (epg-start-sign context (epg-make-data-from-file plain) mode)
1076 (epg-wait-for-completion context t)
1077 (if (epg-context-result-for context 'error)
1078 (error "Sign failed: %S"
1079 (epg-context-result-for context 'error)))
1081 (epg-read-output context)))
1083 (epg-delete-output-file context))
1084 (epg-reset context)))
1087 (defun epg-sign-string (context plain &optional mode)
1088 "Sign a string PLAIN and return the output as string.
1089 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1090 If MODE is t or 'detached, it makes a detached signature.
1091 Otherwise, it makes a normal signature."
1094 (epg-context-set-output-file context
1095 (epg-make-temp-file "epg-output"))
1096 (epg-start-sign context (epg-make-data-from-string plain) mode)
1097 (epg-wait-for-completion context)
1098 (if (epg-context-result-for context 'error)
1099 (error "Sign failed: %S"
1100 (epg-context-result-for context 'error)))
1101 (epg-read-output context))
1102 (epg-delete-output-file context)
1103 (epg-reset context)))
1106 (defun epg-start-encrypt (context plain recipients
1107 &optional sign always-trust)
1108 "Initiate an encrypt operation on PLAIN.
1109 PLAIN is a data object.
1110 If RECIPIENTS is nil, it performs symmetric encryption.
1112 If you use this function, you will need to wait for the completion of
1113 `epg-gpg-program' by using `epg-wait-for-completion' and call
1114 `epg-reset' to clear a temporaly output file.
1115 If you are unsure, use synchronous version of this function
1116 `epg-encrypt-file' or `epg-encrypt-string' instead."
1117 (epg-context-set-result context nil)
1119 (append (if always-trust '("--always-trust"))
1120 (if recipients '("--encrypt") '("--symmetric"))
1124 (mapcar (lambda (signer)
1126 (epg-context-signers context)))))
1128 (mapcar (lambda (recipient)
1129 (list "-r" recipient))
1131 (if (epg-data-file plain)
1132 (list (epg-data-file plain)))))
1134 (epg-wait-for-status context '("BEGIN_SIGNING")))
1135 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))
1136 (if (and (epg-data-string plain)
1137 (eq (process-status (epg-context-process context)) 'run))
1138 (process-send-string (epg-context-process context)
1139 (epg-data-string plain))))
1142 (defun epg-encrypt-file (context plain recipients
1143 cipher &optional sign always-trust)
1144 "Encrypt a file PLAIN and store the result to a file CIPHER.
1145 If CIPHER is nil, it returns the result as a string.
1146 If RECIPIENTS is nil, it performs symmetric encryption."
1150 (epg-context-set-output-file context cipher)
1151 (epg-context-set-output-file context
1152 (epg-make-temp-file "epg-output")))
1153 (epg-start-encrypt context (epg-make-data-from-file plain)
1154 recipients sign always-trust)
1155 (epg-wait-for-completion context t)
1156 (if (epg-context-result-for context 'error)
1157 (error "Encrypt failed: %S"
1158 (epg-context-result-for context 'error)))
1160 (epg-read-output context)))
1162 (epg-delete-output-file context))
1163 (epg-reset context)))
1166 (defun epg-encrypt-string (context plain recipients
1167 &optional sign always-trust)
1168 "Encrypt a string PLAIN.
1169 If RECIPIENTS is nil, it performs symmetric encryption."
1172 (epg-context-set-output-file context
1173 (epg-make-temp-file "epg-output"))
1174 (epg-start-encrypt context (epg-make-data-from-string plain)
1175 recipients sign always-trust)
1176 (epg-wait-for-completion context)
1177 (if (epg-context-result-for context 'error)
1178 (error "Encrypt failed: %S"
1179 (epg-context-result-for context 'error)))
1180 (epg-read-output context))
1181 (epg-delete-output-file context)
1182 (epg-reset context)))
1185 (defun epg-start-export-keys (context keys)
1186 "Initiate an export keys operation.
1188 If you use this function, you will need to wait for the completion of
1189 `epg-gpg-program' by using `epg-wait-for-completion' and call
1190 `epg-reset' to clear a temporaly output file.
1191 If you are unsure, use synchronous version of this function
1192 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1193 (epg-context-set-result context nil)
1194 (epg-start context (cons "--export"
1198 (car (epg-key-sub-key-list key))))
1202 (defun epg-export-keys-to-file (context keys file)
1203 "Extract public KEYS."
1207 (epg-context-set-output-file context file)
1208 (epg-context-set-output-file context
1209 (epg-make-temp-file "epg-output")))
1210 (epg-start-export-keys context keys)
1211 (epg-wait-for-completion context)
1212 (if (epg-context-result-for context 'error)
1213 (error "Export keys failed"))
1215 (epg-read-output context)))
1217 (epg-delete-output-file context))
1218 (epg-reset context)))
1221 (defun epg-export-keys-to-string (context keys)
1222 "Extract public KEYS and return them as a string."
1223 (epg-export-keys-to-file context keys nil))
1226 (defun epg-start-import-keys (context keys)
1227 "Initiate an import keys operation.
1228 KEYS is a data object.
1230 If you use this function, you will need to wait for the completion of
1231 `epg-gpg-program' by using `epg-wait-for-completion' and call
1232 `epg-reset' to clear a temporaly output file.
1233 If you are unsure, use synchronous version of this function
1234 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1235 (epg-context-set-result context nil)
1236 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1237 (epg-start context (list "--import" (epg-data-file keys)))
1238 (if (and (epg-data-string keys)
1239 (eq (process-status (epg-context-process context)) 'run))
1240 (process-send-string (epg-context-process context)
1241 (epg-data-string keys))))
1243 (defun epg-import-keys-1 (context keys)
1246 (epg-start-import-keys context keys)
1247 (epg-wait-for-completion context (epg-data-file keys))
1248 (if (epg-context-result-for context 'error)
1249 (error "Import keys failed"))
1250 (epg-read-output context))
1251 (epg-reset context)))
1254 (defun epg-import-keys-from-file (context keys)
1255 "Add keys from a file KEYS."
1256 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1259 (defun epg-import-keys-from-string (context keys)
1260 "Add keys from a string KEYS."
1261 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1264 (defun epg-start-delete-keys (context keys &optional allow-secret)
1265 "Initiate an delete keys operation.
1267 If you use this function, you will need to wait for the completion of
1268 `epg-gpg-program' by using `epg-wait-for-completion' and call
1269 `epg-reset' to clear a temporaly output file.
1270 If you are unsure, use synchronous version of this function
1271 `epg-delete-keys' instead."
1272 (epg-context-set-result context nil)
1273 (epg-start context (cons (if allow-secret
1274 "--delete-secret-key"
1279 (car (epg-key-sub-key-list key))))
1283 (defun epg-delete-keys (context keys &optional allow-secret)
1284 "Delete KEYS from the key ring."
1287 (epg-start-delete-keys context keys)
1288 (epg-wait-for-completion context t)
1289 (if (epg-context-result-for context 'error)
1290 (error "Delete key failed")))
1291 (epg-reset context)))
1295 ;;; epg.el ends here