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-data-from-file (file)
91 "Make a data object from FILE."
94 (defun epg-make-data-from-string (string)
95 "Make a data object from STRING."
98 (defun epg-data-file (data)
99 "Return the file of DATA."
102 (defun epg-data-string (data)
103 "Return the string of DATA."
106 (defun epg-make-context (&optional protocol armor textmode include-certs)
107 "Return a context object."
108 (vector protocol armor textmode include-certs
109 #'epg-passphrase-callback-function
110 #'epg-progress-callback-function
113 (defun epg-context-protocol (context)
114 "Return the protocol used within the context."
117 (defun epg-context-armor (context)
118 "Return t if the output shouled be ASCII armored in the CONTEXT context."
121 (defun epg-context-textmode (context)
122 "Return t if canonical text mode should be used in the CONTEXT context."
125 (defun epg-context-include-certs (context)
126 "Return how many certificates should be included in an S/MIME signed
130 (defun epg-context-passphrase-callback (context)
131 "Return the function used to query passphrase."
134 (defun epg-context-progress-callback (context)
135 "Return the function which handles progress update."
138 (defun epg-context-signers (context)
139 "Return the list of key-id for singning."
142 (defun epg-context-process (context)
143 "Return the process object of `epg-gpg-program'.
144 This function is for internal use only."
147 (defun epg-context-output-file (context)
148 "Return the output file of `epg-gpg-program'.
149 This function is for internal use only."
152 (defun epg-context-result (context)
153 "Return the result of the previous cryptographic operation."
156 (defun epg-context-set-protocol (context protocol)
157 "Set the protocol used within the context."
158 (aset context 0 protocol))
160 (defun epg-context-set-armor (context armor)
161 "Specify if the output shouled be ASCII armored in the CONTEXT context."
162 (aset context 1 armor))
164 (defun epg-context-set-textmode (context textmode)
165 "Specify if canonical text mode should be used in the CONTEXT context."
166 (aset context 2 textmode))
168 (defun epg-context-set-include-certs (context include-certs)
169 "Set how many certificates should be included in an S/MIME signed message."
170 (aset context 3 include-certs))
172 (defun epg-context-set-passphrase-callback (context
174 "Set the function used to query passphrase."
175 (aset context 4 passphrase-callback))
177 (defun epg-context-set-progress-callback (context progress-callback)
178 "Set the function which handles progress update."
179 (aset context 5 progress-callback))
181 (defun epg-context-set-signers (context signers)
182 "Set the list of key-id for singning."
183 (aset context 6 signers))
185 (defun epg-context-set-process (context process)
186 "Set the process object of `epg-gpg-program'.
187 This function is for internal use only."
188 (aset context 7 process))
190 (defun epg-context-set-output-file (context output-file)
191 "Set the output file of `epg-gpg-program'.
192 This function is for internal use only."
193 (aset context 8 output-file))
195 (defun epg-context-set-result (context result)
196 "Set the result of the previous cryptographic operation."
197 (aset context 9 result))
199 (defun epg-make-signature (status key-id user-id)
200 "Return a signature object."
201 (vector status key-id user-id nil nil))
203 (defun epg-signature-status (signature)
204 "Return the status code of SIGNATURE."
207 (defun epg-signature-key-id (signature)
208 "Return the key-id of SIGNATURE."
211 (defun epg-signature-user-id (signature)
212 "Return the user-id of SIGNATURE."
215 (defun epg-signature-validity (signature)
216 "Return the validity of SIGNATURE."
219 (defun epg-signature-fingerprint (signature)
220 "Return the fingerprint of SIGNATURE."
223 (defun epg-signature-set-status (signature status)
224 "Set the status code of SIGNATURE."
225 (aset signature 0 status))
227 (defun epg-signature-set-key-id (signature key-id)
228 "Set the key-id of SIGNATURE."
229 (aset signature 1 key-id))
231 (defun epg-signature-set-user-id (signature user-id)
232 "Set the user-id of SIGNATURE."
233 (aset signature 2 user-id))
235 (defun epg-signature-set-validity (signature validity)
236 "Set the validity of SIGNATURE."
237 (aset signature 3 validity))
239 (defun epg-signature-set-fingerprint (signature fingerprint)
240 "Set the fingerprint of SIGNATURE."
241 (aset signature 4 fingerprint))
243 (defun epg-context-result-for (context name)
244 (cdr (assq name (epg-context-result context))))
246 (defun epg-context-set-result-for (context name value)
247 (let* ((result (epg-context-result context))
248 (entry (assq name result)))
251 (epg-context-set-result context (cons (cons name value) result)))))
253 (defun epg-start (context args)
254 "Start `epg-gpg-program' in a subprocess with given ARGS."
255 (let* ((args (append (list "--no-tty"
259 (if (epg-context-armor context) '("--armor"))
260 (if (epg-context-textmode context) '("--textmode"))
261 (if (epg-context-output-file context)
262 (list "--output" (epg-context-output-file context)))
264 (coding-system-for-write 'binary)
265 process-connection-type
266 (orig-mode (default-file-modes))
267 (buffer (generate-new-buffer " *epg*"))
269 (with-current-buffer buffer
270 (make-local-variable 'epg-read-point)
271 (setq epg-read-point (point-min))
272 (make-local-variable 'epg-pending-status-list)
273 (setq epg-pending-status-list nil)
274 (make-local-variable 'epg-key-id)
275 (setq epg-key-id nil)
276 (make-local-variable 'epg-context)
277 (setq epg-context context))
280 (set-default-file-modes 448)
282 (apply #'start-process "epg" buffer epg-gpg-program args)))
283 (set-default-file-modes orig-mode))
284 (set-process-filter process #'epg-process-filter)
285 (epg-context-set-process context process)))
287 (defun epg-process-filter (process input)
290 (set-buffer (get-buffer-create " *epg-debug*"))
291 (goto-char (point-max))
293 (if (buffer-live-p (process-buffer process))
295 (set-buffer (process-buffer process))
296 (goto-char (point-max))
298 (goto-char epg-read-point)
300 (while (looking-at ".*\n") ;the input line is finished
302 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
303 (let* ((status (match-string 1))
304 (string (match-string 2))
305 (symbol (intern-soft (concat "epg-status-" status))))
306 (if (member status epg-pending-status-list)
307 (setq epg-pending-status-list nil))
310 (funcall symbol process string)))))
312 (setq epg-read-point (point)))))
314 (defun epg-read-output (context)
316 (if (fboundp 'set-buffer-multibyte)
317 (set-buffer-multibyte nil))
318 (if (file-exists-p (epg-context-output-file context))
319 (let ((coding-system-for-read (if (epg-context-textmode context)
322 (insert-file-contents (epg-context-output-file context))
325 (defun epg-wait-for-status (context status-list)
326 (with-current-buffer (process-buffer (epg-context-process context))
327 (setq epg-pending-status-list status-list)
328 (while (and (eq (process-status (epg-context-process context)) 'run)
329 epg-pending-status-list)
330 (accept-process-output (epg-context-process context) 1))))
332 (defun epg-wait-for-completion (context)
333 (if (eq (process-status (epg-context-process context)) 'run)
334 (process-send-eof (epg-context-process context)))
335 (while (eq (process-status (epg-context-process context)) 'run)
336 ;; We can't use accept-process-output instead of sit-for here
337 ;; because it may cause an interrupt during the sentinel execution.
340 (defun epg-reset (context)
341 (if (and (epg-context-process context)
342 (buffer-live-p (process-buffer (epg-context-process context))))
343 (kill-buffer (process-buffer (epg-context-process context))))
344 (epg-context-set-process context nil))
346 (defun epg-delete-output-file (context)
347 (if (and (epg-context-output-file context)
348 (file-exists-p (epg-context-output-file context)))
349 (delete-file (epg-context-output-file context))))
351 (defun epg-status-USERID_HINT (process string)
352 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
353 (let* ((key-id (match-string 1 string))
354 (user-id (match-string 2 string))
355 (entry (assoc key-id epg-user-id-alist)))
357 (setcdr entry user-id)
358 (setq epg-user-id-alist (cons (cons key-id user-id)
359 epg-user-id-alist))))))
361 (defun epg-status-NEED_PASSPHRASE (process string)
362 (if (string-match "\\`\\([^ ]+\\)" string)
363 (setq epg-key-id (match-string 1 string))))
365 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
366 (setq epg-key-id 'SYM))
368 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
369 (setq epg-key-id 'PIN))
371 (defun epg-status-GET_HIDDEN (process string)
373 (funcall (if (consp (epg-context-passphrase-callback epg-context))
374 (car (epg-context-passphrase-callback epg-context))
375 (epg-context-passphrase-callback epg-context))
377 (if (consp (epg-context-passphrase-callback epg-context))
378 (cdr (epg-context-passphrase-callback epg-context)))))
383 (setq string (concat passphrase "\n"))
384 (fillarray passphrase 0)
385 (setq passphrase nil)
386 (process-send-string process string))
388 (fillarray string 0))))))
390 (defun epg-status-GET_BOOL (process string)
391 (let ((entry (assoc string epg-prompt-alist)))
392 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
393 (process-send-string process "y\n")
394 (process-send-string process "n\n"))))
396 (defun epg-status-GET_LINE (process string)
397 (let* ((entry (assoc string epg-prompt-alist))
398 (string (read-string (if entry (cdr entry) (concat string ": ")))))
399 (process-send-string process (concat string "\n"))))
401 (defun epg-status-GOODSIG (process string)
402 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
403 (epg-context-set-result-for
406 (cons (epg-make-signature 'good
407 (match-string 1 string)
408 (match-string 2 string))
409 (epg-context-result-for epg-context 'verify)))))
411 (defun epg-status-EXPSIG (process string)
412 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
413 (epg-context-set-result-for
416 (cons (epg-make-signature 'expired
417 (match-string 1 string)
418 (match-string 2 string))
419 (epg-context-result-for epg-context 'verify)))))
421 (defun epg-status-EXPKEYSIG (process string)
422 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
423 (epg-context-set-result-for
426 (cons (epg-make-signature 'expired-key
427 (match-string 1 string)
428 (match-string 2 string))
429 (epg-context-result-for epg-context 'verify)))))
431 (defun epg-status-REVKEYSIG (process string)
432 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
433 (epg-context-set-result-for
436 (cons (epg-make-signature 'revoked-key
437 (match-string 1 string)
438 (match-string 2 string))
439 (epg-context-result-for epg-context 'verify)))))
441 (defun epg-status-BADSIG (process string)
442 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
443 (epg-context-set-result-for
446 (cons (epg-make-signature 'bad
447 (match-string 1 string)
448 (match-string 2 string))
449 (epg-context-result-for epg-context 'verify)))))
451 (defun epg-status-VALIDSIG (process string)
452 (let ((signature (car (epg-context-result-for epg-context 'verify))))
454 (eq (epg-signature-status signature) 'good)
455 (string-match "\\`\\([^ ]+\\) " string))
456 (epg-signature-set-fingerprint signature (match-string 1 string)))))
458 (defun epg-status-TRUST_UNDEFINED (process string)
459 (let ((signature (car (epg-context-result-for epg-context 'verify))))
461 (eq (epg-signature-status signature) 'good))
462 (epg-signature-set-validity signature 'undefined))))
464 (defun epg-status-TRUST_NEVER (process string)
465 (let ((signature (car (epg-context-result-for epg-context 'verify))))
467 (eq (epg-signature-status signature) 'good))
468 (epg-signature-set-validity signature 'never))))
470 (defun epg-status-TRUST_MARGINAL (process string)
471 (let ((signature (car (epg-context-result-for epg-context 'verify))))
473 (eq (epg-signature-status signature) 'marginal))
474 (epg-signature-set-validity signature 'marginal))))
476 (defun epg-status-TRUST_FULLY (process string)
477 (let ((signature (car (epg-context-result-for epg-context 'verify))))
479 (eq (epg-signature-status signature) 'good))
480 (epg-signature-set-validity signature 'fully))))
482 (defun epg-status-TRUST_ULTIMATE (process string)
483 (let ((signature (car (epg-context-result-for epg-context 'verify))))
485 (eq (epg-signature-status signature) 'good))
486 (epg-signature-set-validity signature 'ultimate))))
488 (defun epg-status-PROGRESS (process string)
489 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
491 (funcall (if (consp (epg-context-progress-callback epg-context))
492 (car (epg-context-progress-callback epg-context))
493 (epg-context-progress-callback epg-context))
494 (match-string 1 string)
495 (match-string 2 string)
496 (string-to-number (match-string 3 string))
497 (string-to-number (match-string 4 string))
498 (if (consp (epg-context-progress-callback epg-context))
499 (cdr (epg-context-progress-callback epg-context))))))
501 (defun epg-status-DECRYPTION_FAILED (process string)
502 (epg-context-set-result-for
504 (cons 'decryption-failed
505 (epg-context-result-for epg-context 'error))))
507 (defun epg-status-NODATA (process string)
508 (epg-context-set-result-for
510 (cons (cons 'no-data (string-to-number string))
511 (epg-context-result-for epg-context 'error))))
513 (defun epg-status-UNEXPECTED (process string)
514 (epg-context-set-result-for
516 (cons (cons 'unexpected (string-to-number string))
517 (epg-context-result-for epg-context 'error))))
519 (defun epg-status-KEYEXPIRED (process string)
520 (epg-context-set-result-for
522 (cons (cons 'key-expired string)
523 (epg-context-result-for epg-context 'error))))
525 (defun epg-status-KEYREVOKED (process string)
526 (epg-context-set-result-for
529 (epg-context-result-for epg-context 'error))))
531 (defun epg-status-BADARMOR (process string)
532 (epg-context-set-result-for
535 (epg-context-result-for epg-context 'error))))
537 (defun epg-passphrase-callback-function (key-id handback)
540 "Passphrase for symmetric encryption: "
542 "Passphrase for PIN: "
543 (let ((entry (assoc key-id epg-user-id-alist)))
545 (format "Passphrase for %s %s: " key-id (cdr entry))
546 (format "Passphrase for %s: " key-id)))))))
548 (defun epg-progress-callback-function (what char current total handback)
549 (message "%s: %d%%/%d%%" what current total))
551 (defun epg-list-keys (name &optional secret)
552 "List keys associated with STRING."
553 (let ((args (list "--with-colons" "--no-greeting" "--batch"
555 (if secret "--list-secret-keys" "--list-keys")
557 keys type symbol pointer)
559 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
560 (goto-char (point-min))
561 (while (looking-at "\\([a-z][a-z][a-z]\\):\\(.*\\)")
562 (setq type (match-string 1)
563 symbol (intern-soft (format "epg-colons-%s-spec" type)))
564 (if (member type '("pub" "sec"))
565 (setq keys (cons nil keys)))
568 (setcar keys (cons (cons (intern type)
570 (symbol-value symbol)
576 (setcar pointer (nreverse (car pointer)))
577 (setq pointer (cdr pointer)))
580 (defun epg-parse-colons (alist string)
584 (or (null (car alist))
587 (concat "\\(" (nth 1 (car alist)) "\\)?:")
591 (setq index (match-end 0))
592 (if (match-beginning 1)
594 (cons (cons (car (car alist))
595 (funcall (or (nth 3 (car alist)) #'identity)
597 (1+ (or (nth 2 (car alist)) 0))
600 (setq index (1+ index)))
601 (setq alist (cdr alist)))
604 (if (fboundp 'make-temp-file)
605 (defalias 'epg-make-temp-file 'make-temp-file)
606 ;; stolen from poe.el.
607 (defun epg-make-temp-file (prefix)
608 "Create a temporary file.
609 The returned file name (created by appending some random characters at the end
610 of PREFIX, and expanding against `temporary-file-directory' if necessary),
611 is guaranteed to point to a newly created empty file.
612 You can then use `write-region' to write new data into the file."
613 (let (tempdir tempfile)
616 ;; First, create a temporary directory.
617 (while (condition-case ()
619 (setq tempdir (make-temp-name
621 (file-name-directory prefix)
623 ;; return nil or signal an error.
624 (make-directory tempdir))
626 (file-already-exists t)))
627 (set-file-modes tempdir 448)
628 ;; Second, create a temporary file in the tempdir.
629 ;; There *is* a race condition between `make-temp-name'
630 ;; and `write-region', but we don't care it since we are
631 ;; in a private directory now.
632 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
633 (write-region "" nil tempfile nil 'silent)
634 (set-file-modes tempfile 384)
635 ;; Finally, make a hard-link from the tempfile.
636 (while (condition-case ()
638 (setq file (make-temp-name prefix))
639 ;; return nil or signal an error.
640 (add-name-to-file tempfile file))
642 (file-already-exists t)))
644 ;; Cleanup the tempfile.
646 (file-exists-p tempfile)
647 (delete-file tempfile))
648 ;; Cleanup the tempdir.
650 (file-directory-p tempdir)
651 (delete-directory tempdir))))))
654 (defun epg-start-decrypt (context cipher)
655 "Initiate a decrypt operation on CIPHER.
656 CIPHER is a data object.
658 If you use this function, you will need to wait for the completion of
659 `epg-gpg-program' by using `epg-wait-for-completion' and call
660 `epg-reset' to clear a temporaly output file.
661 If you are unsure, use synchronous version of this function
662 `epg-decrypt-file' or `epg-decrypt-string' instead."
663 (unless (epg-data-file cipher)
664 (error "Not a file"))
665 (epg-context-set-result context nil)
666 (epg-start context (list "--decrypt" (epg-data-file cipher)))
667 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
670 (defun epg-decrypt-file (context cipher plain)
671 "Decrypt a file CIPHER and store the result to a file PLAIN.
672 If PLAIN is nil, it returns the result as a string."
676 (epg-context-set-output-file context plain)
677 (epg-context-set-output-file context
678 (epg-make-temp-file "epg-output")))
679 (epg-start-decrypt context (epg-make-data-from-file cipher))
680 (epg-wait-for-completion context)
681 (if (epg-context-result-for context 'error)
682 (error "Decryption failed"))
684 (epg-read-output context)))
686 (epg-delete-output-file context))
687 (epg-reset context)))
690 (defun epg-decrypt-string (context cipher)
691 "Decrypt a string CIPHER and return the plain text."
692 (let ((input-file (epg-make-temp-file "epg-input"))
693 (coding-system-for-write 'binary))
696 (write-region cipher nil input-file)
697 (epg-context-set-output-file context
698 (epg-make-temp-file "epg-output"))
699 (epg-start-decrypt context (epg-make-data-from-file input-file))
700 (epg-wait-for-completion context)
701 (if (epg-context-result-for context 'error)
702 (error "Decryption failed"))
703 (epg-read-output context))
704 (epg-delete-output-file context)
705 (if (file-exists-p input-file)
706 (delete-file input-file))
707 (epg-reset context))))
710 (defun epg-start-verify (context signature &optional signed-text)
711 "Initiate a verify operation on SIGNATURE.
712 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
714 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
715 For a normal or a clear text signature, SIGNED-TEXT should be nil.
717 If you use this function, you will need to wait for the completion of
718 `epg-gpg-program' by using `epg-wait-for-completion' and call
719 `epg-reset' to clear a temporaly output file.
720 If you are unsure, use synchronous version of this function
721 `epg-verify-file' or `epg-verify-string' instead."
722 (epg-context-set-result context nil)
724 ;; Detached signature.
725 (if (epg-data-file signed-text)
726 (epg-start context (list "--verify" (epg-data-file signature)
727 (epg-data-file signed-text)))
728 (epg-start context (list "--verify" (epg-data-file signature) "-"))
729 (if (eq (process-status (epg-context-process context)) 'run)
730 (process-send-string (epg-context-process context)
731 (epg-data-string signed-text))))
732 ;; Normal (or cleartext) signature.
733 (if (epg-data-file signature)
734 (epg-start context (list "--verify" (epg-data-file signature)))
735 (epg-start context (list "--verify"))
736 (if (eq (process-status (epg-context-process context)) 'run)
737 (process-send-string (epg-context-process context)
738 (epg-data-string signature))))))
741 (defun epg-verify-file (context signature &optional signed-text plain)
742 "Verify a file SIGNATURE.
743 SIGNED-TEXT and PLAIN are also a file if they are specified.
745 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
746 For a normal or a clear text signature, SIGNED-TEXT should be nil."
750 (epg-context-set-output-file context plain)
751 (epg-context-set-output-file context
752 (epg-make-temp-file "epg-output")))
754 (epg-start-verify context
755 (epg-make-data-from-file signature)
756 (epg-make-data-from-file signed-text))
757 (epg-start-verify context
758 (epg-make-data-from-file signature)))
759 (epg-wait-for-completion context)
761 (epg-read-output context)))
763 (epg-delete-output-file context))
764 (epg-reset context)))
767 (defun epg-verify-string (context signature &optional signed-text)
768 "Verify a string SIGNATURE.
769 SIGNED-TEXT is a string if it is specified.
771 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
772 For a normal or a clear text signature, SIGNED-TEXT should be nil."
773 (let ((coding-system-for-write 'binary)
777 (epg-context-set-output-file context
778 (epg-make-temp-file "epg-output"))
781 (setq input-file (epg-make-temp-file "epg-signature"))
782 (write-region signature nil input-file)
783 (epg-start-verify context
784 (epg-make-data-from-file input-file)
785 (epg-make-data-from-string signed-text)))
786 (epg-start-verify context (epg-make-data-from-string signature)))
787 (epg-wait-for-completion context)
788 (epg-read-output context))
789 (epg-delete-output-file context)
791 (file-exists-p input-file))
792 (delete-file input-file))
793 (epg-reset context))))
796 (defun epg-start-sign (context plain &optional mode)
797 "Initiate a sign operation on PLAIN.
798 PLAIN is a data object.
800 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
801 If MODE is t or 'detached, it makes a detached signature.
802 Otherwise, it makes a normal signature.
804 If you use this function, you will need to wait for the completion of
805 `epg-gpg-program' by using `epg-wait-for-completion' and call
806 `epg-reset' to clear a temporaly output file.
807 If you are unsure, use synchronous version of this function
808 `epg-sign-file' or `epg-sign-string' instead."
809 (epg-context-set-result context nil)
811 (append (list (if (eq mode 'clearsign)
813 (if (or (eq mode t) (eq mode 'detached))
817 (mapcar (lambda (signer)
819 (epg-context-signers context)))
820 (if (epg-data-file plain)
821 (list (epg-data-file plain)))))
822 (epg-wait-for-status context '("BEGIN_SIGNING"))
823 (if (and (epg-data-string plain)
824 (eq (process-status (epg-context-process context)) 'run))
825 (process-send-string (epg-context-process context)
826 (epg-data-string plain))))
829 (defun epg-sign-file (context plain signature &optional mode)
830 "Sign a file PLAIN and store the result to a file SIGNATURE.
831 If SIGNATURE is nil, it returns the result as a string.
832 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
833 If MODE is t or 'detached, it makes a detached signature.
834 Otherwise, it makes a normal signature."
838 (epg-context-set-output-file context signature)
839 (epg-context-set-output-file context
840 (epg-make-temp-file "epg-output")))
841 (epg-start-sign context (epg-make-data-from-file plain) mode)
842 (epg-wait-for-completion context)
843 (if (epg-context-result-for context 'error)
844 (error "Sign failed"))
846 (epg-read-output context)))
848 (epg-delete-output-file context))
849 (epg-reset context)))
852 (defun epg-sign-string (context plain &optional mode)
853 "Sign a string PLAIN and return the output as string.
854 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
855 If MODE is t or 'detached, it makes a detached signature.
856 Otherwise, it makes a normal signature."
859 (epg-context-set-output-file context
860 (epg-make-temp-file "epg-output"))
861 (epg-start-sign context (epg-make-data-from-string plain) mode)
862 (epg-wait-for-completion context)
863 (if (epg-context-result-for context 'error)
864 (error "Sign failed"))
865 (epg-read-output context))
866 (epg-delete-output-file context)
867 (epg-reset context)))
870 (defun epg-start-encrypt (context plain recipients
871 &optional sign always-trust)
872 "Initiate an encrypt operation on PLAIN.
873 PLAIN is a data object.
874 If RECIPIENTS is nil, it performs symmetric encryption.
876 If you use this function, you will need to wait for the completion of
877 `epg-gpg-program' by using `epg-wait-for-completion' and call
878 `epg-reset' to clear a temporaly output file.
879 If you are unsure, use synchronous version of this function
880 `epg-encrypt-file' or `epg-encrypt-string' instead."
881 (epg-context-set-result context nil)
883 (append (if always-trust '("--always-trust"))
884 (if recipients '("--encrypt") '("--symmetric"))
888 (mapcar (lambda (signer)
890 (epg-context-signers context)))))
892 (mapcar (lambda (recipient)
893 (list "-r" recipient))
895 (if (epg-data-file plain)
896 (list (epg-data-file plain)))))
898 (epg-wait-for-status context '("BEGIN_SIGNING"))
899 (if (null recipients)
900 (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
901 (if (and (epg-data-string plain)
902 (eq (process-status (epg-context-process context)) 'run))
903 (process-send-string (epg-context-process context)
904 (epg-data-string plain))))
907 (defun epg-encrypt-file (context plain recipients
908 cipher &optional sign always-trust)
909 "Encrypt a file PLAIN and store the result to a file CIPHER.
910 If CIPHER is nil, it returns the result as a string.
911 If RECIPIENTS is nil, it performs symmetric encryption."
915 (epg-context-set-output-file context cipher)
916 (epg-context-set-output-file context
917 (epg-make-temp-file "epg-output")))
918 (epg-start-encrypt context (epg-make-data-from-file plain)
919 recipients sign always-trust)
920 (epg-wait-for-completion context)
921 (if (epg-context-result-for context 'error)
922 (error "Encrypt failed"))
924 (epg-read-output context)))
926 (epg-delete-output-file context))
927 (epg-reset context)))
930 (defun epg-encrypt-string (context plain recipients
931 &optional sign always-trust)
932 "Encrypt a string PLAIN.
933 If RECIPIENTS is nil, it performs symmetric encryption."
936 (epg-context-set-output-file context
937 (epg-make-temp-file "epg-output"))
938 (epg-start-encrypt context (epg-make-data-from-string plain)
939 recipients sign always-trust)
940 (epg-wait-for-completion context)
941 (if (epg-context-result-for context 'error)
942 (error "Encrypt failed"))
943 (epg-read-output context))
944 (epg-delete-output-file context)
945 (epg-reset context)))
948 (defun epg-start-export-keys (context pattern)
949 "Initiate an export keys operation.
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-export-keys' instead."
956 (epg-context-set-result context nil)
957 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
958 (epg-start context (list "--export" pattern)))
961 (defun epg-export-keys (context pattern)
962 "Extract public keys matched with PATTERN and return them."
965 (epg-start-export-keys context pattern)
966 (epg-wait-for-completion context)
967 (if (epg-context-result-for context 'error)
968 (error "Export keys failed"))
969 (epg-read-output context))
970 (epg-reset context)))
973 (defun epg-start-import-keys (context keys)
974 "Initiate an import keys operation.
975 KEYS is a data object.
977 If you use this function, you will need to wait for the completion of
978 `epg-gpg-program' by using `epg-wait-for-completion' and call
979 `epg-reset' to clear a temporaly output file.
980 If you are unsure, use synchronous version of this function
981 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
982 (epg-context-set-result context nil)
983 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
984 (epg-start context (append (list "--import") (epg-data-file keys)))
985 (if (and (epg-data-string keys)
986 (eq (process-status (epg-context-process context)) 'run))
987 (process-send-string (epg-context-process context)
988 (epg-data-string keys))))
990 (defun epg-import-keys-1 (context keys)
993 (epg-start-import-keys context keys)
994 (epg-wait-for-completion context)
995 (if (epg-context-result-for context 'error)
996 (error "Import keys failed"))
997 (epg-read-output context))
998 (epg-reset context)))
1001 (defun epg-import-keys-from-file (context keys)
1002 "Add keys from a file KEYS."
1003 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1006 (defun epg-import-keys-from-string (context keys)
1007 "Add keys from a string KEYS."
1008 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1012 ;;; epg.el ends here