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]+")
74 (capability "[escaESCA]+"))
75 "The schema of keylisting output whose type is \"sec\".
76 This is used by `epg-list-keys'.")
78 (defvar epg-colons-uid-spec
83 (creation-date "[0-9]+")
84 (expiration-date "[0-9]+")
88 "The schema of keylisting output whose type is \"uid\".
89 This is used by `epg-list-keys'.")
91 (defvar epg-colons-fpr-spec
100 (fingerprint "[^:]+"))
101 "The schema of keylisting output whose type is \"fpr\".
102 This is used by `epg-list-keys'.")
104 (defconst epg-cipher-algorithm-alist
116 (defconst epg-pubkey-algorithm-alist
124 (defconst epg-digest-algorithm-alist
132 (defconst epg-compress-algorithm-alist
138 (defvar epg-prompt-alist nil)
140 (defun epg-make-data-from-file (file)
141 "Make a data object from FILE."
144 (defun epg-make-data-from-string (string)
145 "Make a data object from STRING."
148 (defun epg-data-file (data)
149 "Return the file of DATA."
152 (defun epg-data-string (data)
153 "Return the string of DATA."
156 (defun epg-make-context (&optional protocol armor textmode include-certs)
157 "Return a context object."
158 (vector protocol armor textmode include-certs
159 #'epg-passphrase-callback-function
160 #'epg-progress-callback-function
163 (defun epg-context-protocol (context)
164 "Return the protocol used within the context."
167 (defun epg-context-armor (context)
168 "Return t if the output shouled be ASCII armored in the CONTEXT context."
171 (defun epg-context-textmode (context)
172 "Return t if canonical text mode should be used in the CONTEXT context."
175 (defun epg-context-include-certs (context)
176 "Return how many certificates should be included in an S/MIME signed
180 (defun epg-context-passphrase-callback (context)
181 "Return the function used to query passphrase."
184 (defun epg-context-progress-callback (context)
185 "Return the function which handles progress update."
188 (defun epg-context-signers (context)
189 "Return the list of key-id for singning."
192 (defun epg-context-process (context)
193 "Return the process object of `epg-gpg-program'.
194 This function is for internal use only."
197 (defun epg-context-output-file (context)
198 "Return the output file of `epg-gpg-program'.
199 This function is for internal use only."
202 (defun epg-context-result (context)
203 "Return the result of the previous cryptographic operation."
206 (defun epg-context-set-protocol (context protocol)
207 "Set the protocol used within the context."
208 (aset context 0 protocol))
210 (defun epg-context-set-armor (context armor)
211 "Specify if the output shouled be ASCII armored in the CONTEXT context."
212 (aset context 1 armor))
214 (defun epg-context-set-textmode (context textmode)
215 "Specify if canonical text mode should be used in the CONTEXT context."
216 (aset context 2 textmode))
218 (defun epg-context-set-include-certs (context include-certs)
219 "Set how many certificates should be included in an S/MIME signed message."
220 (aset context 3 include-certs))
222 (defun epg-context-set-passphrase-callback (context
224 "Set the function used to query passphrase."
225 (aset context 4 passphrase-callback))
227 (defun epg-context-set-progress-callback (context progress-callback)
228 "Set the function which handles progress update."
229 (aset context 5 progress-callback))
231 (defun epg-context-set-signers (context signers)
232 "Set the list of key-id for singning."
233 (aset context 6 signers))
235 (defun epg-context-set-process (context process)
236 "Set the process object of `epg-gpg-program'.
237 This function is for internal use only."
238 (aset context 7 process))
240 (defun epg-context-set-output-file (context output-file)
241 "Set the output file of `epg-gpg-program'.
242 This function is for internal use only."
243 (aset context 8 output-file))
245 (defun epg-context-set-result (context result)
246 "Set the result of the previous cryptographic operation."
247 (aset context 9 result))
249 (defun epg-make-signature (status key-id user-id)
250 "Return a signature object."
251 (vector status key-id user-id nil nil))
253 (defun epg-signature-status (signature)
254 "Return the status code of SIGNATURE."
257 (defun epg-signature-key-id (signature)
258 "Return the key-id of SIGNATURE."
261 (defun epg-signature-user-id (signature)
262 "Return the user-id of SIGNATURE."
265 (defun epg-signature-validity (signature)
266 "Return the validity of SIGNATURE."
269 (defun epg-signature-fingerprint (signature)
270 "Return the fingerprint of SIGNATURE."
273 (defun epg-signature-set-status (signature status)
274 "Set the status code of SIGNATURE."
275 (aset signature 0 status))
277 (defun epg-signature-set-key-id (signature key-id)
278 "Set the key-id of SIGNATURE."
279 (aset signature 1 key-id))
281 (defun epg-signature-set-user-id (signature user-id)
282 "Set the user-id of SIGNATURE."
283 (aset signature 2 user-id))
285 (defun epg-signature-set-validity (signature validity)
286 "Set the validity of SIGNATURE."
287 (aset signature 3 validity))
289 (defun epg-signature-set-fingerprint (signature fingerprint)
290 "Set the fingerprint of SIGNATURE."
291 (aset signature 4 fingerprint))
293 (defun epg-context-result-for (context name)
294 (cdr (assq name (epg-context-result context))))
296 (defun epg-context-set-result-for (context name value)
297 (let* ((result (epg-context-result context))
298 (entry (assq name result)))
301 (epg-context-set-result context (cons (cons name value) result)))))
303 (defun epg-start (context args)
304 "Start `epg-gpg-program' in a subprocess with given ARGS."
305 (let* ((args (append (list "--no-tty"
308 (if (epg-context-armor context) '("--armor"))
309 (if (epg-context-textmode context) '("--textmode"))
310 (if (epg-context-output-file context)
311 (list "--output" (epg-context-output-file context)))
313 (coding-system-for-write 'binary)
314 process-connection-type
315 (orig-mode (default-file-modes))
316 (buffer (generate-new-buffer " *epg*"))
318 (with-current-buffer buffer
319 (make-local-variable 'epg-read-point)
320 (setq epg-read-point (point-min))
321 (make-local-variable 'epg-pending-status-list)
322 (setq epg-pending-status-list nil)
323 (make-local-variable 'epg-key-id)
324 (setq epg-key-id nil)
325 (make-local-variable 'epg-context)
326 (setq epg-context context))
329 (set-default-file-modes 448)
331 (apply #'start-process "epg" buffer epg-gpg-program args)))
332 (set-default-file-modes orig-mode))
333 (set-process-filter process #'epg-process-filter)
334 (epg-context-set-process context process)))
336 (defun epg-process-filter (process input)
339 (set-buffer (get-buffer-create " *epg-debug*"))
340 (goto-char (point-max))
342 (if (buffer-live-p (process-buffer process))
344 (set-buffer (process-buffer process))
345 (goto-char (point-max))
347 (goto-char epg-read-point)
349 (while (looking-at ".*\n") ;the input line is finished
351 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
352 (let* ((status (match-string 1))
353 (string (match-string 2))
354 (symbol (intern-soft (concat "epg-status-" status))))
355 (if (member status epg-pending-status-list)
356 (setq epg-pending-status-list nil))
359 (funcall symbol process string)))))
361 (setq epg-read-point (point)))))
363 (defun epg-read-output (context)
365 (if (fboundp 'set-buffer-multibyte)
366 (set-buffer-multibyte nil))
367 (if (file-exists-p (epg-context-output-file context))
368 (let ((coding-system-for-read (if (epg-context-textmode context)
371 (insert-file-contents (epg-context-output-file context))
374 (defun epg-wait-for-status (context status-list)
375 (with-current-buffer (process-buffer (epg-context-process context))
376 (setq epg-pending-status-list status-list)
377 (while (and (eq (process-status (epg-context-process context)) 'run)
378 epg-pending-status-list)
379 (accept-process-output (epg-context-process context) 1))))
381 (defun epg-wait-for-completion (context)
382 (if (eq (process-status (epg-context-process context)) 'run)
383 (process-send-eof (epg-context-process context)))
384 (while (eq (process-status (epg-context-process context)) 'run)
385 ;; We can't use accept-process-output instead of sit-for here
386 ;; because it may cause an interrupt during the sentinel execution.
389 (defun epg-reset (context)
390 (if (and (epg-context-process context)
391 (buffer-live-p (process-buffer (epg-context-process context))))
392 (kill-buffer (process-buffer (epg-context-process context))))
393 (epg-context-set-process context nil))
395 (defun epg-delete-output-file (context)
396 (if (and (epg-context-output-file context)
397 (file-exists-p (epg-context-output-file context)))
398 (delete-file (epg-context-output-file context))))
400 (defun epg-status-USERID_HINT (process string)
401 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
402 (let* ((key-id (match-string 1 string))
403 (user-id (match-string 2 string))
404 (entry (assoc key-id epg-user-id-alist)))
406 (setcdr entry user-id)
407 (setq epg-user-id-alist (cons (cons key-id user-id)
408 epg-user-id-alist))))))
410 (defun epg-status-NEED_PASSPHRASE (process string)
411 (if (string-match "\\`\\([^ ]+\\)" string)
412 (setq epg-key-id (match-string 1 string))))
414 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
415 (setq epg-key-id 'SYM))
417 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
418 (setq epg-key-id 'PIN))
420 (defun epg-status-GET_HIDDEN (process string)
422 (funcall (if (consp (epg-context-passphrase-callback epg-context))
423 (car (epg-context-passphrase-callback epg-context))
424 (epg-context-passphrase-callback epg-context))
426 (if (consp (epg-context-passphrase-callback epg-context))
427 (cdr (epg-context-passphrase-callback epg-context)))))
432 (setq string (concat passphrase "\n"))
433 (fillarray passphrase 0)
434 (setq passphrase nil)
435 (process-send-string process string))
437 (fillarray string 0))))))
439 (defun epg-status-GET_BOOL (process string)
440 (let ((entry (assoc string epg-prompt-alist)))
441 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
442 (process-send-string process "y\n")
443 (process-send-string process "n\n"))))
445 (defun epg-status-GET_LINE (process string)
446 (let* ((entry (assoc string epg-prompt-alist))
447 (string (read-string (if entry (cdr entry) (concat string ": ")))))
448 (process-send-string process (concat string "\n"))))
450 (defun epg-status-GOODSIG (process string)
451 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
452 (epg-context-set-result-for
455 (cons (epg-make-signature 'good
456 (match-string 1 string)
457 (match-string 2 string))
458 (epg-context-result-for epg-context 'verify)))))
460 (defun epg-status-EXPSIG (process string)
461 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
462 (epg-context-set-result-for
465 (cons (epg-make-signature 'expired
466 (match-string 1 string)
467 (match-string 2 string))
468 (epg-context-result-for epg-context 'verify)))))
470 (defun epg-status-EXPKEYSIG (process string)
471 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
472 (epg-context-set-result-for
475 (cons (epg-make-signature 'expired-key
476 (match-string 1 string)
477 (match-string 2 string))
478 (epg-context-result-for epg-context 'verify)))))
480 (defun epg-status-REVKEYSIG (process string)
481 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
482 (epg-context-set-result-for
485 (cons (epg-make-signature 'revoked-key
486 (match-string 1 string)
487 (match-string 2 string))
488 (epg-context-result-for epg-context 'verify)))))
490 (defun epg-status-BADSIG (process string)
491 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
492 (epg-context-set-result-for
495 (cons (epg-make-signature 'bad
496 (match-string 1 string)
497 (match-string 2 string))
498 (epg-context-result-for epg-context 'verify)))))
500 (defun epg-status-VALIDSIG (process string)
501 (let ((signature (car (epg-context-result-for epg-context 'verify))))
503 (eq (epg-signature-status signature) 'good)
504 (string-match "\\`\\([^ ]+\\) " string))
505 (epg-signature-set-fingerprint signature (match-string 1 string)))))
507 (defun epg-status-TRUST_UNDEFINED (process string)
508 (let ((signature (car (epg-context-result-for epg-context 'verify))))
510 (eq (epg-signature-status signature) 'good))
511 (epg-signature-set-validity signature 'undefined))))
513 (defun epg-status-TRUST_NEVER (process string)
514 (let ((signature (car (epg-context-result-for epg-context 'verify))))
516 (eq (epg-signature-status signature) 'good))
517 (epg-signature-set-validity signature 'never))))
519 (defun epg-status-TRUST_MARGINAL (process string)
520 (let ((signature (car (epg-context-result-for epg-context 'verify))))
522 (eq (epg-signature-status signature) 'marginal))
523 (epg-signature-set-validity signature 'marginal))))
525 (defun epg-status-TRUST_FULLY (process string)
526 (let ((signature (car (epg-context-result-for epg-context 'verify))))
528 (eq (epg-signature-status signature) 'good))
529 (epg-signature-set-validity signature 'fully))))
531 (defun epg-status-TRUST_ULTIMATE (process string)
532 (let ((signature (car (epg-context-result-for epg-context 'verify))))
534 (eq (epg-signature-status signature) 'good))
535 (epg-signature-set-validity signature 'ultimate))))
537 (defun epg-status-PROGRESS (process string)
538 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
540 (funcall (if (consp (epg-context-progress-callback epg-context))
541 (car (epg-context-progress-callback epg-context))
542 (epg-context-progress-callback epg-context))
543 (match-string 1 string)
544 (match-string 2 string)
545 (string-to-number (match-string 3 string))
546 (string-to-number (match-string 4 string))
547 (if (consp (epg-context-progress-callback epg-context))
548 (cdr (epg-context-progress-callback epg-context))))))
550 (defun epg-status-DECRYPTION_FAILED (process string)
551 (epg-context-set-result-for
553 (cons 'decryption-failed
554 (epg-context-result-for epg-context 'error))))
556 (defun epg-status-NODATA (process string)
557 (epg-context-set-result-for
559 (cons (cons 'no-data (string-to-number string))
560 (epg-context-result-for epg-context 'error))))
562 (defun epg-status-UNEXPECTED (process string)
563 (epg-context-set-result-for
565 (cons (cons 'unexpected (string-to-number string))
566 (epg-context-result-for epg-context 'error))))
568 (defun epg-status-KEYEXPIRED (process string)
569 (epg-context-set-result-for
571 (cons (cons 'key-expired string)
572 (epg-context-result-for epg-context 'error))))
574 (defun epg-status-KEYREVOKED (process string)
575 (epg-context-set-result-for
578 (epg-context-result-for epg-context 'error))))
580 (defun epg-status-BADARMOR (process string)
581 (epg-context-set-result-for
584 (epg-context-result-for epg-context 'error))))
586 (defun epg-passphrase-callback-function (key-id handback)
589 "Passphrase for symmetric encryption: "
591 "Passphrase for PIN: "
592 (let ((entry (assoc key-id epg-user-id-alist)))
594 (format "Passphrase for %s %s: " key-id (cdr entry))
595 (format "Passphrase for %s: " key-id)))))))
597 (defun epg-progress-callback-function (what char current total handback)
598 (message "%s: %d%%/%d%%" what current total))
600 (defun epg-configuration ()
601 "Return a list of internal configuration parameters of `epg-gpg-program'."
604 (apply #'call-process epg-gpg-program nil (list t nil) nil
605 '("--with-colons" "--list-config"))
606 (goto-char (point-min))
607 (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
608 (setq type (intern (match-string 1))
609 config (cons (cons type
611 '(pubkey cipher digest compress))
612 (mapcar #'string-to-number
613 (delete "" (split-string
620 (defun epg-list-keys (name &optional secret)
621 "List keys associated with STRING."
622 (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
623 "--fixed-list-mode" "--with-fingerprint"
624 (if secret "--list-secret-keys" "--list-keys"))
625 (if name (list name))))
626 keys type symbol pointer)
628 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
629 (goto-char (point-min))
630 (while (re-search-forward "^\\([a-z][a-z][a-z]\\):\\(.*\\)" nil t)
631 (setq type (match-string 1)
632 symbol (intern-soft (format "epg-colons-%s-spec" type)))
633 (if (member type '("pub" "sec"))
634 (setq keys (cons nil keys)))
637 (setcar keys (cons (cons (intern type)
639 (symbol-value symbol)
645 (setcar pointer (nreverse (car pointer)))
646 (setq pointer (cdr pointer)))
649 (defun epg-parse-colons (alist string)
653 (or (null (car alist))
656 (concat "\\(" (nth 1 (car alist)) "\\)?:")
660 (setq index (match-end 0))
661 (if (match-beginning 1)
663 (cons (cons (car (car alist))
664 (funcall (or (nth 3 (car alist)) #'identity)
666 (1+ (or (nth 2 (car alist)) 0))
669 (setq index (1+ index)))
670 (setq alist (cdr alist)))
673 (if (fboundp 'make-temp-file)
674 (defalias 'epg-make-temp-file 'make-temp-file)
675 ;; stolen from poe.el.
676 (defun epg-make-temp-file (prefix)
677 "Create a temporary file.
678 The returned file name (created by appending some random characters at the end
679 of PREFIX, and expanding against `temporary-file-directory' if necessary),
680 is guaranteed to point to a newly created empty file.
681 You can then use `write-region' to write new data into the file."
682 (let (tempdir tempfile)
685 ;; First, create a temporary directory.
686 (while (condition-case ()
688 (setq tempdir (make-temp-name
690 (file-name-directory prefix)
692 ;; return nil or signal an error.
693 (make-directory tempdir))
695 (file-already-exists t)))
696 (set-file-modes tempdir 448)
697 ;; Second, create a temporary file in the tempdir.
698 ;; There *is* a race condition between `make-temp-name'
699 ;; and `write-region', but we don't care it since we are
700 ;; in a private directory now.
701 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
702 (write-region "" nil tempfile nil 'silent)
703 (set-file-modes tempfile 384)
704 ;; Finally, make a hard-link from the tempfile.
705 (while (condition-case ()
707 (setq file (make-temp-name prefix))
708 ;; return nil or signal an error.
709 (add-name-to-file tempfile file))
711 (file-already-exists t)))
713 ;; Cleanup the tempfile.
715 (file-exists-p tempfile)
716 (delete-file tempfile))
717 ;; Cleanup the tempdir.
719 (file-directory-p tempdir)
720 (delete-directory tempdir))))))
723 (defun epg-start-decrypt (context cipher)
724 "Initiate a decrypt operation on CIPHER.
725 CIPHER is a data object.
727 If you use this function, you will need to wait for the completion of
728 `epg-gpg-program' by using `epg-wait-for-completion' and call
729 `epg-reset' to clear a temporaly output file.
730 If you are unsure, use synchronous version of this function
731 `epg-decrypt-file' or `epg-decrypt-string' instead."
732 (unless (epg-data-file cipher)
733 (error "Not a file"))
734 (epg-context-set-result context nil)
735 (epg-start context (list "--decrypt" (epg-data-file cipher)))
736 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
739 (defun epg-decrypt-file (context cipher plain)
740 "Decrypt a file CIPHER and store the result to a file PLAIN.
741 If PLAIN is nil, it returns the result as a string."
745 (epg-context-set-output-file context plain)
746 (epg-context-set-output-file context
747 (epg-make-temp-file "epg-output")))
748 (epg-start-decrypt context (epg-make-data-from-file cipher))
749 (epg-wait-for-completion context)
750 (if (epg-context-result-for context 'error)
751 (error "Decryption failed"))
753 (epg-read-output context)))
755 (epg-delete-output-file context))
756 (epg-reset context)))
759 (defun epg-decrypt-string (context cipher)
760 "Decrypt a string CIPHER and return the plain text."
761 (let ((input-file (epg-make-temp-file "epg-input"))
762 (coding-system-for-write 'binary))
765 (write-region cipher nil input-file)
766 (epg-context-set-output-file context
767 (epg-make-temp-file "epg-output"))
768 (epg-start-decrypt context (epg-make-data-from-file input-file))
769 (epg-wait-for-completion context)
770 (if (epg-context-result-for context 'error)
771 (error "Decryption failed"))
772 (epg-read-output context))
773 (epg-delete-output-file context)
774 (if (file-exists-p input-file)
775 (delete-file input-file))
776 (epg-reset context))))
779 (defun epg-start-verify (context signature &optional signed-text)
780 "Initiate a verify operation on SIGNATURE.
781 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
783 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
784 For a normal or a clear text signature, SIGNED-TEXT should be nil.
786 If you use this function, you will need to wait for the completion of
787 `epg-gpg-program' by using `epg-wait-for-completion' and call
788 `epg-reset' to clear a temporaly output file.
789 If you are unsure, use synchronous version of this function
790 `epg-verify-file' or `epg-verify-string' instead."
791 (epg-context-set-result context nil)
793 ;; Detached signature.
794 (if (epg-data-file signed-text)
795 (epg-start context (list "--verify" (epg-data-file signature)
796 (epg-data-file signed-text)))
797 (epg-start context (list "--verify" (epg-data-file signature) "-"))
798 (if (eq (process-status (epg-context-process context)) 'run)
799 (process-send-string (epg-context-process context)
800 (epg-data-string signed-text))))
801 ;; Normal (or cleartext) signature.
802 (if (epg-data-file signature)
803 (epg-start context (list "--verify" (epg-data-file signature)))
804 (epg-start context (list "--verify"))
805 (if (eq (process-status (epg-context-process context)) 'run)
806 (process-send-string (epg-context-process context)
807 (epg-data-string signature))))))
810 (defun epg-verify-file (context signature &optional signed-text plain)
811 "Verify a file SIGNATURE.
812 SIGNED-TEXT and PLAIN are also a file if they are specified.
814 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
815 For a normal or a clear text signature, SIGNED-TEXT should be nil."
819 (epg-context-set-output-file context plain)
820 (epg-context-set-output-file context
821 (epg-make-temp-file "epg-output")))
823 (epg-start-verify context
824 (epg-make-data-from-file signature)
825 (epg-make-data-from-file signed-text))
826 (epg-start-verify context
827 (epg-make-data-from-file signature)))
828 (epg-wait-for-completion context)
830 (epg-read-output context)))
832 (epg-delete-output-file context))
833 (epg-reset context)))
836 (defun epg-verify-string (context signature &optional signed-text)
837 "Verify a string SIGNATURE.
838 SIGNED-TEXT is a string if it is specified.
840 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
841 For a normal or a clear text signature, SIGNED-TEXT should be nil."
842 (let ((coding-system-for-write 'binary)
846 (epg-context-set-output-file context
847 (epg-make-temp-file "epg-output"))
850 (setq input-file (epg-make-temp-file "epg-signature"))
851 (write-region signature nil input-file)
852 (epg-start-verify context
853 (epg-make-data-from-file input-file)
854 (epg-make-data-from-string signed-text)))
855 (epg-start-verify context (epg-make-data-from-string signature)))
856 (epg-wait-for-completion context)
857 (epg-read-output context))
858 (epg-delete-output-file context)
860 (file-exists-p input-file))
861 (delete-file input-file))
862 (epg-reset context))))
865 (defun epg-start-sign (context plain &optional mode)
866 "Initiate a sign operation on PLAIN.
867 PLAIN is a data object.
869 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
870 If MODE is t or 'detached, it makes a detached signature.
871 Otherwise, it makes a normal signature.
873 If you use this function, you will need to wait for the completion of
874 `epg-gpg-program' by using `epg-wait-for-completion' and call
875 `epg-reset' to clear a temporaly output file.
876 If you are unsure, use synchronous version of this function
877 `epg-sign-file' or `epg-sign-string' instead."
878 (epg-context-set-result context nil)
880 (append (list (if (eq mode 'clearsign)
882 (if (or (eq mode t) (eq mode 'detached))
886 (mapcar (lambda (signer)
888 (epg-context-signers context)))
889 (if (epg-data-file plain)
890 (list (epg-data-file plain)))))
891 (epg-wait-for-status context '("BEGIN_SIGNING"))
892 (if (and (epg-data-string plain)
893 (eq (process-status (epg-context-process context)) 'run))
894 (process-send-string (epg-context-process context)
895 (epg-data-string plain))))
898 (defun epg-sign-file (context plain signature &optional mode)
899 "Sign a file PLAIN and store the result to a file SIGNATURE.
900 If SIGNATURE is nil, it returns the result as a string.
901 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
902 If MODE is t or 'detached, it makes a detached signature.
903 Otherwise, it makes a normal signature."
907 (epg-context-set-output-file context signature)
908 (epg-context-set-output-file context
909 (epg-make-temp-file "epg-output")))
910 (epg-start-sign context (epg-make-data-from-file plain) mode)
911 (epg-wait-for-completion context)
912 (if (epg-context-result-for context 'error)
913 (error "Sign failed"))
915 (epg-read-output context)))
917 (epg-delete-output-file context))
918 (epg-reset context)))
921 (defun epg-sign-string (context plain &optional mode)
922 "Sign a string PLAIN and return the output as string.
923 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
924 If MODE is t or 'detached, it makes a detached signature.
925 Otherwise, it makes a normal signature."
928 (epg-context-set-output-file context
929 (epg-make-temp-file "epg-output"))
930 (epg-start-sign context (epg-make-data-from-string plain) mode)
931 (epg-wait-for-completion context)
932 (if (epg-context-result-for context 'error)
933 (error "Sign failed"))
934 (epg-read-output context))
935 (epg-delete-output-file context)
936 (epg-reset context)))
939 (defun epg-start-encrypt (context plain recipients
940 &optional sign always-trust)
941 "Initiate an encrypt operation on PLAIN.
942 PLAIN is a data object.
943 If RECIPIENTS is nil, it performs symmetric encryption.
945 If you use this function, you will need to wait for the completion of
946 `epg-gpg-program' by using `epg-wait-for-completion' and call
947 `epg-reset' to clear a temporaly output file.
948 If you are unsure, use synchronous version of this function
949 `epg-encrypt-file' or `epg-encrypt-string' instead."
950 (epg-context-set-result context nil)
952 (append (if always-trust '("--always-trust"))
953 (if recipients '("--encrypt") '("--symmetric"))
957 (mapcar (lambda (signer)
959 (epg-context-signers context)))))
961 (mapcar (lambda (recipient)
962 (list "-r" recipient))
964 (if (epg-data-file plain)
965 (list (epg-data-file plain)))))
967 (epg-wait-for-status context '("BEGIN_SIGNING"))
968 (if (null recipients)
969 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
970 (if (and (epg-data-string plain)
971 (eq (process-status (epg-context-process context)) 'run))
972 (process-send-string (epg-context-process context)
973 (epg-data-string plain))))
976 (defun epg-encrypt-file (context plain recipients
977 cipher &optional sign always-trust)
978 "Encrypt a file PLAIN and store the result to a file CIPHER.
979 If CIPHER is nil, it returns the result as a string.
980 If RECIPIENTS is nil, it performs symmetric encryption."
984 (epg-context-set-output-file context cipher)
985 (epg-context-set-output-file context
986 (epg-make-temp-file "epg-output")))
987 (epg-start-encrypt context (epg-make-data-from-file plain)
988 recipients sign always-trust)
989 (epg-wait-for-completion context)
990 (if (epg-context-result-for context 'error)
991 (error "Encrypt failed"))
993 (epg-read-output context)))
995 (epg-delete-output-file context))
996 (epg-reset context)))
999 (defun epg-encrypt-string (context plain recipients
1000 &optional sign always-trust)
1001 "Encrypt a string PLAIN.
1002 If RECIPIENTS is nil, it performs symmetric encryption."
1005 (epg-context-set-output-file context
1006 (epg-make-temp-file "epg-output"))
1007 (epg-start-encrypt context (epg-make-data-from-string plain)
1008 recipients sign always-trust)
1009 (epg-wait-for-completion context)
1010 (if (epg-context-result-for context 'error)
1011 (error "Encrypt failed"))
1012 (epg-read-output context))
1013 (epg-delete-output-file context)
1014 (epg-reset context)))
1017 (defun epg-start-export-keys (context pattern)
1018 "Initiate an export keys operation.
1020 If you use this function, you will need to wait for the completion of
1021 `epg-gpg-program' by using `epg-wait-for-completion' and call
1022 `epg-reset' to clear a temporaly output file.
1023 If you are unsure, use synchronous version of this function
1024 `epg-export-keys' instead."
1025 (epg-context-set-result context nil)
1026 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1027 (epg-start context (list "--export" pattern)))
1030 (defun epg-export-keys (context pattern)
1031 "Extract public keys matched with PATTERN and return them."
1034 (epg-start-export-keys context pattern)
1035 (epg-wait-for-completion context)
1036 (if (epg-context-result-for context 'error)
1037 (error "Export keys failed"))
1038 (epg-read-output context))
1039 (epg-reset context)))
1042 (defun epg-start-import-keys (context keys)
1043 "Initiate an import keys operation.
1044 KEYS is a data object.
1046 If you use this function, you will need to wait for the completion of
1047 `epg-gpg-program' by using `epg-wait-for-completion' and call
1048 `epg-reset' to clear a temporaly output file.
1049 If you are unsure, use synchronous version of this function
1050 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1051 (epg-context-set-result context nil)
1052 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1053 (epg-start context (append (list "--import") (epg-data-file keys)))
1054 (if (and (epg-data-string keys)
1055 (eq (process-status (epg-context-process context)) 'run))
1056 (process-send-string (epg-context-process context)
1057 (epg-data-string keys))))
1059 (defun epg-import-keys-1 (context keys)
1062 (epg-start-import-keys context keys)
1063 (epg-wait-for-completion context)
1064 (if (epg-context-result-for context 'error)
1065 (error "Import keys failed"))
1066 (epg-read-output context))
1067 (epg-reset context)))
1070 (defun epg-import-keys-from-file (context keys)
1071 "Add keys from a file KEYS."
1072 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1075 (defun epg-import-keys-from-string (context keys)
1076 "Add keys from a string KEYS."
1077 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1081 ;;; epg.el ends here