1 ;;; epg.el --- the EasyPG Library
2 ;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
3 ;; 2005, 2006 Free Software Foundation, Inc.
4 ;; Copyright (C) 2006 Daiki Ueno
6 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: PGP, GnuPG
9 ;; This file is part of EasyPG.
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
31 (defcustom epg-gpg-program "gpg"
32 "The `gpg' executable."
36 (defconst epg-version-number "0.0.0")
38 (defvar epg-user-id nil
39 "GnuPG ID of your default identity.")
41 (defvar epg-user-id-alist nil
42 "An alist mapping from key ID to user ID.")
44 (defvar epg-read-point nil)
45 (defvar epg-pending-status-list nil)
46 (defvar epg-key-id nil)
47 (defvar epg-context nil)
48 (defvar epg-debug nil)
49 (defvar epg-debug-buffer nil)
51 ;; from gnupg/include/cipher.h
52 (defconst epg-cipher-algorithm-alist
64 ;; from gnupg/include/cipher.h
65 (defconst epg-pubkey-algorithm-alist
73 ;; from gnupg/include/cipher.h
74 (defconst epg-digest-algorithm-alist
82 ;; from gnupg/include/cipher.h
83 (defconst epg-compress-algorithm-alist
89 (defconst epg-invalid-recipients-alist
90 '((0 . "No specific reason given")
92 (2 . "Ambigious specification")
93 (3 . "Wrong key usage")
98 (8 . "Policy mismatch")
99 (9 . "Not a secret key")
100 (10 . "Key not trusted")))
102 (defconst epg-delete-problem-alist
103 '((1 . "No such key")
104 (2 . "Must delete secret key first")
105 (3 . "Ambigious specification")))
107 (defvar epg-key-validity-alist
120 (defvar epg-key-capablity-alist
124 (?a . authentication)))
126 (defvar epg-prompt-alist nil)
128 (defun epg-make-data-from-file (file)
129 "Make a data object from FILE."
132 (defun epg-make-data-from-string (string)
133 "Make a data object from STRING."
136 (defun epg-data-file (data)
137 "Return the file of DATA."
140 (defun epg-data-string (data)
141 "Return the string of DATA."
144 (defun epg-make-context (&optional protocol armor textmode include-certs
145 cipher-algorithm digest-algorithm
147 "Return a context object."
148 (vector protocol armor textmode include-certs
149 cipher-algorithm digest-algorithm compress-algorithm
150 #'epg-passphrase-callback-function
151 #'epg-progress-callback-function
154 (defun epg-context-protocol (context)
155 "Return the protocol used within CONTEXT."
158 (defun epg-context-armor (context)
159 "Return t if the output shouled be ASCII armored in CONTEXT."
162 (defun epg-context-textmode (context)
163 "Return t if canonical text mode should be used in CONTEXT."
166 (defun epg-context-include-certs (context)
167 "Return how many certificates should be included in an S/MIME signed
171 (defun epg-context-cipher-algorithm (context)
172 "Return the cipher algorithm in CONTEXT."
175 (defun epg-context-digest-algorithm (context)
176 "Return the digest algorithm in CONTEXT."
179 (defun epg-context-compress-algorithm (context)
180 "Return the compress algorithm in CONTEXT."
183 (defun epg-context-passphrase-callback (context)
184 "Return the function used to query passphrase."
187 (defun epg-context-progress-callback (context)
188 "Return the function which handles progress update."
191 (defun epg-context-signers (context)
192 "Return the list of key-id for singning."
195 (defun epg-context-process (context)
196 "Return the process object of `epg-gpg-program'.
197 This function is for internal use only."
200 (defun epg-context-output-file (context)
201 "Return the output file of `epg-gpg-program'.
202 This function is for internal use only."
205 (defun epg-context-result (context)
206 "Return the result of the previous cryptographic operation."
209 (defun epg-context-set-protocol (context protocol)
210 "Set the protocol used within CONTEXT."
211 (aset context 0 protocol))
213 (defun epg-context-set-armor (context armor)
214 "Specify if the output shouled be ASCII armored in CONTEXT."
215 (aset context 1 armor))
217 (defun epg-context-set-textmode (context textmode)
218 "Specify if canonical text mode should be used in CONTEXT."
219 (aset context 2 textmode))
221 (defun epg-context-set-include-certs (context include-certs)
222 "Set how many certificates should be included in an S/MIME signed message."
223 (aset context 3 include-certs))
225 (defun epg-context-set-cipher-algorithm (context cipher-algorithm)
226 "Set the cipher algorithm in CONTEXT."
227 (aset context 4 cipher-algorithm))
229 (defun epg-context-set-digest-algorithm (context digest-algorithm)
230 "Set the digest algorithm in CONTEXT."
231 (aset context 5 digest-algorithm))
233 (defun epg-context-set-compress-algorithm (context compress-algorithm)
234 "Set the compress algorithm in CONTEXT."
235 (aset context 6 compress-algorithm))
237 (defun epg-context-set-passphrase-callback (context
239 "Set the function used to query passphrase."
240 (aset context 7 passphrase-callback))
242 (defun epg-context-set-progress-callback (context progress-callback)
243 "Set the function which handles progress update."
244 (aset context 8 progress-callback))
246 (defun epg-context-set-signers (context signers)
247 "Set the list of key-id for singning."
248 (aset context 9 signers))
250 (defun epg-context-set-process (context process)
251 "Set the process object of `epg-gpg-program'.
252 This function is for internal use only."
253 (aset context 10 process))
255 (defun epg-context-set-output-file (context output-file)
256 "Set the output file of `epg-gpg-program'.
257 This function is for internal use only."
258 (aset context 11 output-file))
260 (defun epg-context-set-result (context result)
261 "Set the result of the previous cryptographic operation."
262 (aset context 12 result))
264 (defun epg-make-signature (status key-id user-id)
265 "Return a signature object."
266 (vector status key-id user-id nil nil))
268 (defun epg-signature-status (signature)
269 "Return the status code of SIGNATURE."
272 (defun epg-signature-key-id (signature)
273 "Return the key-id of SIGNATURE."
276 (defun epg-signature-user-id (signature)
277 "Return the user-id of SIGNATURE."
280 (defun epg-signature-validity (signature)
281 "Return the validity of SIGNATURE."
284 (defun epg-signature-fingerprint (signature)
285 "Return the fingerprint of SIGNATURE."
288 (defun epg-signature-set-status (signature status)
289 "Set the status code of SIGNATURE."
290 (aset signature 0 status))
292 (defun epg-signature-set-key-id (signature key-id)
293 "Set the key-id of SIGNATURE."
294 (aset signature 1 key-id))
296 (defun epg-signature-set-user-id (signature user-id)
297 "Set the user-id of SIGNATURE."
298 (aset signature 2 user-id))
300 (defun epg-signature-set-validity (signature validity)
301 "Set the validity of SIGNATURE."
302 (aset signature 3 validity))
304 (defun epg-signature-set-fingerprint (signature fingerprint)
305 "Set the fingerprint of SIGNATURE."
306 (aset signature 4 fingerprint))
308 (defun epg-make-key (owner-trust)
309 "Return a key object."
310 (vector owner-trust nil nil))
312 (defun epg-key-owner-trust (key)
313 "Return the owner trust of KEY."
316 (defun epg-key-sub-key-list (key)
317 "Return the sub key list of KEY."
320 (defun epg-key-user-id-list (key)
321 "Return the user ID list of KEY."
324 (defun epg-key-set-sub-key-list (key sub-key-list)
325 "Set the sub key list of KEY."
326 (aset key 1 sub-key-list))
328 (defun epg-key-set-user-id-list (key user-id-list)
329 "Set the user ID list of KEY."
330 (aset key 2 user-id-list))
332 (defun epg-make-sub-key (validity capability secret algorithm length id
333 creation-time expiration-time)
334 "Return a sub key object."
335 (vector validity capability secret algorithm length id creation-time
336 expiration-time nil))
338 (defun epg-sub-key-validity (sub-key)
339 "Return the validity of SUB-KEY."
342 (defun epg-sub-key-capability (sub-key)
343 "Return the capability of SUB-KEY."
346 (defun epg-sub-key-secret (sub-key)
347 "Return non-nil if SUB-KEY is a secret key."
350 (defun epg-sub-key-algorithm (sub-key)
351 "Return the algorithm of SUB-KEY."
354 (defun epg-sub-key-length (sub-key)
355 "Return the length of SUB-KEY."
358 (defun epg-sub-key-id (sub-key)
359 "Return the ID of SUB-KEY."
362 (defun epg-sub-key-creation-time (sub-key)
363 "Return the creation time of SUB-KEY."
366 (defun epg-sub-key-expiration-time (sub-key)
367 "Return the expiration time of SUB-KEY."
370 (defun epg-sub-key-fingerprint (sub-key)
371 "Return the fingerprint of SUB-KEY."
374 (defun epg-sub-key-set-fingerprint (sub-key fingerprint)
375 "Set the fingerprint of SUB-KEY.
376 This function is for internal use only."
377 (aset sub-key 8 fingerprint))
379 (defun epg-make-user-id (validity name)
380 "Return a user ID object."
381 (vector validity name nil))
383 (defun epg-user-id-validity (user-id)
384 "Return the validity of USER-ID."
387 (defun epg-user-id-name (user-id)
388 "Return the name of USER-ID."
391 (defun epg-user-id-signature-list (user-id)
392 "Return the signature list of USER-ID."
395 (defun epg-user-id-set-signature-list (user-id signature-list)
396 "Set the signature list of USER-ID."
397 (aset user-id 2 signature-list))
399 (defun epg-context-result-for (context name)
400 (cdr (assq name (epg-context-result context))))
402 (defun epg-context-set-result-for (context name value)
403 (let* ((result (epg-context-result context))
404 (entry (assq name result)))
407 (epg-context-set-result context (cons (cons name value) result)))))
409 (defun epg-signature-to-string (signature)
410 (format "%s signature from %s %s%s"
411 (capitalize (symbol-name (epg-signature-status signature)))
412 (epg-signature-key-id signature)
413 (epg-signature-user-id signature)
414 (if (epg-signature-validity signature)
415 (format " (trust %s)"
416 (epg-signature-validity signature))
419 (defun epg-verify-result-to-string (verify-result)
420 (mapconcat #'epg-signature-to-string verify-result "\n"))
422 (defun epg-start (context args)
423 "Start `epg-gpg-program' in a subprocess with given ARGS."
424 (let* ((args (append (list "--no-tty"
428 (if (epg-context-armor context) '("--armor"))
429 (if (epg-context-textmode context) '("--textmode"))
430 (if (epg-context-output-file context)
431 (list "--output" (epg-context-output-file context)))
433 (coding-system-for-write 'binary)
434 process-connection-type
435 (orig-mode (default-file-modes))
436 (buffer (generate-new-buffer " *epg*"))
440 (unless epg-debug-buffer
441 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
442 (set-buffer epg-debug-buffer)
443 (goto-char (point-max))
444 (insert (format "%s %s\n" epg-gpg-program
445 (mapconcat #'identity args " ")))))
446 (with-current-buffer buffer
447 (make-local-variable 'epg-read-point)
448 (setq epg-read-point (point-min))
449 (make-local-variable 'epg-pending-status-list)
450 (setq epg-pending-status-list nil)
451 (make-local-variable 'epg-key-id)
452 (setq epg-key-id nil)
453 (make-local-variable 'epg-context)
454 (setq epg-context context))
457 (set-default-file-modes 448)
459 (apply #'start-process "epg" buffer epg-gpg-program args)))
460 (set-default-file-modes orig-mode))
461 (set-process-filter process #'epg-process-filter)
462 (epg-context-set-process context process)))
464 (defun epg-process-filter (process input)
467 (unless epg-debug-buffer
468 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
469 (set-buffer epg-debug-buffer)
470 (goto-char (point-max))
472 (if (buffer-live-p (process-buffer process))
474 (set-buffer (process-buffer process))
475 (goto-char (point-max))
477 (goto-char epg-read-point)
479 (while (looking-at ".*\n") ;the input line finished
481 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
482 (let* ((status (match-string 1))
483 (string (match-string 2))
484 (symbol (intern-soft (concat "epg-status-" status))))
485 (if (member status epg-pending-status-list)
486 (setq epg-pending-status-list nil))
489 (funcall symbol process string)))))
491 (setq epg-read-point (point)))))
493 (defun epg-read-output (context)
495 (if (fboundp 'set-buffer-multibyte)
496 (set-buffer-multibyte nil))
497 (if (file-exists-p (epg-context-output-file context))
498 (let ((coding-system-for-read (if (epg-context-textmode context)
501 (insert-file-contents (epg-context-output-file context))
504 (defun epg-wait-for-status (context status-list)
505 (with-current-buffer (process-buffer (epg-context-process context))
506 (setq epg-pending-status-list status-list)
507 (while (and (eq (process-status (epg-context-process context)) 'run)
508 epg-pending-status-list)
509 (accept-process-output (epg-context-process context) 1))))
511 (defun epg-wait-for-completion (context)
512 (while (eq (process-status (epg-context-process context)) 'run)
513 ;; We can't use accept-process-output instead of sit-for here
514 ;; because it may cause an interrupt during the sentinel execution.
517 (defun epg-flush (context)
518 (if (eq (process-status (epg-context-process context)) 'run)
519 (process-send-eof (epg-context-process context))))
521 (defun epg-reset (context)
522 (if (and (epg-context-process context)
523 (buffer-live-p (process-buffer (epg-context-process context))))
524 (kill-buffer (process-buffer (epg-context-process context))))
525 (epg-context-set-process context nil))
527 (defun epg-delete-output-file (context)
528 (if (and (epg-context-output-file context)
529 (file-exists-p (epg-context-output-file context)))
530 (delete-file (epg-context-output-file context))))
532 (defun epg-status-USERID_HINT (process string)
533 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
534 (let* ((key-id (match-string 1 string))
535 (user-id (match-string 2 string))
536 (entry (assoc key-id epg-user-id-alist)))
538 (setcdr entry user-id)
539 (setq epg-user-id-alist (cons (cons key-id user-id)
540 epg-user-id-alist))))))
542 (defun epg-status-NEED_PASSPHRASE (process string)
543 (if (string-match "\\`\\([^ ]+\\)" string)
544 (setq epg-key-id (match-string 1 string))))
546 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
547 (setq epg-key-id 'SYM))
549 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
550 (setq epg-key-id 'PIN))
552 (defun epg-status-GET_HIDDEN (process string)
554 (string-match "\\`passphrase\\." string))
557 passphrase-with-new-line)
563 (if (consp (epg-context-passphrase-callback
565 (car (epg-context-passphrase-callback
567 (epg-context-passphrase-callback epg-context))
569 (if (consp (epg-context-passphrase-callback
571 (cdr (epg-context-passphrase-callback
574 (setq passphrase-with-new-line (concat passphrase "\n"))
575 (fillarray passphrase 0)
576 (setq passphrase nil)
577 (process-send-string process passphrase-with-new-line)))
579 (epg-context-set-result-for
582 (epg-context-result-for epg-context 'error)))
583 (delete-process process)))
585 (fillarray passphrase 0))
586 (if passphrase-with-new-line
587 (fillarray passphrase-with-new-line 0))))))
589 (defun epg-status-GET_BOOL (process string)
590 (let ((entry (assoc string epg-prompt-alist))
593 (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
594 (process-send-string process "y\n")
595 (process-send-string process "n\n"))
597 (epg-context-set-result-for
600 (epg-context-result-for epg-context 'error)))
601 (delete-process process)))))
603 (defun epg-status-GET_LINE (process string)
604 (let ((entry (assoc string epg-prompt-alist))
609 (concat (read-string (if entry (cdr entry) (concat string ": ")))
612 (epg-context-set-result-for
615 (epg-context-result-for epg-context 'error)))
616 (delete-process process)))))
618 (defun epg-status-GOODSIG (process string)
619 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
620 (epg-context-set-result-for
623 (cons (epg-make-signature 'good
624 (match-string 1 string)
625 (match-string 2 string))
626 (epg-context-result-for epg-context 'verify)))))
628 (defun epg-status-EXPSIG (process string)
629 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
630 (epg-context-set-result-for
633 (cons (epg-make-signature 'expired
634 (match-string 1 string)
635 (match-string 2 string))
636 (epg-context-result-for epg-context 'verify)))))
638 (defun epg-status-EXPKEYSIG (process string)
639 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
640 (epg-context-set-result-for
643 (cons (epg-make-signature 'expired-key
644 (match-string 1 string)
645 (match-string 2 string))
646 (epg-context-result-for epg-context 'verify)))))
648 (defun epg-status-REVKEYSIG (process string)
649 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
650 (epg-context-set-result-for
653 (cons (epg-make-signature 'revoked-key
654 (match-string 1 string)
655 (match-string 2 string))
656 (epg-context-result-for epg-context 'verify)))))
658 (defun epg-status-BADSIG (process string)
659 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
660 (epg-context-set-result-for
663 (cons (epg-make-signature 'bad
664 (match-string 1 string)
665 (match-string 2 string))
666 (epg-context-result-for epg-context 'verify)))))
668 (defun epg-status-VALIDSIG (process string)
669 (let ((signature (car (epg-context-result-for epg-context 'verify))))
671 (eq (epg-signature-status signature) 'good)
672 (string-match "\\`\\([^ ]+\\) " string))
673 (epg-signature-set-fingerprint signature (match-string 1 string)))))
675 (defun epg-status-TRUST_UNDEFINED (process string)
676 (let ((signature (car (epg-context-result-for epg-context 'verify))))
678 (eq (epg-signature-status signature) 'good))
679 (epg-signature-set-validity signature 'undefined))))
681 (defun epg-status-TRUST_NEVER (process string)
682 (let ((signature (car (epg-context-result-for epg-context 'verify))))
684 (eq (epg-signature-status signature) 'good))
685 (epg-signature-set-validity signature 'never))))
687 (defun epg-status-TRUST_MARGINAL (process string)
688 (let ((signature (car (epg-context-result-for epg-context 'verify))))
690 (eq (epg-signature-status signature) 'marginal))
691 (epg-signature-set-validity signature 'marginal))))
693 (defun epg-status-TRUST_FULLY (process string)
694 (let ((signature (car (epg-context-result-for epg-context 'verify))))
696 (eq (epg-signature-status signature) 'good))
697 (epg-signature-set-validity signature 'full))))
699 (defun epg-status-TRUST_ULTIMATE (process string)
700 (let ((signature (car (epg-context-result-for epg-context 'verify))))
702 (eq (epg-signature-status signature) 'good))
703 (epg-signature-set-validity signature 'ultimate))))
705 (defun epg-status-PROGRESS (process string)
706 (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
708 (funcall (if (consp (epg-context-progress-callback epg-context))
709 (car (epg-context-progress-callback epg-context))
710 (epg-context-progress-callback epg-context))
711 (match-string 1 string)
712 (match-string 2 string)
713 (string-to-number (match-string 3 string))
714 (string-to-number (match-string 4 string))
715 (if (consp (epg-context-progress-callback epg-context))
716 (cdr (epg-context-progress-callback epg-context))))))
718 (defun epg-status-DECRYPTION_FAILED (process string)
719 (epg-context-set-result-for
721 (cons 'decryption-failed
722 (epg-context-result-for epg-context 'error))))
724 (defun epg-status-NODATA (process string)
725 (epg-context-set-result-for
727 (cons (cons 'no-data (string-to-number string))
728 (epg-context-result-for epg-context 'error))))
730 (defun epg-status-UNEXPECTED (process string)
731 (epg-context-set-result-for
733 (cons (cons 'unexpected (string-to-number string))
734 (epg-context-result-for epg-context 'error))))
736 (defun epg-status-KEYEXPIRED (process string)
737 (epg-context-set-result-for
739 (cons (cons 'key-expired string)
740 (epg-context-result-for epg-context 'error))))
742 (defun epg-status-KEYREVOKED (process string)
743 (epg-context-set-result-for
746 (epg-context-result-for epg-context 'error))))
748 (defun epg-status-BADARMOR (process string)
749 (epg-context-set-result-for
752 (epg-context-result-for epg-context 'error))))
754 (defun epg-status-INV_RECP (process string)
755 (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
756 (epg-context-set-result-for
758 (cons (list 'invalid-recipient
759 (string-to-number (match-string 1 string))
760 (match-string 2 string))
761 (epg-context-result-for epg-context 'error)))))
763 (defun epg-status-NO_RECP (process string)
764 (epg-context-set-result-for
767 (epg-context-result-for epg-context 'error))))
769 (defun epg-status-DELETE_PROBLEM (process string)
770 (if (string-match "\\`\\([0-9]+\\)" string)
771 (epg-context-set-result-for
773 (cons (cons 'delete-problem (string-to-number (match-string 1 string)))
774 (epg-context-result-for epg-context 'error)))))
776 (defun epg-status-SIG_CREATED (process string)
777 (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
778 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
779 (epg-context-set-result-for
781 (cons (list (cons 'type (string-to-char (match-string 1 string)))
782 (cons 'pubkey-algorithm
783 (string-to-number (match-string 2 string)))
784 (cons 'digest-algorithm
785 (string-to-number (match-string 3 string)))
786 (cons 'class (string-to-number (match-string 4 string) 16))
787 (cons 'creation-time (match-string 5 string))
788 (cons 'fingerprint (substring string (match-end 0))))
789 (epg-context-result-for epg-context 'sign)))))
791 (defun epg-passphrase-callback-function (key-id handback)
794 "Passphrase for symmetric encryption: "
796 "Passphrase for PIN: "
797 (let ((entry (assoc key-id epg-user-id-alist)))
799 (format "Passphrase for %s %s: " key-id (cdr entry))
800 (format "Passphrase for %s: " key-id)))))))
802 (defun epg-progress-callback-function (what char current total handback)
803 (message "%s: %d%%/%d%%" what current total))
805 (defun epg-configuration ()
806 "Return a list of internal configuration parameters of `epg-gpg-program'."
809 (apply #'call-process epg-gpg-program nil (list t nil) nil
810 '("--with-colons" "--list-config"))
811 (goto-char (point-min))
812 (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
813 (setq type (intern (match-string 1))
814 config (cons (cons type
816 '(pubkey cipher digest compress))
817 (mapcar #'string-to-number
818 (delete "" (split-string
825 (defun epg-list-keys-1 (name mode)
826 (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
827 "--fixed-list-mode" "--with-fingerprint"
829 (if mode "--list-secret-keys" "--list-keys"))
830 (if name (list name))))
831 keys string field index)
833 (apply #'call-process epg-gpg-program nil (list t nil) nil args)
834 (goto-char (point-min))
835 (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
836 (setq keys (cons (make-vector 15 nil) keys)
837 string (match-string 0)
841 (string-match "\\([^:]+\\)?:" string index))
842 (setq index (match-end 0))
843 (aset (car keys) field (match-string 1 string))
844 (setq field (1+ field))))
847 (defun epg-make-sub-key-1 (line)
850 (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
852 (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
854 (member (aref line 0) '("sec" "ssb"))
855 (string-to-number (aref line 3))
856 (string-to-number (aref line 2))
861 (defun epg-list-keys (&optional name mode)
862 (let ((lines (epg-list-keys-1 name mode))
866 ((member (aref (car lines) 0) '("pub" "sec"))
868 (epg-key-set-sub-key-list
870 (nreverse (epg-key-sub-key-list (car keys))))
871 (epg-key-set-user-id-list
873 (nreverse (epg-key-user-id-list (car keys)))))
874 (setq keys (cons (epg-make-key
875 (if (aref (car lines) 8)
876 (cdr (assq (string-to-char (aref (car lines) 8))
877 epg-key-validity-alist))))
879 (epg-key-set-sub-key-list
881 (cons (epg-make-sub-key-1 (car lines))
882 (epg-key-sub-key-list (car keys)))))
883 ((member (aref (car lines) 0) '("sub" "ssb"))
884 (epg-key-set-sub-key-list
886 (cons (epg-make-sub-key-1 (car lines))
887 (epg-key-sub-key-list (car keys)))))
888 ((equal (aref (car lines) 0) "uid")
889 (epg-key-set-user-id-list
891 (cons (epg-make-user-id
892 (if (aref (car lines) 1)
893 (cdr (assq (string-to-char (aref (car lines) 1))
894 epg-key-validity-alist)))
895 (aref (car lines) 9))
896 (epg-key-user-id-list (car keys)))))
897 ((equal (aref (car lines) 0) "fpr")
898 (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
899 (aref (car lines) 9))))
900 (setq lines (cdr lines)))
903 (if (fboundp 'make-temp-file)
904 (defalias 'epg-make-temp-file 'make-temp-file)
905 ;; stolen from poe.el.
906 (defun epg-make-temp-file (prefix)
907 "Create a temporary file.
908 The returned file name (created by appending some random characters at the end
909 of PREFIX, and expanding against `temporary-file-directory' if necessary),
910 is guaranteed to point to a newly created empty file.
911 You can then use `write-region' to write new data into the file."
912 (let (tempdir tempfile)
915 ;; First, create a temporary directory.
916 (while (condition-case ()
918 (setq tempdir (make-temp-name
920 (file-name-directory prefix)
922 ;; return nil or signal an error.
923 (make-directory tempdir))
925 (file-already-exists t)))
926 (set-file-modes tempdir 448)
927 ;; Second, create a temporary file in the tempdir.
928 ;; There *is* a race condition between `make-temp-name'
929 ;; and `write-region', but we don't care it since we are
930 ;; in a private directory now.
931 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
932 (write-region "" nil tempfile nil 'silent)
933 (set-file-modes tempfile 384)
934 ;; Finally, make a hard-link from the tempfile.
935 (while (condition-case ()
937 (setq file (make-temp-name prefix))
938 ;; return nil or signal an error.
939 (add-name-to-file tempfile file))
941 (file-already-exists t)))
943 ;; Cleanup the tempfile.
945 (file-exists-p tempfile)
946 (delete-file tempfile))
947 ;; Cleanup the tempdir.
949 (file-directory-p tempdir)
950 (delete-directory tempdir))))))
953 (defun epg-start-decrypt (context cipher)
954 "Initiate a decrypt operation on CIPHER.
955 CIPHER is a data object.
957 If you use this function, you will need to wait for the completion of
958 `epg-gpg-program' by using `epg-wait-for-completion' and call
959 `epg-reset' to clear a temporaly output file.
960 If you are unsure, use synchronous version of this function
961 `epg-decrypt-file' or `epg-decrypt-string' instead."
962 (unless (epg-data-file cipher)
963 (error "Not a file"))
964 (epg-context-set-result context nil)
965 (epg-start context (list "--decrypt" (epg-data-file cipher)))
966 (epg-wait-for-status context '("BEGIN_DECRYPTION")))
969 (defun epg-decrypt-file (context cipher plain)
970 "Decrypt a file CIPHER and store the result to a file PLAIN.
971 If PLAIN is nil, it returns the result as a string."
975 (epg-context-set-output-file context plain)
976 (epg-context-set-output-file context
977 (epg-make-temp-file "epg-output")))
978 (epg-start-decrypt context (epg-make-data-from-file cipher))
979 (epg-wait-for-completion context)
980 (if (epg-context-result-for context 'error)
981 (error "Decrypt failed: %S"
982 (epg-context-result-for context 'error)))
984 (epg-read-output context)))
986 (epg-delete-output-file context))
987 (epg-reset context)))
990 (defun epg-decrypt-string (context cipher)
991 "Decrypt a string CIPHER and return the plain text."
992 (let ((input-file (epg-make-temp-file "epg-input"))
993 (coding-system-for-write 'binary))
996 (write-region cipher nil input-file nil 'quiet)
997 (epg-context-set-output-file context
998 (epg-make-temp-file "epg-output"))
999 (epg-start-decrypt context (epg-make-data-from-file input-file))
1001 (epg-wait-for-completion context)
1002 (if (epg-context-result-for context 'error)
1003 (error "Decrypt failed: %S"
1004 (epg-context-result-for context 'error)))
1005 (epg-read-output context))
1006 (epg-delete-output-file context)
1007 (if (file-exists-p input-file)
1008 (delete-file input-file))
1009 (epg-reset context))))
1012 (defun epg-start-verify (context signature &optional signed-text)
1013 "Initiate a verify operation on SIGNATURE.
1014 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
1016 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
1017 For a normal or a clear text signature, SIGNED-TEXT should be nil.
1019 If you use this function, you will need to wait for the completion of
1020 `epg-gpg-program' by using `epg-wait-for-completion' and call
1021 `epg-reset' to clear a temporaly output file.
1022 If you are unsure, use synchronous version of this function
1023 `epg-verify-file' or `epg-verify-string' instead."
1024 (epg-context-set-result context nil)
1026 ;; Detached signature.
1027 (if (epg-data-file signed-text)
1028 (epg-start context (list "--verify" (epg-data-file signature)
1029 (epg-data-file signed-text)))
1030 (epg-start context (list "--verify" (epg-data-file signature) "-"))
1031 (if (eq (process-status (epg-context-process context)) 'run)
1032 (process-send-string (epg-context-process context)
1033 (epg-data-string signed-text))))
1034 ;; Normal (or cleartext) signature.
1035 (if (epg-data-file signature)
1036 (epg-start context (list "--verify" (epg-data-file signature)))
1037 (epg-start context (list "--verify"))
1038 (if (eq (process-status (epg-context-process context)) 'run)
1039 (process-send-string (epg-context-process context)
1040 (epg-data-string signature))))))
1043 (defun epg-verify-file (context signature &optional signed-text plain)
1044 "Verify a file SIGNATURE.
1045 SIGNED-TEXT and PLAIN are also a file if they are specified.
1047 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1048 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1052 (epg-context-set-output-file context plain)
1053 (epg-context-set-output-file context
1054 (epg-make-temp-file "epg-output")))
1056 (epg-start-verify context
1057 (epg-make-data-from-file signature)
1058 (epg-make-data-from-file signed-text))
1059 (epg-start-verify context
1060 (epg-make-data-from-file signature)))
1061 (epg-wait-for-completion context)
1063 (epg-read-output context)))
1065 (epg-delete-output-file context))
1066 (epg-reset context)))
1069 (defun epg-verify-string (context signature &optional signed-text)
1070 "Verify a string SIGNATURE.
1071 SIGNED-TEXT is a string if it is specified.
1073 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1074 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1075 (let ((coding-system-for-write 'binary)
1079 (epg-context-set-output-file context
1080 (epg-make-temp-file "epg-output"))
1083 (setq input-file (epg-make-temp-file "epg-signature"))
1084 (write-region signature nil input-file nil 'quiet)
1085 (epg-start-verify context
1086 (epg-make-data-from-file input-file)
1087 (epg-make-data-from-string signed-text)))
1088 (epg-start-verify context (epg-make-data-from-string signature)))
1090 (epg-wait-for-completion context)
1091 (epg-read-output context))
1092 (epg-delete-output-file context)
1094 (file-exists-p input-file))
1095 (delete-file input-file))
1096 (epg-reset context))))
1099 (defun epg-start-sign (context plain &optional mode)
1100 "Initiate a sign operation on PLAIN.
1101 PLAIN is a data object.
1103 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1104 If MODE is t or 'detached, it makes a detached signature.
1105 Otherwise, it makes a normal signature.
1107 If you use this function, you will need to wait for the completion of
1108 `epg-gpg-program' by using `epg-wait-for-completion' and call
1109 `epg-reset' to clear a temporaly output file.
1110 If you are unsure, use synchronous version of this function
1111 `epg-sign-file' or `epg-sign-string' instead."
1112 (epg-context-set-result context nil)
1114 (append (list (if (eq mode 'clearsign)
1116 (if (or (eq mode t) (eq mode 'detached))
1124 (car (epg-key-sub-key-list signer)))))
1125 (epg-context-signers context)))
1126 (if (epg-data-file plain)
1127 (list (epg-data-file plain)))))
1128 (epg-wait-for-status context '("BEGIN_SIGNING"))
1129 (if (and (epg-data-string plain)
1130 (eq (process-status (epg-context-process context)) 'run))
1131 (process-send-string (epg-context-process context)
1132 (epg-data-string plain))))
1135 (defun epg-sign-file (context plain signature &optional mode)
1136 "Sign a file PLAIN and store the result to a file SIGNATURE.
1137 If SIGNATURE is nil, it returns the result as a string.
1138 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1139 If MODE is t or 'detached, it makes a detached signature.
1140 Otherwise, it makes a normal signature."
1144 (epg-context-set-output-file context signature)
1145 (epg-context-set-output-file context
1146 (epg-make-temp-file "epg-output")))
1147 (epg-start-sign context (epg-make-data-from-file plain) mode)
1148 (epg-wait-for-completion context)
1149 (if (epg-context-result-for context 'error)
1150 (error "Sign failed: %S"
1151 (epg-context-result-for context 'error)))
1153 (epg-read-output context)))
1155 (epg-delete-output-file context))
1156 (epg-reset context)))
1159 (defun epg-sign-string (context plain &optional mode)
1160 "Sign a string PLAIN and return the output as string.
1161 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1162 If MODE is t or 'detached, it makes a detached signature.
1163 Otherwise, it makes a normal signature."
1166 (epg-context-set-output-file context
1167 (epg-make-temp-file "epg-output"))
1168 (epg-start-sign context (epg-make-data-from-string plain) mode)
1170 (epg-wait-for-completion context)
1171 (if (epg-context-result-for context 'error)
1172 (error "Sign failed: %S"
1173 (epg-context-result-for context 'error)))
1174 (epg-read-output context))
1175 (epg-delete-output-file context)
1176 (epg-reset context)))
1179 (defun epg-start-encrypt (context plain recipients
1180 &optional sign always-trust)
1181 "Initiate an encrypt operation on PLAIN.
1182 PLAIN is a data object.
1183 If RECIPIENTS is nil, it performs symmetric encryption.
1185 If you use this function, you will need to wait for the completion of
1186 `epg-gpg-program' by using `epg-wait-for-completion' and call
1187 `epg-reset' to clear a temporaly output file.
1188 If you are unsure, use synchronous version of this function
1189 `epg-encrypt-file' or `epg-encrypt-string' instead."
1190 (epg-context-set-result context nil)
1192 (append (if always-trust '("--always-trust"))
1193 (if recipients '("--encrypt") '("--symmetric"))
1197 (mapcar (lambda (signer)
1199 (epg-context-signers context)))))
1205 (car (epg-key-sub-key-list recipient)))))
1207 (if (epg-data-file plain)
1208 (list (epg-data-file plain)))))
1210 (epg-wait-for-status context '("BEGIN_SIGNING"))
1211 (epg-wait-for-status context '("BEGIN_ENCRYPTION")))
1212 (if (and (epg-data-string plain)
1213 (eq (process-status (epg-context-process context)) 'run))
1214 (process-send-string (epg-context-process context)
1215 (epg-data-string plain))))
1218 (defun epg-encrypt-file (context plain recipients
1219 cipher &optional sign always-trust)
1220 "Encrypt a file PLAIN and store the result to a file CIPHER.
1221 If CIPHER is nil, it returns the result as a string.
1222 If RECIPIENTS is nil, it performs symmetric encryption."
1226 (epg-context-set-output-file context cipher)
1227 (epg-context-set-output-file context
1228 (epg-make-temp-file "epg-output")))
1229 (epg-start-encrypt context (epg-make-data-from-file plain)
1230 recipients sign always-trust)
1231 (epg-wait-for-completion context)
1232 (if (epg-context-result-for context 'error)
1233 (error "Encrypt failed: %S"
1234 (epg-context-result-for context 'error)))
1236 (epg-read-output context)))
1238 (epg-delete-output-file context))
1239 (epg-reset context)))
1242 (defun epg-encrypt-string (context plain recipients
1243 &optional sign always-trust)
1244 "Encrypt a string PLAIN.
1245 If RECIPIENTS is nil, it performs symmetric encryption."
1248 (epg-context-set-output-file context
1249 (epg-make-temp-file "epg-output"))
1250 (epg-start-encrypt context (epg-make-data-from-string plain)
1251 recipients sign always-trust)
1253 (epg-wait-for-completion context)
1254 (if (epg-context-result-for context 'error)
1255 (error "Encrypt failed: %S"
1256 (epg-context-result-for context 'error)))
1257 (epg-read-output context))
1258 (epg-delete-output-file context)
1259 (epg-reset context)))
1262 (defun epg-start-export-keys (context keys)
1263 "Initiate an export keys operation.
1265 If you use this function, you will need to wait for the completion of
1266 `epg-gpg-program' by using `epg-wait-for-completion' and call
1267 `epg-reset' to clear a temporaly output file.
1268 If you are unsure, use synchronous version of this function
1269 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1270 (epg-context-set-result context nil)
1271 (epg-start context (cons "--export"
1275 (car (epg-key-sub-key-list key))))
1279 (defun epg-export-keys-to-file (context keys file)
1280 "Extract public KEYS."
1284 (epg-context-set-output-file context file)
1285 (epg-context-set-output-file context
1286 (epg-make-temp-file "epg-output")))
1287 (epg-start-export-keys context keys)
1288 (epg-wait-for-completion context)
1289 (if (epg-context-result-for context 'error)
1290 (error "Export keys failed: %S"
1291 (epg-context-result-for context 'error)))
1293 (epg-read-output context)))
1295 (epg-delete-output-file context))
1296 (epg-reset context)))
1299 (defun epg-export-keys-to-string (context keys)
1300 "Extract public KEYS and return them as a string."
1301 (epg-export-keys-to-file context keys nil))
1304 (defun epg-start-import-keys (context keys)
1305 "Initiate an import keys operation.
1306 KEYS is a data object.
1308 If you use this function, you will need to wait for the completion of
1309 `epg-gpg-program' by using `epg-wait-for-completion' and call
1310 `epg-reset' to clear a temporaly output file.
1311 If you are unsure, use synchronous version of this function
1312 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1313 (epg-context-set-result context nil)
1314 (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1315 (epg-start context (list "--import" (epg-data-file keys)))
1316 (if (and (epg-data-string keys)
1317 (eq (process-status (epg-context-process context)) 'run))
1318 (process-send-string (epg-context-process context)
1319 (epg-data-string keys))))
1321 (defun epg-import-keys-1 (context keys)
1324 (epg-start-import-keys context keys)
1325 (if (epg-data-file keys)
1326 (epg-flush context))
1327 (epg-wait-for-completion context)
1328 (if (epg-context-result-for context 'error)
1329 (error "Import keys failed: %S"
1330 (epg-context-result-for context 'error)))
1331 (epg-read-output context))
1332 (epg-reset context)))
1335 (defun epg-import-keys-from-file (context keys)
1336 "Add keys from a file KEYS."
1337 (epg-import-keys-1 context (epg-make-data-from-file keys)))
1340 (defun epg-import-keys-from-string (context keys)
1341 "Add keys from a string KEYS."
1342 (epg-import-keys-1 context (epg-make-data-from-string keys)))
1345 (defun epg-start-delete-keys (context keys &optional allow-secret)
1346 "Initiate an delete keys operation.
1348 If you use this function, you will need to wait for the completion of
1349 `epg-gpg-program' by using `epg-wait-for-completion' and call
1350 `epg-reset' to clear a temporaly output file.
1351 If you are unsure, use synchronous version of this function
1352 `epg-delete-keys' instead."
1353 (epg-context-set-result context nil)
1354 (epg-start context (cons (if allow-secret
1355 "--delete-secret-key"
1360 (car (epg-key-sub-key-list key))))
1364 (defun epg-delete-keys (context keys &optional allow-secret)
1365 "Delete KEYS from the key ring."
1368 (epg-start-delete-keys context keys allow-secret)
1369 (epg-wait-for-completion context)
1370 (if (epg-context-result-for context 'error)
1371 (error "Delete keys failed: %S"
1372 (epg-context-result-for context 'error))))
1373 (epg-reset context)))
1376 (defun epg-start-sign-keys (context keys &optional local)
1377 "Initiate an sign keys operation.
1379 If you use this function, you will need to wait for the completion of
1380 `epg-gpg-program' by using `epg-wait-for-completion' and call
1381 `epg-reset' to clear a temporaly output file.
1382 If you are unsure, use synchronous version of this function
1383 `epg-sign-keys' instead."
1384 (epg-context-set-result context nil)
1385 (epg-start context (cons (if local
1391 (car (epg-key-sub-key-list key))))
1395 (defun epg-sign-keys (context keys &optional local)
1396 "Sign KEYS from the key ring."
1399 (epg-start-sign-keys context keys local)
1400 (epg-wait-for-completion context)
1401 (if (epg-context-result-for context 'error)
1402 (error "Sign keys failed: %S"
1403 (epg-context-result-for context 'error))))
1404 (epg-reset context)))
1408 ;;; epg.el ends here