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 (defconst epg-cipher-algorithm-alist
100 (defconst epg-pubkey-algorithm-alist
108 (defconst epg-digest-algorithm-alist
116 (defconst epg-compress-algorithm-alist
122 (defvar epg-prompt-alist nil)
124 (defun epg-make-data-from-file (file)
125 "Make a data object from FILE."
128 (defun epg-make-data-from-string (string)
129 "Make a data object from STRING."
132 (defun epg-data-file (data)
133 "Return the file of DATA."
136 (defun epg-data-string (data)
137 "Return the string of DATA."
140 (defun epg-make-context (&optional protocol armor textmode include-certs)
141 "Return a context object."
142 (vector protocol armor textmode include-certs
143 #'epg-passphrase-callback-function
144 #'epg-progress-callback-function
147 (defun epg-context-protocol (context)
148 "Return the protocol used within the context."
151 (defun epg-context-armor (context)
152 "Return t if the output shouled be ASCII armored in the CONTEXT context."
155 (defun epg-context-textmode (context)
156 "Return t if canonical text mode should be used in the CONTEXT context."
159 (defun epg-context-include-certs (context)
160 "Return how many certificates should be included in an S/MIME signed
164 (defun epg-context-passphrase-callback (context)
165 "Return the function used to query passphrase."
168 (defun epg-context-progress-callback (context)
169 "Return the function which handles progress update."
172 (defun epg-context-signers (context)
173 "Return the list of key-id for singning."
176 (defun epg-context-process (context)
177 "Return the process object of `epg-gpg-program'.
178 This function is for internal use only."
181 (defun epg-context-output-file (context)
182 "Return the output file of `epg-gpg-program'.
183 This function is for internal use only."
186 (defun epg-context-result (context)
187 "Return the result of the previous cryptographic operation."
190 (defun epg-context-set-protocol (context protocol)
191 "Set the protocol used within the context."
192 (aset context 0 protocol))
194 (defun epg-context-set-armor (context armor)
195 "Specify if the output shouled be ASCII armored in the CONTEXT context."
196 (aset context 1 armor))
198 (defun epg-context-set-textmode (context textmode)
199 "Specify if canonical text mode should be used in the CONTEXT context."
200 (aset context 2 textmode))
202 (defun epg-context-set-include-certs (context include-certs)
203 "Set how many certificates should be included in an S/MIME signed message."
204 (aset context 3 include-certs))
206 (defun epg-context-set-passphrase-callback (context
208 "Set the function used to query passphrase."
209 (aset context 4 passphrase-callback))
211 (defun epg-context-set-progress-callback (context progress-callback)
212 "Set the function which handles progress update."
213 (aset context 5 progress-callback))
215 (defun epg-context-set-signers (context signers)
216 "Set the list of key-id for singning."
217 (aset context 6 signers))
219 (defun epg-context-set-process (context process)
220 "Set the process object of `epg-gpg-program'.
221 This function is for internal use only."
222 (aset context 7 process))
224 (defun epg-context-set-output-file (context output-file)
225 "Set the output file of `epg-gpg-program'.
226 This function is for internal use only."
227 (aset context 8 output-file))
229 (defun epg-context-set-result (context result)
230 "Set the result of the previous cryptographic operation."
231 (aset context 9 result))
233 (defun epg-make-signature (status key-id user-id)
234 "Return a signature object."
235 (vector status key-id user-id nil nil))
237 (defun epg-signature-status (signature)
238 "Return the status code of SIGNATURE."
241 (defun epg-signature-key-id (signature)
242 "Return the key-id of SIGNATURE."
245 (defun epg-signature-user-id (signature)
246 "Return the user-id of SIGNATURE."
249 (defun epg-signature-validity (signature)
250 "Return the validity of SIGNATURE."
253 (defun epg-signature-fingerprint (signature)
254 "Return the fingerprint of SIGNATURE."
257 (defun epg-signature-set-status (signature status)
258 "Set the status code of SIGNATURE."
259 (aset signature 0 status))
261 (defun epg-signature-set-key-id (signature key-id)
262 "Set the key-id of SIGNATURE."
263 (aset signature 1 key-id))
265 (defun epg-signature-set-user-id (signature user-id)
266 "Set the user-id of SIGNATURE."
267 (aset signature 2 user-id))
269 (defun epg-signature-set-validity (signature validity)
270 "Set the validity of SIGNATURE."
271 (aset signature 3 validity))
273 (defun epg-signature-set-fingerprint (signature fingerprint)
274 "Set the fingerprint of SIGNATURE."
275 (aset signature 4 fingerprint))
277 (defun epg-context-result-for (context name)
278 (cdr (assq name (epg-context-result context))))
280 (defun epg-context-set-result-for (context name value)
281 (let* ((result (epg-context-result context))
282 (entry (assq name result)))
285 (epg-context-set-result context (cons (cons name value) result)))))
287 (defun epg-start (context args)
288 "Start `epg-gpg-program' in a subprocess with given ARGS."
289 (let* ((args (append (list "--no-tty"
292 (if (epg-context-armor context) '("--armor"))
293 (if (epg-context-textmode context) '("--textmode"))
294 (if (epg-context-output-file context)
295 (list "--output" (epg-context-output-file context)))
297 (coding-system-for-write 'binary)
298 process-connection-type
299 (orig-mode (default-file-modes))
300 (buffer (generate-new-buffer " *epg*"))
302 (with-current-buffer buffer
303 (make-local-variable 'epg-read-point)
304 (setq epg-read-point (point-min))
305 (make-local-variable 'epg-pending-status-list)
306 (setq epg-pending-status-list nil)
307 (make-local-variable 'epg-key-id)
308 (setq epg-key-id nil)
309 (make-local-variable 'epg-context)
310 (setq epg-context context))
313 (set-default-file-modes 448)
315 (apply #'start-process "epg" buffer epg-gpg-program args)))
316 (set-default-file-modes orig-mode))
317 (set-process-filter process #'epg-process-filter)
318 (epg-context-set-process context process)))
320 (defun epg-process-filter (process input)
323 (set-buffer (get-buffer-create " *epg-debug*"))
324 (goto-char (point-max))
326 (if (buffer-live-p (process-buffer process))
328 (set-buffer (process-buffer process))
329 (goto-char (point-max))
331 (goto-char epg-read-point)
333 (while (looking-at ".*\n") ;the input line is finished
335 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
336 (let* ((status (match-string 1))
337 (string (match-string 2))
338 (symbol (intern-soft (concat "epg-status-" status))))
339 (if (member status epg-pending-status-list)
340 (setq epg-pending-status-list nil))
343 (funcall symbol process string)))))
345 (setq epg-read-point (point)))))
347 (defun epg-read-output (context)
349 (if (fboundp 'set-buffer-multibyte)
350 (set-buffer-multibyte nil))
351 (if (file-exists-p (epg-context-output-file context))
352 (let ((coding-system-for-read (if (epg-context-textmode context)
355 (insert-file-contents (epg-context-output-file context))
358 (defun epg-wait-for-status (context status-list)
359 (with-current-buffer (process-buffer (epg-context-process context))
360 (setq epg-pending-status-list status-list)
361 (while (and (eq (process-status (epg-context-process context)) 'run)
362 epg-pending-status-list)
363 (accept-process-output (epg-context-process context) 1))))
365 (defun epg-wait-for-completion (context)
366 (if (eq (process-status (epg-context-process context)) 'run)
367 (process-send-eof (epg-context-process context)))
368 (while (eq (process-status (epg-context-process context)) 'run)
369 ;; We can't use accept-process-output instead of sit-for here
370 ;; because it may cause an interrupt during the sentinel execution.
373 (defun epg-reset (context)
374 (if (and (epg-context-process context)
375 (buffer-live-p (process-buffer (epg-context-process context))))
376 (kill-buffer (process-buffer (epg-context-process context))))
377 (epg-context-set-process context nil))
379 (defun epg-delete-output-file (context)
380 (if (and (epg-context-output-file context)
381 (file-exists-p (epg-context-output-file context)))
382 (delete-file (epg-context-output-file context))))
384 (defun epg-status-USERID_HINT (process string)
385 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
386 (let* ((key-id (match-string 1 string))
387 (user-id (match-string 2 string))
388 (entry (assoc key-id epg-user-id-alist)))
390 (setcdr entry user-id)
391 (setq epg-user-id-alist (cons (cons key-id user-id)
392 epg-user-id-alist))))))
394 (defun epg-status-NEED_PASSPHRASE (process string)
395 (if (string-match "\\`\\([^ ]+\\)" string)
396 (setq epg-key-id (match-string 1 string))))
398 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
399 (setq epg-key-id 'SYM))
401 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
402 (setq epg-key-id 'PIN))
404 (defun epg-status-GET_HIDDEN (process string)
406 (funcall (if (consp (epg-context-passphrase-callback epg-context))
407 (car (epg-context-passphrase-callback epg-context))
408 (epg-context-passphrase-callback epg-context))
410 (if (consp (epg-context-passphrase-callback epg-context))
411 (cdr (epg-context-passphrase-callback epg-context)))))
416 (setq string (concat passphrase "\n"))
417 (fillarray passphrase 0)
418 (setq passphrase nil)
419 (process-send-string process string))
421 (fillarray string 0))))))
423 (defun epg-status-GET_BOOL (process string)
424 (let ((entry (assoc string epg-prompt-alist)))
425 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
426 (process-send-string process "y\n")
427 (process-send-string process "n\n"))))
429 (defun epg-status-GET_LINE (process string)
430 (let* ((entry (assoc string epg-prompt-alist))
431 (string (read-string (if entry (cdr entry) (concat string ": ")))))
432 (process-send-string process (concat string "\n"))))
434 (defun epg-status-GOODSIG (process string)
435 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
436 (epg-context-set-result-for
439 (cons (epg-make-signature 'good
440 (match-string 1 string)
441 (match-string 2 string))
442 (epg-context-result-for epg-context 'verify)))))
444 (defun epg-status-EXPSIG (process string)
445 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
446 (epg-context-set-result-for
449 (cons (epg-make-signature 'expired
450 (match-string 1 string)
451 (match-string 2 string))
452 (epg-context-result-for epg-context 'verify)))))
454 (defun epg-status-EXPKEYSIG (process string)
455 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
456 (epg-context-set-result-for
459 (cons (epg-make-signature 'expired-key
460 (match-string 1 string)
461 (match-string 2 string))
462 (epg-context-result-for epg-context 'verify)))))
464 (defun epg-status-REVKEYSIG (process string)
465 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
466 (epg-context-set-result-for
469 (cons (epg-make-signature 'revoked-key
470 (match-string 1 string)
471 (match-string 2 string))
472 (epg-context-result-for epg-context 'verify)))))
474 (defun epg-status-BADSIG (process string)
475 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
476 (epg-context-set-result-for
479 (cons (epg-make-signature 'bad
480 (match-string 1 string)
481 (match-string 2 string))
482 (epg-context-result-for epg-context 'verify)))))
484 (defun epg-status-VALIDSIG (process string)
485 (let ((signature (car (epg-context-result-for epg-context 'verify))))
487 (eq (epg-signature-status signature) 'good)
488 (string-match "\\`\\([^ ]+\\) " string))
489 (epg-signature-set-fingerprint signature (match-string 1 string)))))
491 (defun epg-status-TRUST_UNDEFINED (process string)
492 (let ((signature (car (epg-context-result-for epg-context 'verify))))
494 (eq (epg-signature-status signature) 'good))
495 (epg-signature-set-validity signature 'undefined))))
497 (defun epg-status-TRUST_NEVER (process string)
498 (let ((signature (car (epg-context-result-for epg-context 'verify))))
500 (eq (epg-signature-status signature) 'good))
501 (epg-signature-set-validity signature 'never))))
503 (defun epg-status-TRUST_MARGINAL (process string)
504 (let ((signature (car (epg-context-result-for epg-context 'verify))))
506 (eq (epg-signature-status signature) 'marginal))
507 (epg-signature-set-validity signature 'marginal))))
509 (defun epg-status-TRUST_FULLY (process string)
510 (let ((signature (car (epg-context-result-for epg-context 'verify))))
512 (eq (epg-signature-status signature) 'good))
513 (epg-signature-set-validity signature 'fully))))
515 (defun epg-status-TRUST_ULTIMATE (process string)
516 (let ((signature (car (epg-context-result-for epg-context 'verify))))
518 (eq (epg-signature-status signature) 'good))
519 (epg-signature-set-validity signature 'ultimate))))
521 (defun epg-status-PROGRESS (process string)
522 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
524 (funcall (if (consp (epg-context-progress-callback epg-context))
525 (car (epg-context-progress-callback epg-context))
526 (epg-context-progress-callback epg-context))
527 (match-string 1 string)
528 (match-string 2 string)
529 (string-to-number (match-string 3 string))
530 (string-to-number (match-string 4 string))
531 (if (consp (epg-context-progress-callback epg-context))
532 (cdr (epg-context-progress-callback epg-context))))))
534 (defun epg-status-DECRYPTION_FAILED (process string)
535 (epg-context-set-result-for
537 (cons 'decryption-failed
538 (epg-context-result-for epg-context 'error))))
540 (defun epg-status-NODATA (process string)
541 (epg-context-set-result-for
543 (cons (cons 'no-data (string-to-number string))
544 (epg-context-result-for epg-context 'error))))
546 (defun epg-status-UNEXPECTED (process string)
547 (epg-context-set-result-for
549 (cons (cons 'unexpected (string-to-number string))
550 (epg-context-result-for epg-context 'error))))
552 (defun epg-status-KEYEXPIRED (process string)
553 (epg-context-set-result-for
555 (cons (cons 'key-expired string)
556 (epg-context-result-for epg-context 'error))))
558 (defun epg-status-KEYREVOKED (process string)
559 (epg-context-set-result-for
562 (epg-context-result-for epg-context 'error))))
564 (defun epg-status-BADARMOR (process string)
565 (epg-context-set-result-for
568 (epg-context-result-for epg-context 'error))))
570 (defun epg-passphrase-callback-function (key-id handback)
573 "Passphrase for symmetric encryption: "
575 "Passphrase for PIN: "
576 (let ((entry (assoc key-id epg-user-id-alist)))
578 (format "Passphrase for %s %s: " key-id (cdr entry))
579 (format "Passphrase for %s: " key-id)))))))
581 (defun epg-progress-callback-function (what char current total handback)
582 (message "%s: %d%%/%d%%" what current total))
584 (defun epg-configuration ()
585 "Return a list of internal configuration parameters of `epg-gpg-program'."
588 (apply #'call-process epg-gpg-program nil (list t nil) nil
589 '("--with-colons" "--list-config"))
590 (goto-char (point-min))
591 (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
592 (setq type (intern (match-string 1))
593 config (cons (cons type
595 '(pubkey cipher digest compress))
596 (mapcar #'string-to-number
597 (delete "" (split-string
604 (defun epg-list-keys (name &optional secret)
605 "List keys associated with STRING."
606 (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
608 (if secret "--list-secret-keys" "--list-keys"))
609 (if name (list name))))
610 keys type symbol pointer)
612 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
613 (goto-char (point-min))
614 (while (re-search-forward "^\\([a-z][a-z][a-z]\\):\\(.*\\)" nil t)
615 (setq type (match-string 1)
616 symbol (intern-soft (format "epg-colons-%s-spec" type)))
617 (if (member type '("pub" "sec"))
618 (setq keys (cons nil keys)))
621 (setcar keys (cons (cons (intern type)
623 (symbol-value symbol)
629 (setcar pointer (nreverse (car pointer)))
630 (setq pointer (cdr pointer)))
633 (defun epg-parse-colons (alist string)
637 (or (null (car alist))
640 (concat "\\(" (nth 1 (car alist)) "\\)?:")
644 (setq index (match-end 0))
645 (if (match-beginning 1)
647 (cons (cons (car (car alist))
648 (funcall (or (nth 3 (car alist)) #'identity)
650 (1+ (or (nth 2 (car alist)) 0))
653 (setq index (1+ index)))
654 (setq alist (cdr alist)))
657 (if (fboundp 'make-temp-file)
658 (defalias 'epg-make-temp-file 'make-temp-file)
659 ;; stolen from poe.el.
660 (defun epg-make-temp-file (prefix)
661 "Create a temporary file.
662 The returned file name (created by appending some random characters at the end
663 of PREFIX, and expanding against `temporary-file-directory' if necessary),
664 is guaranteed to point to a newly created empty file.
665 You can then use `write-region' to write new data into the file."
666 (let (tempdir tempfile)
669 ;; First, create a temporary directory.
670 (while (condition-case ()
672 (setq tempdir (make-temp-name
674 (file-name-directory prefix)
676 ;; return nil or signal an error.
677 (make-directory tempdir))
679 (file-already-exists t)))
680 (set-file-modes tempdir 448)
681 ;; Second, create a temporary file in the tempdir.
682 ;; There *is* a race condition between `make-temp-name'
683 ;; and `write-region', but we don't care it since we are
684 ;; in a private directory now.
685 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
686 (write-region "" nil tempfile nil 'silent)
687 (set-file-modes tempfile 384)
688 ;; Finally, make a hard-link from the tempfile.
689 (while (condition-case ()
691 (setq file (make-temp-name prefix))
692 ;; return nil or signal an error.
693 (add-name-to-file tempfile file))
695 (file-already-exists t)))
697 ;; Cleanup the tempfile.
699 (file-exists-p tempfile)
700 (delete-file tempfile))
701 ;; Cleanup the tempdir.
703 (file-directory-p tempdir)
704 (delete-directory tempdir))))))
707 (defun epg-start-decrypt (context cipher)
708 "Initiate a decrypt operation on CIPHER.
709 CIPHER is a data object.
711 If you use this function, you will need to wait for the completion of
712 `epg-gpg-program' by using `epg-wait-for-completion' and call
713 `epg-reset' to clear a temporaly output file.
714 If you are unsure, use synchronous version of this function
715 `epg-decrypt-file' or `epg-decrypt-string' instead."
716 (unless (epg-data-file cipher)
717 (error "Not a file"))
718 (epg-context-set-result context nil)
719 (epg-start context (list "--decrypt" (epg-data-file cipher)))
720 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
723 (defun epg-decrypt-file (context cipher plain)
724 "Decrypt a file CIPHER and store the result to a file PLAIN.
725 If PLAIN is nil, it returns the result as a string."
729 (epg-context-set-output-file context plain)
730 (epg-context-set-output-file context
731 (epg-make-temp-file "epg-output")))
732 (epg-start-decrypt context (epg-make-data-from-file cipher))
733 (epg-wait-for-completion context)
734 (if (epg-context-result-for context 'error)
735 (error "Decryption failed"))
737 (epg-read-output context)))
739 (epg-delete-output-file context))
740 (epg-reset context)))
743 (defun epg-decrypt-string (context cipher)
744 "Decrypt a string CIPHER and return the plain text."
745 (let ((input-file (epg-make-temp-file "epg-input"))
746 (coding-system-for-write 'binary))
749 (write-region cipher nil input-file)
750 (epg-context-set-output-file context
751 (epg-make-temp-file "epg-output"))
752 (epg-start-decrypt context (epg-make-data-from-file input-file))
753 (epg-wait-for-completion context)
754 (if (epg-context-result-for context 'error)
755 (error "Decryption failed"))
756 (epg-read-output context))
757 (epg-delete-output-file context)
758 (if (file-exists-p input-file)
759 (delete-file input-file))
760 (epg-reset context))))
763 (defun epg-start-verify (context signature &optional signed-text)
764 "Initiate a verify operation on SIGNATURE.
765 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
767 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
768 For a normal or a clear text signature, SIGNED-TEXT should be nil.
770 If you use this function, you will need to wait for the completion of
771 `epg-gpg-program' by using `epg-wait-for-completion' and call
772 `epg-reset' to clear a temporaly output file.
773 If you are unsure, use synchronous version of this function
774 `epg-verify-file' or `epg-verify-string' instead."
775 (epg-context-set-result context nil)
777 ;; Detached signature.
778 (if (epg-data-file signed-text)
779 (epg-start context (list "--verify" (epg-data-file signature)
780 (epg-data-file signed-text)))
781 (epg-start context (list "--verify" (epg-data-file signature) "-"))
782 (if (eq (process-status (epg-context-process context)) 'run)
783 (process-send-string (epg-context-process context)
784 (epg-data-string signed-text))))
785 ;; Normal (or cleartext) signature.
786 (if (epg-data-file signature)
787 (epg-start context (list "--verify" (epg-data-file signature)))
788 (epg-start context (list "--verify"))
789 (if (eq (process-status (epg-context-process context)) 'run)
790 (process-send-string (epg-context-process context)
791 (epg-data-string signature))))))
794 (defun epg-verify-file (context signature &optional signed-text plain)
795 "Verify a file SIGNATURE.
796 SIGNED-TEXT and PLAIN are also a file if they are specified.
798 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
799 For a normal or a clear text signature, SIGNED-TEXT should be nil."
803 (epg-context-set-output-file context plain)
804 (epg-context-set-output-file context
805 (epg-make-temp-file "epg-output")))
807 (epg-start-verify context
808 (epg-make-data-from-file signature)
809 (epg-make-data-from-file signed-text))
810 (epg-start-verify context
811 (epg-make-data-from-file signature)))
812 (epg-wait-for-completion context)
814 (epg-read-output context)))
816 (epg-delete-output-file context))
817 (epg-reset context)))
820 (defun epg-verify-string (context signature &optional signed-text)
821 "Verify a string SIGNATURE.
822 SIGNED-TEXT is a string if it is specified.
824 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
825 For a normal or a clear text signature, SIGNED-TEXT should be nil."
826 (let ((coding-system-for-write 'binary)
830 (epg-context-set-output-file context
831 (epg-make-temp-file "epg-output"))
834 (setq input-file (epg-make-temp-file "epg-signature"))
835 (write-region signature nil input-file)
836 (epg-start-verify context
837 (epg-make-data-from-file input-file)
838 (epg-make-data-from-string signed-text)))
839 (epg-start-verify context (epg-make-data-from-string signature)))
840 (epg-wait-for-completion context)
841 (epg-read-output context))
842 (epg-delete-output-file context)
844 (file-exists-p input-file))
845 (delete-file input-file))
846 (epg-reset context))))
849 (defun epg-start-sign (context plain &optional mode)
850 "Initiate a sign operation on PLAIN.
851 PLAIN is a data object.
853 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
854 If MODE is t or 'detached, it makes a detached signature.
855 Otherwise, it makes a normal signature.
857 If you use this function, you will need to wait for the completion of
858 `epg-gpg-program' by using `epg-wait-for-completion' and call
859 `epg-reset' to clear a temporaly output file.
860 If you are unsure, use synchronous version of this function
861 `epg-sign-file' or `epg-sign-string' instead."
862 (epg-context-set-result context nil)
864 (append (list (if (eq mode 'clearsign)
866 (if (or (eq mode t) (eq mode 'detached))
870 (mapcar (lambda (signer)
872 (epg-context-signers context)))
873 (if (epg-data-file plain)
874 (list (epg-data-file plain)))))
875 (epg-wait-for-status context '("BEGIN_SIGNING"))
876 (if (and (epg-data-string plain)
877 (eq (process-status (epg-context-process context)) 'run))
878 (process-send-string (epg-context-process context)
879 (epg-data-string plain))))
882 (defun epg-sign-file (context plain signature &optional mode)
883 "Sign a file PLAIN and store the result to a file SIGNATURE.
884 If SIGNATURE is nil, it returns the result as a string.
885 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
886 If MODE is t or 'detached, it makes a detached signature.
887 Otherwise, it makes a normal signature."
891 (epg-context-set-output-file context signature)
892 (epg-context-set-output-file context
893 (epg-make-temp-file "epg-output")))
894 (epg-start-sign context (epg-make-data-from-file plain) mode)
895 (epg-wait-for-completion context)
896 (if (epg-context-result-for context 'error)
897 (error "Sign failed"))
899 (epg-read-output context)))
901 (epg-delete-output-file context))
902 (epg-reset context)))
905 (defun epg-sign-string (context plain &optional mode)
906 "Sign a string PLAIN and return the output as string.
907 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
908 If MODE is t or 'detached, it makes a detached signature.
909 Otherwise, it makes a normal signature."
912 (epg-context-set-output-file context
913 (epg-make-temp-file "epg-output"))
914 (epg-start-sign context (epg-make-data-from-string plain) mode)
915 (epg-wait-for-completion context)
916 (if (epg-context-result-for context 'error)
917 (error "Sign failed"))
918 (epg-read-output context))
919 (epg-delete-output-file context)
920 (epg-reset context)))
923 (defun epg-start-encrypt (context plain recipients
924 &optional sign always-trust)
925 "Initiate an encrypt operation on PLAIN.
926 PLAIN is a data object.
927 If RECIPIENTS is nil, it performs symmetric encryption.
929 If you use this function, you will need to wait for the completion of
930 `epg-gpg-program' by using `epg-wait-for-completion' and call
931 `epg-reset' to clear a temporaly output file.
932 If you are unsure, use synchronous version of this function
933 `epg-encrypt-file' or `epg-encrypt-string' instead."
934 (epg-context-set-result context nil)
936 (append (if always-trust '("--always-trust"))
937 (if recipients '("--encrypt") '("--symmetric"))
941 (mapcar (lambda (signer)
943 (epg-context-signers context)))))
945 (mapcar (lambda (recipient)
946 (list "-r" recipient))
948 (if (epg-data-file plain)
949 (list (epg-data-file plain)))))
951 (epg-wait-for-status context '("BEGIN_SIGNING"))
952 (if (null recipients)
953 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
954 (if (and (epg-data-string plain)
955 (eq (process-status (epg-context-process context)) 'run))
956 (process-send-string (epg-context-process context)
957 (epg-data-string plain))))
960 (defun epg-encrypt-file (context plain recipients
961 cipher &optional sign always-trust)
962 "Encrypt a file PLAIN and store the result to a file CIPHER.
963 If CIPHER is nil, it returns the result as a string.
964 If RECIPIENTS is nil, it performs symmetric encryption."
968 (epg-context-set-output-file context cipher)
969 (epg-context-set-output-file context
970 (epg-make-temp-file "epg-output")))
971 (epg-start-encrypt context (epg-make-data-from-file plain)
972 recipients sign always-trust)
973 (epg-wait-for-completion context)
974 (if (epg-context-result-for context 'error)
975 (error "Encrypt failed"))
977 (epg-read-output context)))
979 (epg-delete-output-file context))
980 (epg-reset context)))
983 (defun epg-encrypt-string (context plain recipients
984 &optional sign always-trust)
985 "Encrypt a string PLAIN.
986 If RECIPIENTS is nil, it performs symmetric encryption."
989 (epg-context-set-output-file context
990 (epg-make-temp-file "epg-output"))
991 (epg-start-encrypt context (epg-make-data-from-string plain)
992 recipients sign always-trust)
993 (epg-wait-for-completion context)
994 (if (epg-context-result-for context 'error)
995 (error "Encrypt failed"))
996 (epg-read-output context))
997 (epg-delete-output-file context)
998 (epg-reset context)))
1001 (defun epg-start-export-keys (context pattern)
1002 "Initiate an export keys operation.
1004 If you use this function, you will need to wait for the completion of
1005 `epg-gpg-program' by using `epg-wait-for-completion' and call
1006 `epg-reset' to clear a temporaly output file.
1007 If you are unsure, use synchronous version of this function
1008 `epg-export-keys' instead."
1009 (epg-context-set-result context nil)
1010 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1011 (epg-start context (list "--export" pattern)))
1014 (defun epg-export-keys (context pattern)
1015 "Extract public keys matched with PATTERN and return them."
1018 (epg-start-export-keys context pattern)
1019 (epg-wait-for-completion context)
1020 (if (epg-context-result-for context 'error)
1021 (error "Export keys failed"))
1022 (epg-read-output context))
1023 (epg-reset context)))
1026 (defun epg-start-import-keys (context keys)
1027 "Initiate an import keys operation.
1028 KEYS is a data object.
1030 If you use this function, you will need to wait for the completion of
1031 `epg-gpg-program' by using `epg-wait-for-completion' and call
1032 `epg-reset' to clear a temporaly output file.
1033 If you are unsure, use synchronous version of this function
1034 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1035 (epg-context-set-result context nil)
1036 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1037 (epg-start context (append (list "--import") (epg-data-file keys)))
1038 (if (and (epg-data-string keys)
1039 (eq (process-status (epg-context-process context)) 'run))
1040 (process-send-string (epg-context-process context)
1041 (epg-data-string keys))))
1043 (defun epg-import-keys-1 (context keys)
1046 (epg-start-import-keys context keys)
1047 (epg-wait-for-completion context)
1048 (if (epg-context-result-for context 'error)
1049 (error "Import keys failed"))
1050 (epg-read-output context))
1051 (epg-reset context)))
1054 (defun epg-import-keys-from-file (context keys)
1055 "Add keys from a file KEYS."
1056 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1059 (defun epg-import-keys-from-string (context keys)
1060 "Add keys from a string KEYS."
1061 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1065 ;;; epg.el ends here