1 ;;; epg.el --- EasyPG, yet another GnuPG interface.
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.
29 "EasyPG, yet another GnuPG interface.")
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 (defvar epg-colons-pub-spec
50 (length "[0-9]+" 0 string-to-number)
51 (algorithm "[0-9]+" 0 string-to-number)
53 (creation-date "[0-9]+")
54 (expiration-date "[0-9]+")
59 (capability "[escaESCA]*"))
60 "The schema of keylisting output whose type is \"pub\".
61 This is used by `epg-list-keys'.")
63 (defvar epg-colons-sec-spec
65 (length "[0-9]+" 0 string-to-number)
66 (algorithm "[0-9]+" 0 string-to-number)
68 (creation-date "[0-9]+")
69 (expiration-date "[0-9]+")
72 "The schema of keylisting output whose type is \"sec\".
73 This is used by `epg-list-keys'.")
75 (defvar epg-colons-uid-spec
80 (creation-date "[0-9]+")
81 (expiration-date "[0-9]+")
85 "The schema of keylisting output whose type is \"uid\".
86 This is used by `epg-list-keys'.")
88 (defvar epg-prompt-alist nil)
90 (defun epg-make-context (&optional protocol armor textmode include-certs)
91 "Return a context object."
92 (vector protocol armor textmode include-certs
93 (cons #'epg-passphrase-callback-function nil)
94 (cons #'epg-progress-callback-function nil)
97 (defun epg-context-protocol (context)
98 "Return the protocol used within the context."
101 (defun epg-context-armor (context)
102 "Return t if the output shouled be ASCII armored in the CONTEXT context."
105 (defun epg-context-textmode (context)
106 "Return t if canonical text mode should be used in the CONTEXT context."
109 (defun epg-context-include-certs (context)
110 "Return how many certificates should be included in an S/MIME signed
114 (defun epg-context-passphrase-callback-info (context)
115 "Return the function used to query passphrase."
118 (defun epg-context-progress-callback-info (context)
119 "Return the function which handles progress update."
122 (defun epg-context-signers (context)
123 "Return the list of key-id for singning."
126 (defun epg-context-process (context)
127 "Return the process object of `epg-gpg-program'.
128 This function is for internal use only."
131 (defun epg-context-output-file (context)
132 "Return the output file of `epg-gpg-program'.
133 This function is for internal use only."
136 (defun epg-context-result (context)
137 "Return the result of the previous cryptographic operation."
140 (defun epg-context-set-protocol (context protocol)
141 "Set the protocol used within the context."
142 (aset context 0 protocol))
144 (defun epg-context-set-armor (context armor)
145 "Specify if the output shouled be ASCII armored in the CONTEXT context."
146 (aset context 1 armor))
148 (defun epg-context-set-textmode (context textmode)
149 "Specify if canonical text mode should be used in the CONTEXT context."
150 (aset context 2 textmode))
152 (defun epg-context-set-include-certs (context include-certs)
153 "Set how many certificates should be included in an S/MIME signed message."
154 (aset context 3 include-certs))
156 (defun epg-context-set-passphrase-callback-info (context
157 passphrase-callback-info)
158 "Set the function used to query passphrase."
159 (aset context 4 passphrase-callback-info))
161 (defun epg-context-set-progress-callback-info (context progress-callback-info)
162 "Set the function which handles progress update."
163 (aset context 5 progress-callback-info))
165 (defun epg-context-set-signers (context signers)
166 "Set the list of key-id for singning."
167 (aset context 6 signers))
169 (defun epg-context-set-process (context process)
170 "Set the process object of `epg-gpg-program'.
171 This function is for internal use only."
172 (aset context 7 process))
174 (defun epg-context-set-output-file (context output-file)
175 "Set the output file of `epg-gpg-program'.
176 This function is for internal use only."
177 (aset context 8 output-file))
179 (defun epg-context-set-result (context result)
180 "Set the result of the previous cryptographic operation."
181 (aset context 9 result))
183 (defun epg-make-signature (status key-id user-id)
184 "Return a signature object."
185 (vector status key-id user-id nil nil))
187 (defun epg-signature-status (signature)
188 "Return the status code of SIGNATURE."
191 (defun epg-signature-key-id (signature)
192 "Return the key-id of SIGNATURE."
195 (defun epg-signature-user-id (signature)
196 "Return the user-id of SIGNATURE."
199 (defun epg-signature-validity (signature)
200 "Return the validity of SIGNATURE."
203 (defun epg-signature-fingerprint (signature)
204 "Return the fingerprint of SIGNATURE."
207 (defun epg-signature-set-status (signature status)
208 "Set the status code of SIGNATURE."
209 (aset signature 0 status))
211 (defun epg-signature-set-key-id (signature key-id)
212 "Set the key-id of SIGNATURE."
213 (aset signature 1 key-id))
215 (defun epg-signature-set-user-id (signature user-id)
216 "Set the user-id of SIGNATURE."
217 (aset signature 2 user-id))
219 (defun epg-signature-set-validity (signature validity)
220 "Set the validity of SIGNATURE."
221 (aset signature 3 validity))
223 (defun epg-signature-set-fingerprint (signature fingerprint)
224 "Set the fingerprint of SIGNATURE."
225 (aset signature 4 fingerprint))
227 (defun epg-context-result-for (context name)
228 (cdr (assq name (epg-context-result context))))
230 (defun epg-context-set-result-for (context name value)
231 (let* ((result (epg-context-result context))
232 (entry (assq name result)))
235 (epg-context-set-result context (cons (cons name value) result)))))
237 (defun epg-start (context args)
238 "Start `epg-gpg-program' in a subprocess with given ARGS."
239 (let* ((args (append (list "--no-tty"
243 (if (epg-context-armor context) '("--armor"))
244 (if (epg-context-textmode context) '("--textmode"))
245 (if (epg-context-output-file context)
246 (list "--output" (epg-context-output-file context)))
248 (coding-system-for-write 'binary)
249 process-connection-type
250 (orig-mode (default-file-modes))
251 (buffer (generate-new-buffer " *epg*"))
253 (with-current-buffer buffer
254 (make-local-variable 'epg-read-point)
255 (setq epg-read-point (point-min))
256 (make-local-variable 'epg-pending-status-list)
257 (setq epg-pending-status-list nil)
258 (make-local-variable 'epg-key-id)
259 (setq epg-key-id nil)
260 (make-local-variable 'epg-context)
261 (setq epg-context context))
264 (set-default-file-modes 448)
266 (apply #'start-process "epg" buffer epg-gpg-program args)))
267 (set-default-file-modes orig-mode))
268 (set-process-filter process #'epg-process-filter)
269 (epg-context-set-process context process)))
271 (defun epg-process-filter (process input)
274 (set-buffer (get-buffer-create " *epg-debug*"))
275 (goto-char (point-max))
277 (if (buffer-live-p (process-buffer process))
279 (set-buffer (process-buffer process))
280 (goto-char (point-max))
282 (goto-char epg-read-point)
284 (while (looking-at ".*\n") ;the input line is finished
286 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
287 (let* ((status (match-string 1))
288 (string (match-string 2))
289 (symbol (intern-soft (concat "epg-status-" status))))
290 (if (member status epg-pending-status-list)
291 (setq epg-pending-status-list nil))
294 (funcall symbol process string)))))
296 (setq epg-read-point (point)))))
298 (defun epg-read-output (context)
300 (if (fboundp 'set-buffer-multibyte)
301 (set-buffer-multibyte nil))
302 (if (file-exists-p (epg-context-output-file context))
303 (let ((coding-system-for-read (if (epg-context-textmode context)
306 (insert-file-contents (epg-context-output-file context))
309 (defun epg-wait-for-status (context status-list)
310 (with-current-buffer (process-buffer (epg-context-process context))
311 (setq epg-pending-status-list status-list)
312 (while (and (eq (process-status (epg-context-process context)) 'run)
313 epg-pending-status-list)
314 (accept-process-output (epg-context-process context) 1))))
316 (defun epg-wait-for-completion (context)
317 (if (eq (process-status (epg-context-process context)) 'run)
318 (process-send-eof (epg-context-process context)))
319 (while (eq (process-status (epg-context-process context)) 'run)
320 ;; We can't use accept-process-output instead of sit-for here
321 ;; because it may cause an interrupt during the sentinel execution.
324 (defun epg-reset (context)
325 (if (and (epg-context-process context)
326 (buffer-live-p (process-buffer (epg-context-process context))))
327 (kill-buffer (process-buffer (epg-context-process context))))
328 (epg-context-set-process context nil)
329 (if (file-exists-p (epg-context-output-file context))
330 (delete-file (epg-context-output-file context))))
332 (defun epg-status-USERID_HINT (process string)
333 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
334 (let* ((key-id (match-string 1 string))
335 (user-id (match-string 2 string))
336 (entry (assoc key-id epg-user-id-alist)))
338 (setcdr entry user-id)
339 (setq epg-user-id-alist (cons (cons key-id user-id)
340 epg-user-id-alist))))))
342 (defun epg-status-NEED_PASSPHRASE (process string)
343 (if (string-match "\\`\\([^ ]+\\)" string)
344 (setq epg-key-id (match-string 1 string))))
346 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
347 (setq epg-key-id 'SYM))
349 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
350 (setq epg-key-id 'PIN))
352 (defun epg-status-GET_HIDDEN (process string)
354 (funcall (car (epg-context-passphrase-callback-info epg-context))
356 (cdr (epg-context-passphrase-callback-info epg-context))))
361 (setq string (concat passphrase "\n"))
362 (fillarray passphrase 0)
363 (setq passphrase nil)
364 (process-send-string process string))
366 (fillarray string 0))))))
368 (defun epg-status-GET_BOOL (process string)
369 (let ((entry (assoc string epg-prompt-alist)))
370 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
371 (process-send-string process "y\n")
372 (process-send-string process "n\n"))))
374 (defun epg-status-GET_LINE (process string)
375 (let* ((entry (assoc string epg-prompt-alist))
376 (string (read-string (if entry (cdr entry) (concat string ": ")))))
377 (process-send-string process (concat string "\n")))))
379 (defun epg-status-GOODSIG (process string)
380 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
381 (epg-context-set-result-for
384 (cons (epg-make-signature 'good
385 (match-string 1 string)
386 (match-string 2 string))
387 (epg-context-result-for epg-context 'verify)))))
389 (defun epg-status-EXPSIG (process string)
390 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
391 (epg-context-set-result-for
394 (cons (epg-make-signature 'expired
395 (match-string 1 string)
396 (match-string 2 string))
397 (epg-context-result-for epg-context 'verify)))))
399 (defun epg-status-EXPKEYSIG (process string)
400 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
401 (epg-context-set-result-for
404 (cons (epg-make-signature 'expired-key
405 (match-string 1 string)
406 (match-string 2 string))
407 (epg-context-result-for epg-context 'verify)))))
409 (defun epg-status-REVKEYSIG (process string)
410 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
411 (epg-context-set-result-for
414 (cons (epg-make-signature 'revoked-key
415 (match-string 1 string)
416 (match-string 2 string))
417 (epg-context-result-for epg-context 'verify)))))
419 (defun epg-status-BADSIG (process string)
420 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
421 (epg-context-set-result-for
424 (cons (epg-make-signature 'bad
425 (match-string 1 string)
426 (match-string 2 string))
427 (epg-context-result-for epg-context 'verify)))))
429 (defun epg-status-VALIDSIG (process string)
430 (let ((signature (car (epg-context-result-for epg-context 'verify))))
432 (eq (epg-signature-status signature) 'good)
433 (string-match "\\`\\([^ ]+\\) " string))
434 (epg-signature-set-fingerprint signature (match-string 1 string)))))
436 (defun epg-status-TRUST_UNDEFINED (process string)
437 (let ((signature (car (epg-context-result-for epg-context 'verify))))
439 (eq (epg-signature-status signature) 'good))
440 (epg-signature-set-validity signature 'undefined))))
442 (defun epg-status-TRUST_NEVER (process string)
443 (let ((signature (car (epg-context-result-for epg-context 'verify))))
445 (eq (epg-signature-status signature) 'good))
446 (epg-signature-set-validity signature 'never))))
448 (defun epg-status-TRUST_MARGINAL (process string)
449 (let ((signature (car (epg-context-result-for epg-context 'verify))))
451 (eq (epg-signature-status signature) 'marginal))
452 (epg-signature-set-validity signature 'marginal))))
454 (defun epg-status-TRUST_FULLY (process string)
455 (let ((signature (car (epg-context-result-for epg-context 'verify))))
457 (eq (epg-signature-status signature) 'good))
458 (epg-signature-set-validity signature 'fully))))
460 (defun epg-status-TRUST_ULTIMATE (process string)
461 (let ((signature (car (epg-context-result-for epg-context 'verify))))
463 (eq (epg-signature-status signature) 'good))
464 (epg-signature-set-validity signature 'ultimate))))
466 (defun epg-status-PROGRESS (process string)
467 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
469 (funcall (car (epg-context-progress-callback-info epg-context))
470 (match-string 1 string)
471 (match-string 2 string)
472 (string-to-number (match-string 3 string))
473 (string-to-number (match-string 4 string))
474 (cdr (epg-context-progress-callback-info epg-context)))))
476 (defun epg-status-DECRYPTION_FAILED (process string)
477 (epg-context-set-result-for
479 (cons 'decryption-failed
480 (epg-context-result-for epg-context 'error))))
482 (defun epg-status-NODATA (process string)
483 (epg-context-set-result-for
485 (cons (cons 'no-data (string-to-number string))
486 (epg-context-result-for epg-context 'error))))
488 (defun epg-status-UNEXPECTED (process string)
489 (epg-context-set-result-for
491 (cons (cons 'unexpected (string-to-number string))
492 (epg-context-result-for epg-context 'error))))
494 (defun epg-status-KEYEXPIRED (process string)
495 (epg-context-set-result-for
497 (cons (cons 'key-expired string)
498 (epg-context-result-for epg-context 'error))))
500 (defun epg-status-KEYREVOKED (process string)
501 (epg-context-set-result-for
504 (epg-context-result-for epg-context 'error))))
506 (defun epg-status-BADARMOR (process string)
507 (epg-context-set-result-for
510 (epg-context-result-for epg-context 'error))))
512 (defun epg-passphrase-callback-function (key-id handback)
515 "Passphrase for symmetric encryption: "
517 "Passphrase for PIN: "
518 (let ((entry (assoc key-id epg-user-id-alist)))
520 (format "Passphrase for %s %s: " key-id (cdr entry))
521 (format "Passphrase for %s: " key-id)))))))
523 (defun epg-progress-callback-function (what char current total handback)
524 (message "%s: %d%%/%d%%" what current total))
526 (defun epg-list-keys (name &optional secret)
527 "List keys associated with STRING."
528 (let ((args (list "--with-colons" "--no-greeting" "--batch"
530 (if secret "--list-secret-keys" "--list-keys")
532 keys type symbol pointer)
534 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
535 (goto-char (point-min))
536 (while (looking-at "\\([a-z][a-z][a-z]\\):\\(.*\\)")
537 (setq type (match-string 1)
538 symbol (intern-soft (format "epg-colons-%s-spec" type)))
539 (if (member type '("pub" "sec"))
540 (setq keys (cons nil keys)))
543 (setcar keys (cons (cons (intern type)
545 (symbol-value symbol)
551 (setcar pointer (nreverse (car pointer)))
552 (setq pointer (cdr pointer)))
555 (defun epg-parse-colons (alist string)
559 (or (null (car alist))
562 (concat "\\(" (nth 1 (car alist)) "\\)?:")
566 (setq index (match-end 0))
567 (if (match-beginning 1)
569 (cons (cons (car (car alist))
570 (funcall (or (nth 3 (car alist)) #'identity)
572 (1+ (or (nth 2 (car alist)) 0))
575 (setq index (1+ index)))
576 (setq alist (cdr alist)))
579 (if (fboundp 'make-temp-file)
580 (defalias 'epg-make-temp-file 'make-temp-file)
581 ;; stolen from poe.el.
582 (defun epg-make-temp-file (prefix)
583 "Create a temporary file.
584 The returned file name (created by appending some random characters at the end
585 of PREFIX, and expanding against `temporary-file-directory' if necessary),
586 is guaranteed to point to a newly created empty file.
587 You can then use `write-region' to write new data into the file."
588 (let (tempdir tempfile)
591 ;; First, create a temporary directory.
592 (while (condition-case ()
594 (setq tempdir (make-temp-name
596 (file-name-directory prefix)
598 ;; return nil or signal an error.
599 (make-directory tempdir))
601 (file-already-exists t)))
602 (set-file-modes tempdir 448)
603 ;; Second, create a temporary file in the tempdir.
604 ;; There *is* a race condition between `make-temp-name'
605 ;; and `write-region', but we don't care it since we are
606 ;; in a private directory now.
607 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
608 (write-region "" nil tempfile nil 'silent)
609 (set-file-modes tempfile 384)
610 ;; Finally, make a hard-link from the tempfile.
611 (while (condition-case ()
613 (setq file (make-temp-name prefix))
614 ;; return nil or signal an error.
615 (add-name-to-file tempfile file))
617 (file-already-exists t)))
619 ;; Cleanup the tempfile.
621 (file-exists-p tempfile)
622 (delete-file tempfile))
623 ;; Cleanup the tempdir.
625 (file-directory-p tempdir)
626 (delete-directory tempdir))))))
629 (defun epg-start-decrypt (context input-file)
630 "Initiate a decrypt operation on INPUT-FILE.
632 If you use this function, you will need to wait for the completion of
633 `epg-gpg-program' by using `epg-wait-for-completion' and call
634 `epg-reset' to clear a temporaly output file.
635 If you are unsure, use synchronous version of this function
636 `epg-decrypt-string' instead."
637 (epg-context-set-result context nil)
638 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
640 (list "--decrypt" input-file))
641 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
644 (defun epg-decrypt-file (context input-file)
645 "Decrypt INPUT-FILE and return the plain text."
648 (epg-start-decrypt context input-file)
649 (epg-wait-for-completion context)
650 (if (epg-context-result-for context 'error)
651 (error "Decryption failed"))
652 (epg-read-output context))
653 (epg-reset context)))
656 (defun epg-decrypt-string (context string)
657 "Decrypt STRING and return the plain text."
658 (let ((input-file (epg-make-temp-file "epg-input"))
659 (coding-system-for-write 'binary))
662 (write-region string nil input-file)
663 (epg-decrypt-file context input-file))
664 (if (file-exists-p input-file)
665 (delete-file input-file)))))
668 (defun epg-start-verify (context signature &optional string)
669 "Initiate a verify operation on SIGNATURE.
671 For a detached signature, both SIGNATURE and STRING should be string.
672 For a normal or a clear text signature, STRING should be nil.
674 If you use this function, you will need to wait for the completion of
675 `epg-gpg-program' by using `epg-wait-for-completion' and call
676 `epg-reset' to clear a temporaly output file.
677 If you are unsure, use synchronous version of this function
678 `epg-verify-string' instead."
679 (epg-context-set-result context nil)
680 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
682 ;; Detached signature.
685 (append (list "--verify")
686 (list signature "-")))
687 (if (eq (process-status (epg-context-process context)) 'run)
688 (process-send-string (epg-context-process context) string)))
689 ;; Normal (or cleartext) signature.
690 (epg-start context (list "--verify"))
691 (if (eq (process-status (epg-context-process context)) 'run)
692 (process-send-string (epg-context-process context) signature))))
695 (defun epg-verify-file (context input-file &optional string)
698 For a detached signature, both INPUT-FILE and STRING should be string.
699 For a normal or a clear text signature, STRING should be nil."
702 (epg-start-verify context input-file string)
703 (epg-wait-for-completion context)
704 (epg-context-result-for context 'verify))
705 (epg-reset context)))
708 (defun epg-verify-string (context signature &optional string)
711 For a detached signature, both SIGNATURE and STRING should be string.
712 For a normal or a clear text signature, STRING should be nil."
713 (let ((input-file (epg-make-temp-file "epg-input"))
714 (coding-system-for-write 'binary))
718 (write-region signature nil input-file))
719 (epg-verify-file context input-file string))
720 (if (file-exists-p input-file)
721 (delete-file input-file)))))
724 (defun epg-start-sign (context string &optional mode)
725 "Initiate a sign operation on STRING.
727 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
728 If MODE is t or 'detached, it makes a detached signature.
729 Otherwise, it makes a normal signature.
731 If you use this function, you will need to wait for the completion of
732 `epg-gpg-program' by using `epg-wait-for-completion' and call
733 `epg-reset' to clear a temporaly output file.
734 If you are unsure, use synchronous version of this function
735 `epg-sign-string' instead."
736 (epg-context-set-result context nil)
737 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
739 (append (list (if (eq mode 'clearsign)
741 (if (or (eq mode t) (eq mode 'detached))
745 (mapcar (lambda (signer)
747 (epg-context-signers context)))))
748 (epg-wait-for-status context '("BEGIN_SIGNING"))
749 (if (eq (process-status (epg-context-process context)) 'run)
750 (process-send-string (epg-context-process context) string)))
753 (defun epg-sign-string (context string &optional mode)
754 "Sign STRING and return the output as string.
755 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
756 If MODE is t or 'detached, it makes a detached signature.
757 Otherwise, it makes a normal signature."
760 (epg-start-sign context string mode)
761 (epg-wait-for-completion context)
762 (if (epg-context-result-for context 'error)
763 (error "Sign failed"))
764 (epg-read-output context))
765 (epg-reset context)))
768 (defun epg-start-encrypt (context string recipients
769 &optional sign always-trust)
770 "Initiate an encrypt operation on STRING.
771 If RECIPIENTS is nil, it performs symmetric encryption.
773 If you use this function, you will need to wait for the completion of
774 `epg-gpg-program' by using `epg-wait-for-completion' and call
775 `epg-reset' to clear a temporaly output file.
776 If you are unsure, use synchronous version of this function
777 `epg-encrypt-string' instead."
778 (epg-context-set-result context nil)
779 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
781 (append (if always-trust '("--always-trust"))
782 (if recipients '("--encrypt") '("--symmetric"))
786 (mapcar (lambda (signer)
788 (epg-context-signers context)))))
790 (mapcar (lambda (recipient)
791 (list "-r" recipient))
794 (epg-wait-for-status context '("BEGIN_SIGNING"))
795 (if (null recipients)
796 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
797 (if (eq (process-status (epg-context-process context)) 'run)
798 (process-send-string (epg-context-process context) string)))
801 (defun epg-encrypt-string (context string recipients
802 &optional sign always-trust)
804 If RECIPIENTS is nil, it performs symmetric encryption."
807 (epg-start-encrypt context string recipients sign always-trust)
808 (epg-wait-for-completion context)
809 (if (epg-context-result-for context 'error)
810 (error "Encrypt failed"))
811 (epg-read-output context))
812 (epg-reset context)))
815 (defun epg-start-export-keys (context pattern)
816 "Initiate an export keys operation.
818 If you use this function, you will need to wait for the completion of
819 `epg-gpg-program' by using `epg-wait-for-completion' and call
820 `epg-reset' to clear a temporaly output file.
821 If you are unsure, use synchronous version of this function
822 `epg-export-keys' instead."
823 (epg-context-set-result context nil)
824 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
825 (epg-start context (list "--export" pattern)))
828 (defun epg-export-keys (context pattern)
829 "Extract public keys matched with PATTERN and return them."
832 (epg-start-export-keys context pattern)
833 (epg-wait-for-completion context)
834 (if (epg-context-result-for context 'error)
835 (error "Export keys failed"))
836 (epg-read-output context))
837 (epg-reset context)))
840 (defun epg-start-import-keys (context keys)
841 "Initiate an import key operation.
843 If you use this function, you will need to wait for the completion of
844 `epg-gpg-program' by using `epg-wait-for-completion' and call
845 `epg-reset' to clear a temporaly output file.
846 If you are unsure, use synchronous version of this function
847 `epg-import-keys' instead."
848 (epg-context-set-result context nil)
849 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
850 (epg-start context (list "--import"))
851 (if (eq (process-status (epg-context-process context)) 'run)
852 (process-send-string (epg-context-process context) keys)))
855 (defun epg-import-keys (context keys)
859 (epg-start-import-keys context keys)
860 (epg-wait-for-completion context)
861 (if (epg-context-result-for context 'error)
862 (error "Import keys failed"))
863 (epg-read-output context))
864 (epg-reset context)))