pgg-pgp.el 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. ;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG.
  2. ;; Copyright (C) 1999-2000, 2002-2012 Free Software Foundation, Inc.
  3. ;; Author: Daiki Ueno <ueno@unixuser.org>
  4. ;; Created: 1999/11/02
  5. ;; Keywords: PGP, OpenPGP
  6. ;; Package: pgg
  7. ;; Obsolete-since: 24.1
  8. ;; This file is part of GNU Emacs.
  9. ;; GNU Emacs is free software: you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Code:
  20. (eval-when-compile
  21. (require 'cl) ; for pgg macros
  22. (require 'pgg))
  23. (defgroup pgg-pgp ()
  24. "PGP 2.* and 6.* interface."
  25. :group 'pgg)
  26. (defcustom pgg-pgp-program "pgp"
  27. "PGP 2.* and 6.* executable."
  28. :group 'pgg-pgp
  29. :type 'string)
  30. (defcustom pgg-pgp-shell-file-name "/bin/sh"
  31. "File name to load inferior shells from.
  32. Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
  33. :group 'pgg-pgp
  34. :type 'string)
  35. (defcustom pgg-pgp-shell-command-switch "-c"
  36. "Switch used to have the shell execute its command line argument."
  37. :group 'pgg-pgp
  38. :type 'string)
  39. (defcustom pgg-pgp-extra-args nil
  40. "Extra arguments for every PGP invocation."
  41. :group 'pgg-pgp
  42. :type '(choice
  43. (const :tag "None" nil)
  44. (string :tag "Arguments")))
  45. (defvar pgg-pgp-user-id nil
  46. "PGP ID of your default identity.")
  47. (defun pgg-pgp-process-region (start end passphrase program args)
  48. (let* ((errors-file-name (pgg-make-temp-file "pgg-errors"))
  49. (args
  50. (concat args
  51. pgg-pgp-extra-args
  52. " 2>" (shell-quote-argument errors-file-name)))
  53. (shell-file-name pgg-pgp-shell-file-name)
  54. (shell-command-switch pgg-pgp-shell-command-switch)
  55. (process-environment process-environment)
  56. (output-buffer pgg-output-buffer)
  57. (errors-buffer pgg-errors-buffer)
  58. (process-connection-type nil)
  59. process status exit-status)
  60. (with-current-buffer (get-buffer-create output-buffer)
  61. (buffer-disable-undo)
  62. (erase-buffer))
  63. (when passphrase
  64. (setenv "PGPPASSFD" "0"))
  65. (unwind-protect
  66. (progn
  67. (let ((coding-system-for-read 'binary)
  68. (coding-system-for-write 'binary))
  69. (setq process
  70. (start-process-shell-command "*PGP*" output-buffer
  71. (concat program " " args))))
  72. (set-process-sentinel process #'ignore)
  73. (when passphrase
  74. (process-send-string process (concat passphrase "\n")))
  75. (process-send-region process start end)
  76. (process-send-eof process)
  77. (while (eq 'run (process-status process))
  78. (accept-process-output process 5))
  79. (setq status (process-status process)
  80. exit-status (process-exit-status process))
  81. (delete-process process)
  82. (with-current-buffer output-buffer
  83. (pgg-convert-lbt-region (point-min)(point-max) 'LF)
  84. (if (memq status '(stop signal))
  85. (error "%s exited abnormally: '%s'" program exit-status))
  86. (if (= 127 exit-status)
  87. (error "%s could not be found" program))
  88. (set-buffer (get-buffer-create errors-buffer))
  89. (buffer-disable-undo)
  90. (erase-buffer)
  91. (insert-file-contents errors-file-name)))
  92. (if (and process (eq 'run (process-status process)))
  93. (interrupt-process process))
  94. (condition-case nil
  95. (delete-file errors-file-name)
  96. (file-error nil)))))
  97. (defun pgg-pgp-lookup-key (string &optional type)
  98. "Search keys associated with STRING."
  99. (let ((args (list "+batchmode" "+language=en" "-kv" string)))
  100. (with-current-buffer (get-buffer-create pgg-output-buffer)
  101. (buffer-disable-undo)
  102. (erase-buffer)
  103. (apply #'call-process pgg-pgp-program nil t nil args)
  104. (goto-char (point-min))
  105. (cond
  106. ((re-search-forward "^pub\\s +[0-9]+/" nil t);PGP 2.*
  107. (buffer-substring (point)(+ 8 (point))))
  108. ((re-search-forward "^Type" nil t);PGP 6.*
  109. (beginning-of-line 2)
  110. (substring
  111. (nth 2 (split-string
  112. (buffer-substring (point)(progn (end-of-line) (point)))))
  113. 2))))))
  114. (defun pgg-pgp-encrypt-region (start end recipients &optional sign passphrase)
  115. "Encrypt the current region between START and END."
  116. (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
  117. (passphrase (or passphrase
  118. (when sign
  119. (pgg-read-passphrase
  120. (format "PGP passphrase for %s: "
  121. pgg-pgp-user-id)
  122. pgg-pgp-user-id))))
  123. (args
  124. (concat
  125. "+encrypttoself=off +verbose=1 +batchmode +language=us -fate "
  126. (if (or recipients pgg-encrypt-for-me)
  127. (mapconcat 'shell-quote-argument
  128. (append recipients
  129. (if pgg-encrypt-for-me
  130. (list pgg-pgp-user-id))) " "))
  131. (if sign (concat " -s -u " (shell-quote-argument pgg-pgp-user-id))))))
  132. (pgg-pgp-process-region start end nil pgg-pgp-program args)
  133. (pgg-process-when-success nil)))
  134. (defun pgg-pgp-decrypt-region (start end &optional passphrase)
  135. "Decrypt the current region between START and END.
  136. If optional PASSPHRASE is not specified, it will be obtained from the
  137. passphrase cache or user."
  138. (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
  139. (key (pgg-pgp-lookup-key pgg-pgp-user-id 'encrypt))
  140. (passphrase
  141. (or passphrase
  142. (pgg-read-passphrase
  143. (format "PGP passphrase for %s: " pgg-pgp-user-id) key)))
  144. (args
  145. "+verbose=1 +batchmode +language=us -f"))
  146. (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
  147. (pgg-process-when-success
  148. (if pgg-cache-passphrase
  149. (pgg-add-passphrase-to-cache key passphrase)))))
  150. (defun pgg-pgp-sign-region (start end &optional clearsign passphrase)
  151. "Make detached signature from text between START and END.
  152. If optional PASSPHRASE is not specified, it will be obtained from the
  153. passphrase cache or user."
  154. (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
  155. (passphrase
  156. (or passphrase
  157. (pgg-read-passphrase
  158. (format "PGP passphrase for %s: " pgg-pgp-user-id)
  159. (pgg-pgp-lookup-key pgg-pgp-user-id 'sign))))
  160. (args
  161. (concat (if clearsign "-fast" "-fbast")
  162. " +verbose=1 +language=us +batchmode"
  163. " -u " (shell-quote-argument pgg-pgp-user-id))))
  164. (pgg-pgp-process-region start end passphrase pgg-pgp-program args)
  165. (pgg-process-when-success
  166. (goto-char (point-min))
  167. (when (re-search-forward "^-+BEGIN PGP" nil t);XXX
  168. (let ((packet
  169. (cdr (assq 2 (pgg-parse-armor-region
  170. (progn (beginning-of-line 2)
  171. (point))
  172. (point-max))))))
  173. (if pgg-cache-passphrase
  174. (pgg-add-passphrase-to-cache
  175. (cdr (assq 'key-identifier packet))
  176. passphrase)))))))
  177. (defun pgg-pgp-verify-region (start end &optional signature)
  178. "Verify region between START and END as the detached signature SIGNATURE."
  179. (let* ((orig-file (pgg-make-temp-file "pgg"))
  180. (args "+verbose=1 +batchmode +language=us")
  181. (orig-mode (default-file-modes)))
  182. (unwind-protect
  183. (progn
  184. (set-default-file-modes 448)
  185. (let ((coding-system-for-write 'binary)
  186. jka-compr-compression-info-list jam-zcat-filename-list)
  187. (write-region start end orig-file)))
  188. (set-default-file-modes orig-mode))
  189. (if (stringp signature)
  190. (progn
  191. (copy-file signature (setq signature (concat orig-file ".asc")))
  192. (setq args (concat args " " (shell-quote-argument signature)))))
  193. (setq args (concat args " " (shell-quote-argument orig-file)))
  194. (pgg-pgp-process-region (point)(point) nil pgg-pgp-program args)
  195. (delete-file orig-file)
  196. (if signature (delete-file signature))
  197. (pgg-process-when-success
  198. (goto-char (point-min))
  199. (let ((case-fold-search t))
  200. (while (re-search-forward "^warning: " nil t)
  201. (delete-region (match-beginning 0)
  202. (progn (beginning-of-line 2) (point)))))
  203. (goto-char (point-min))
  204. (when (re-search-forward "^\\.$" nil t)
  205. (delete-region (point-min)
  206. (progn (beginning-of-line 2)
  207. (point)))))))
  208. (defun pgg-pgp-insert-key ()
  209. "Insert public key at point."
  210. (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
  211. (args
  212. (concat "+verbose=1 +batchmode +language=us -kxaf "
  213. (shell-quote-argument pgg-pgp-user-id))))
  214. (pgg-pgp-process-region (point)(point) nil pgg-pgp-program args)
  215. (insert-buffer-substring pgg-output-buffer)))
  216. (defun pgg-pgp-snarf-keys-region (start end)
  217. "Add all public keys in region between START and END to the keyring."
  218. (let* ((pgg-pgp-user-id (or pgg-pgp-user-id pgg-default-user-id))
  219. (key-file (pgg-make-temp-file "pgg"))
  220. (args
  221. (concat "+verbose=1 +batchmode +language=us -kaf "
  222. (shell-quote-argument key-file))))
  223. (let ((coding-system-for-write 'raw-text-dos))
  224. (write-region start end key-file))
  225. (pgg-pgp-process-region start end nil pgg-pgp-program args)
  226. (delete-file key-file)
  227. (pgg-process-when-success nil)))
  228. (provide 'pgg-pgp)
  229. ;;; pgg-pgp.el ends here