epa.el 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. ;;; epa.el --- the EasyPG Assistant -*- lexical-binding: t -*-
  2. ;; Copyright (C) 2006-2012 Free Software Foundation, Inc.
  3. ;; Author: Daiki Ueno <ueno@unixuser.org>
  4. ;; Keywords: PGP, GnuPG
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Code:
  17. (require 'epg)
  18. (require 'font-lock)
  19. (require 'widget)
  20. (eval-when-compile (require 'wid-edit))
  21. (require 'derived)
  22. (defgroup epa nil
  23. "The EasyPG Assistant"
  24. :version "23.1"
  25. :group 'epg)
  26. (defcustom epa-popup-info-window t
  27. "If non-nil, status information from epa commands is displayed on
  28. the separate window."
  29. :type 'boolean
  30. :group 'epa)
  31. (defcustom epa-info-window-height 5
  32. "Number of lines used to display status information."
  33. :type 'integer
  34. :group 'epa)
  35. (defgroup epa-faces nil
  36. "Faces for epa-mode."
  37. :version "23.1"
  38. :group 'epa)
  39. (defface epa-validity-high
  40. `((((class color) (background dark))
  41. (:foreground "PaleTurquoise"
  42. ,@(if (assq ':weight custom-face-attributes)
  43. '(:weight bold)
  44. '(:bold t))))
  45. (t
  46. (,@(if (assq ':weight custom-face-attributes)
  47. '(:weight bold)
  48. '(:bold t)))))
  49. "Face used for displaying the high validity."
  50. :group 'epa-faces)
  51. (defface epa-validity-medium
  52. `((((class color) (background dark))
  53. (:foreground "PaleTurquoise"
  54. ,@(if (assq ':slant custom-face-attributes)
  55. '(:slant italic)
  56. '(:italic t))))
  57. (t
  58. (,@(if (assq ':slant custom-face-attributes)
  59. '(:slant italic)
  60. '(:italic t)))))
  61. "Face used for displaying the medium validity."
  62. :group 'epa-faces)
  63. (defface epa-validity-low
  64. `((t
  65. (,@(if (assq ':slant custom-face-attributes)
  66. '(:slant italic)
  67. '(:italic t)))))
  68. "Face used for displaying the low validity."
  69. :group 'epa-faces)
  70. (defface epa-validity-disabled
  71. `((t
  72. (,@(if (assq ':slant custom-face-attributes)
  73. '(:slant italic)
  74. '(:italic t))
  75. :inverse-video t)))
  76. "Face used for displaying the disabled validity."
  77. :group 'epa-faces)
  78. (defface epa-string
  79. '((((class color) (background dark))
  80. (:foreground "lightyellow"))
  81. (((class color) (background light))
  82. (:foreground "blue4")))
  83. "Face used for displaying the string."
  84. :group 'epa-faces)
  85. (defface epa-mark
  86. `((((class color) (background dark))
  87. (:foreground "orange"
  88. ,@(if (assq ':weight custom-face-attributes)
  89. '(:weight bold)
  90. '(:bold t))))
  91. (((class color) (background light))
  92. (:foreground "red"
  93. ,@(if (assq ':weight custom-face-attributes)
  94. '(:weight bold)
  95. '(:bold t))))
  96. (t
  97. (,@(if (assq ':weight custom-face-attributes)
  98. '(:weight bold)
  99. '(:bold t)))))
  100. "Face used for displaying the high validity."
  101. :group 'epa-faces)
  102. (defface epa-field-name
  103. `((((class color) (background dark))
  104. (:foreground "PaleTurquoise"
  105. ,@(if (assq ':weight custom-face-attributes)
  106. '(:weight bold)
  107. '(:bold t))))
  108. (t
  109. (,@(if (assq ':weight custom-face-attributes)
  110. '(:weight bold)
  111. '(:bold t)))))
  112. "Face for the name of the attribute field."
  113. :group 'epa)
  114. (defface epa-field-body
  115. `((((class color) (background dark))
  116. (:foreground "turquoise"
  117. ,@(if (assq ':slant custom-face-attributes)
  118. '(:slant italic)
  119. '(:italic t))))
  120. (t
  121. (,@(if (assq ':slant custom-face-attributes)
  122. '(:slant italic)
  123. '(:italic t)))))
  124. "Face for the body of the attribute field."
  125. :group 'epa)
  126. (defcustom epa-validity-face-alist
  127. '((unknown . epa-validity-disabled)
  128. (invalid . epa-validity-disabled)
  129. (disabled . epa-validity-disabled)
  130. (revoked . epa-validity-disabled)
  131. (expired . epa-validity-disabled)
  132. (none . epa-validity-low)
  133. (undefined . epa-validity-low)
  134. (never . epa-validity-low)
  135. (marginal . epa-validity-medium)
  136. (full . epa-validity-high)
  137. (ultimate . epa-validity-high))
  138. "An alist mapping validity values to faces."
  139. :type '(repeat (cons symbol face))
  140. :group 'epa)
  141. (defvar epa-font-lock-keywords
  142. '(("^\\*"
  143. (0 'epa-mark))
  144. ("^\t\\([^\t:]+:\\)[ \t]*\\(.*\\)$"
  145. (1 'epa-field-name)
  146. (2 'epa-field-body)))
  147. "Default expressions to addon in epa-mode.")
  148. (defconst epa-pubkey-algorithm-letter-alist
  149. '((1 . ?R)
  150. (2 . ?r)
  151. (3 . ?s)
  152. (16 . ?g)
  153. (17 . ?D)
  154. (20 . ?G)))
  155. (defvar epa-protocol 'OpenPGP
  156. "*The default protocol.
  157. The value can be either OpenPGP or CMS.
  158. You should bind this variable with `let', but do not set it globally.")
  159. (defvar epa-armor nil
  160. "*If non-nil, epa commands create ASCII armored output.
  161. You should bind this variable with `let', but do not set it globally.")
  162. (defvar epa-textmode nil
  163. "*If non-nil, epa commands treat input files as text.
  164. You should bind this variable with `let', but do not set it globally.")
  165. (defvar epa-keys-buffer nil)
  166. (defvar epa-key-buffer-alist nil)
  167. (defvar epa-key nil)
  168. (defvar epa-list-keys-arguments nil)
  169. (defvar epa-info-buffer nil)
  170. (defvar epa-last-coding-system-specified nil)
  171. (defvar epa-key-list-mode-map
  172. (let ((keymap (make-sparse-keymap))
  173. (menu-map (make-sparse-keymap)))
  174. (define-key keymap "m" 'epa-mark-key)
  175. (define-key keymap "u" 'epa-unmark-key)
  176. (define-key keymap "d" 'epa-decrypt-file)
  177. (define-key keymap "v" 'epa-verify-file)
  178. (define-key keymap "s" 'epa-sign-file)
  179. (define-key keymap "e" 'epa-encrypt-file)
  180. (define-key keymap "r" 'epa-delete-keys)
  181. (define-key keymap "i" 'epa-import-keys)
  182. (define-key keymap "o" 'epa-export-keys)
  183. (define-key keymap "g" 'revert-buffer)
  184. (define-key keymap "n" 'next-line)
  185. (define-key keymap "p" 'previous-line)
  186. (define-key keymap " " 'scroll-up-command)
  187. (define-key keymap [delete] 'scroll-down-command)
  188. (define-key keymap "q" 'epa-exit-buffer)
  189. (define-key keymap [menu-bar epa-key-list-mode] (cons "Keys" menu-map))
  190. (define-key menu-map [epa-key-list-unmark-key]
  191. '(menu-item "Unmark Key" epa-unmark-key
  192. :help "Unmark a key"))
  193. (define-key menu-map [epa-key-list-mark-key]
  194. '(menu-item "Mark Key" epa-mark-key
  195. :help "Mark a key"))
  196. (define-key menu-map [separator-epa-file] '(menu-item "--"))
  197. (define-key menu-map [epa-verify-file]
  198. '(menu-item "Verify File..." epa-verify-file
  199. :help "Verify FILE"))
  200. (define-key menu-map [epa-sign-file]
  201. '(menu-item "Sign File..." epa-sign-file
  202. :help "Sign FILE by SIGNERS keys selected"))
  203. (define-key menu-map [epa-decrypt-file]
  204. '(menu-item "Decrypt File..." epa-decrypt-file
  205. :help "Decrypt FILE"))
  206. (define-key menu-map [epa-encrypt-file]
  207. '(menu-item "Encrypt File..." epa-encrypt-file
  208. :help "Encrypt FILE for RECIPIENTS"))
  209. (define-key menu-map [separator-epa-key-list] '(menu-item "--"))
  210. (define-key menu-map [epa-key-list-delete-keys]
  211. '(menu-item "Delete Keys" epa-delete-keys
  212. :help "Delete Marked Keys"))
  213. (define-key menu-map [epa-key-list-import-keys]
  214. '(menu-item "Import Keys" epa-import-keys
  215. :help "Import keys from a file"))
  216. (define-key menu-map [epa-key-list-export-keys]
  217. '(menu-item "Export Keys" epa-export-keys
  218. :help "Export marked keys to a file"))
  219. keymap))
  220. (defvar epa-key-mode-map
  221. (let ((keymap (make-sparse-keymap)))
  222. (define-key keymap "q" 'epa-exit-buffer)
  223. keymap))
  224. (defvar epa-info-mode-map
  225. (let ((keymap (make-sparse-keymap)))
  226. (define-key keymap "q" 'delete-window)
  227. keymap))
  228. (defvar epa-exit-buffer-function #'bury-buffer)
  229. (define-widget 'epa-key 'push-button
  230. "Button for representing a epg-key object."
  231. :format "%[%v%]"
  232. :button-face-get 'epa--key-widget-button-face-get
  233. :value-create 'epa--key-widget-value-create
  234. :action 'epa--key-widget-action
  235. :help-echo 'epa--key-widget-help-echo)
  236. (defun epa--key-widget-action (widget &optional _event)
  237. (save-selected-window
  238. (epa--show-key (widget-get widget :value))))
  239. (defun epa--key-widget-value-create (widget)
  240. (let* ((key (widget-get widget :value))
  241. (primary-sub-key (car (epg-key-sub-key-list key)))
  242. (primary-user-id (car (epg-key-user-id-list key))))
  243. (insert (format "%c "
  244. (if (epg-sub-key-validity primary-sub-key)
  245. (car (rassq (epg-sub-key-validity primary-sub-key)
  246. epg-key-validity-alist))
  247. ? ))
  248. (epg-sub-key-id primary-sub-key)
  249. " "
  250. (if primary-user-id
  251. (if (stringp (epg-user-id-string primary-user-id))
  252. (epg-user-id-string primary-user-id)
  253. (epg-decode-dn (epg-user-id-string primary-user-id)))
  254. ""))))
  255. (defun epa--key-widget-button-face-get (widget)
  256. (let ((validity (epg-sub-key-validity (car (epg-key-sub-key-list
  257. (widget-get widget :value))))))
  258. (if validity
  259. (cdr (assq validity epa-validity-face-alist))
  260. 'default)))
  261. (defun epa--key-widget-help-echo (widget)
  262. (format "Show %s"
  263. (epg-sub-key-id (car (epg-key-sub-key-list
  264. (widget-get widget :value))))))
  265. (eval-and-compile
  266. (if (fboundp 'encode-coding-string)
  267. (defalias 'epa--encode-coding-string 'encode-coding-string)
  268. (defalias 'epa--encode-coding-string 'identity)))
  269. (eval-and-compile
  270. (if (fboundp 'decode-coding-string)
  271. (defalias 'epa--decode-coding-string 'decode-coding-string)
  272. (defalias 'epa--decode-coding-string 'identity)))
  273. (defun epa-key-list-mode ()
  274. "Major mode for `epa-list-keys'."
  275. (kill-all-local-variables)
  276. (buffer-disable-undo)
  277. (setq major-mode 'epa-key-list-mode
  278. mode-name "Keys"
  279. truncate-lines t
  280. buffer-read-only t)
  281. (use-local-map epa-key-list-mode-map)
  282. (make-local-variable 'font-lock-defaults)
  283. (setq font-lock-defaults '(epa-font-lock-keywords t))
  284. ;; In XEmacs, auto-initialization of font-lock is not effective
  285. ;; if buffer-file-name is not set.
  286. (font-lock-set-defaults)
  287. (make-local-variable 'epa-exit-buffer-function)
  288. (make-local-variable 'revert-buffer-function)
  289. (setq revert-buffer-function 'epa--key-list-revert-buffer)
  290. (run-mode-hooks 'epa-key-list-mode-hook))
  291. (defun epa-key-mode ()
  292. "Major mode for a key description."
  293. (kill-all-local-variables)
  294. (buffer-disable-undo)
  295. (setq major-mode 'epa-key-mode
  296. mode-name "Key"
  297. truncate-lines t
  298. buffer-read-only t)
  299. (use-local-map epa-key-mode-map)
  300. (make-local-variable 'font-lock-defaults)
  301. (setq font-lock-defaults '(epa-font-lock-keywords t))
  302. ;; In XEmacs, auto-initialization of font-lock is not effective
  303. ;; if buffer-file-name is not set.
  304. (font-lock-set-defaults)
  305. (make-local-variable 'epa-exit-buffer-function)
  306. (run-mode-hooks 'epa-key-mode-hook))
  307. (defun epa-info-mode ()
  308. "Major mode for `epa-info-buffer'."
  309. (kill-all-local-variables)
  310. (buffer-disable-undo)
  311. (setq major-mode 'epa-info-mode
  312. mode-name "Info"
  313. truncate-lines t
  314. buffer-read-only t)
  315. (use-local-map epa-info-mode-map)
  316. (run-mode-hooks 'epa-info-mode-hook))
  317. (defun epa-mark-key (&optional arg)
  318. "Mark a key on the current line.
  319. If ARG is non-nil, unmark the key."
  320. (interactive "P")
  321. (let ((inhibit-read-only t)
  322. buffer-read-only
  323. properties)
  324. (beginning-of-line)
  325. (unless (get-text-property (point) 'epa-key)
  326. (error "No key on this line"))
  327. (setq properties (text-properties-at (point)))
  328. (delete-char 1)
  329. (insert (if arg " " "*"))
  330. (set-text-properties (1- (point)) (point) properties)
  331. (forward-line)))
  332. (defun epa-unmark-key (&optional arg)
  333. "Unmark a key on the current line.
  334. If ARG is non-nil, mark the key."
  335. (interactive "P")
  336. (epa-mark-key (not arg)))
  337. (defun epa-exit-buffer ()
  338. "Exit the current buffer.
  339. `epa-exit-buffer-function' is called if it is set."
  340. (interactive)
  341. (funcall epa-exit-buffer-function))
  342. (defun epa--insert-keys (keys)
  343. (save-excursion
  344. (save-restriction
  345. (narrow-to-region (point) (point))
  346. (let (point)
  347. (while keys
  348. (setq point (point))
  349. (insert " ")
  350. (add-text-properties point (point)
  351. (list 'epa-key (car keys)
  352. 'front-sticky nil
  353. 'rear-nonsticky t
  354. 'start-open t
  355. 'end-open t))
  356. (widget-create 'epa-key :value (car keys))
  357. (insert "\n")
  358. (setq keys (cdr keys))))
  359. (add-text-properties (point-min) (point-max)
  360. (list 'epa-list-keys t
  361. 'front-sticky nil
  362. 'rear-nonsticky t
  363. 'start-open t
  364. 'end-open t)))))
  365. (defun epa--list-keys (name secret)
  366. (unless (and epa-keys-buffer
  367. (buffer-live-p epa-keys-buffer))
  368. (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
  369. (set-buffer epa-keys-buffer)
  370. (epa-key-list-mode)
  371. (let ((inhibit-read-only t)
  372. buffer-read-only
  373. (point (point-min))
  374. (context (epg-make-context epa-protocol)))
  375. (unless (get-text-property point 'epa-list-keys)
  376. (setq point (next-single-property-change point 'epa-list-keys)))
  377. (when point
  378. (delete-region point
  379. (or (next-single-property-change point 'epa-list-keys)
  380. (point-max)))
  381. (goto-char point))
  382. (epa--insert-keys (epg-list-keys context name secret))
  383. (widget-setup)
  384. (set-keymap-parent (current-local-map) widget-keymap))
  385. (make-local-variable 'epa-list-keys-arguments)
  386. (setq epa-list-keys-arguments (list name secret))
  387. (goto-char (point-min))
  388. (pop-to-buffer (current-buffer)))
  389. ;;;###autoload
  390. (defun epa-list-keys (&optional name)
  391. "List all keys matched with NAME from the public keyring."
  392. (interactive
  393. (if current-prefix-arg
  394. (let ((name (read-string "Pattern: "
  395. (if epa-list-keys-arguments
  396. (car epa-list-keys-arguments)))))
  397. (list (if (equal name "") nil name)))
  398. (list nil)))
  399. (epa--list-keys name nil))
  400. ;;;###autoload
  401. (defun epa-list-secret-keys (&optional name)
  402. "List all keys matched with NAME from the private keyring."
  403. (interactive
  404. (if current-prefix-arg
  405. (let ((name (read-string "Pattern: "
  406. (if epa-list-keys-arguments
  407. (car epa-list-keys-arguments)))))
  408. (list (if (equal name "") nil name)))
  409. (list nil)))
  410. (epa--list-keys name t))
  411. (defun epa--key-list-revert-buffer (&optional _ignore-auto _noconfirm)
  412. (apply #'epa--list-keys epa-list-keys-arguments))
  413. (defun epa--marked-keys ()
  414. (or (with-current-buffer epa-keys-buffer
  415. (goto-char (point-min))
  416. (let (keys key)
  417. (while (re-search-forward "^\\*" nil t)
  418. (if (setq key (get-text-property (match-beginning 0)
  419. 'epa-key))
  420. (setq keys (cons key keys))))
  421. (nreverse keys)))
  422. (let ((key (get-text-property (point-at-bol) 'epa-key)))
  423. (if key
  424. (list key)))))
  425. (defun epa--select-keys (prompt keys)
  426. (unless (and epa-keys-buffer
  427. (buffer-live-p epa-keys-buffer))
  428. (setq epa-keys-buffer (generate-new-buffer "*Keys*")))
  429. (with-current-buffer epa-keys-buffer
  430. (epa-key-list-mode)
  431. ;; C-c C-c is the usual way to finish the selection (bug#11159).
  432. (define-key (current-local-map) "\C-c\C-c" 'exit-recursive-edit)
  433. (let ((inhibit-read-only t)
  434. buffer-read-only)
  435. (erase-buffer)
  436. (insert prompt "\n"
  437. (substitute-command-keys "\
  438. - `\\[epa-mark-key]' to mark a key on the line
  439. - `\\[epa-unmark-key]' to unmark a key on the line\n"))
  440. (widget-create 'link
  441. :notify (lambda (&rest _ignore) (abort-recursive-edit))
  442. :help-echo
  443. (substitute-command-keys
  444. "Click here or \\[abort-recursive-edit] to cancel")
  445. "Cancel")
  446. (widget-create 'link
  447. :notify (lambda (&rest _ignore) (exit-recursive-edit))
  448. :help-echo
  449. (substitute-command-keys
  450. "Click here or \\[exit-recursive-edit] to finish")
  451. "OK")
  452. (insert "\n\n")
  453. (epa--insert-keys keys)
  454. (widget-setup)
  455. (set-keymap-parent (current-local-map) widget-keymap)
  456. (setq epa-exit-buffer-function #'abort-recursive-edit)
  457. (goto-char (point-min))
  458. (let ((display-buffer-mark-dedicated 'soft))
  459. (pop-to-buffer (current-buffer))))
  460. (unwind-protect
  461. (progn
  462. (recursive-edit)
  463. (epa--marked-keys))
  464. (kill-buffer epa-keys-buffer))))
  465. ;;;###autoload
  466. (defun epa-select-keys (context prompt &optional names secret)
  467. "Display a user's keyring and ask him to select keys.
  468. CONTEXT is an epg-context.
  469. PROMPT is a string to prompt with.
  470. NAMES is a list of strings to be matched with keys. If it is nil, all
  471. the keys are listed.
  472. If SECRET is non-nil, list secret keys instead of public keys."
  473. (let ((keys (epg-list-keys context names secret)))
  474. (epa--select-keys prompt keys)))
  475. (defun epa--show-key (key)
  476. (let* ((primary-sub-key (car (epg-key-sub-key-list key)))
  477. (entry (assoc (epg-sub-key-id primary-sub-key)
  478. epa-key-buffer-alist))
  479. (inhibit-read-only t)
  480. buffer-read-only
  481. pointer)
  482. (unless entry
  483. (setq entry (cons (epg-sub-key-id primary-sub-key) nil)
  484. epa-key-buffer-alist (cons entry epa-key-buffer-alist)))
  485. (unless (and (cdr entry)
  486. (buffer-live-p (cdr entry)))
  487. (setcdr entry (generate-new-buffer
  488. (format "*Key*%s" (epg-sub-key-id primary-sub-key)))))
  489. (set-buffer (cdr entry))
  490. (epa-key-mode)
  491. (make-local-variable 'epa-key)
  492. (setq epa-key key)
  493. (erase-buffer)
  494. (setq pointer (epg-key-user-id-list key))
  495. (while pointer
  496. (if (car pointer)
  497. (insert " "
  498. (if (epg-user-id-validity (car pointer))
  499. (char-to-string
  500. (car (rassq (epg-user-id-validity (car pointer))
  501. epg-key-validity-alist)))
  502. " ")
  503. " "
  504. (if (stringp (epg-user-id-string (car pointer)))
  505. (epg-user-id-string (car pointer))
  506. (epg-decode-dn (epg-user-id-string (car pointer))))
  507. "\n"))
  508. (setq pointer (cdr pointer)))
  509. (setq pointer (epg-key-sub-key-list key))
  510. (while pointer
  511. (insert " "
  512. (if (epg-sub-key-validity (car pointer))
  513. (char-to-string
  514. (car (rassq (epg-sub-key-validity (car pointer))
  515. epg-key-validity-alist)))
  516. " ")
  517. " "
  518. (epg-sub-key-id (car pointer))
  519. " "
  520. (format "%dbits"
  521. (epg-sub-key-length (car pointer)))
  522. " "
  523. (cdr (assq (epg-sub-key-algorithm (car pointer))
  524. epg-pubkey-algorithm-alist))
  525. "\n\tCreated: "
  526. (condition-case nil
  527. (format-time-string "%Y-%m-%d"
  528. (epg-sub-key-creation-time (car pointer)))
  529. (error "????-??-??"))
  530. (if (epg-sub-key-expiration-time (car pointer))
  531. (format (if (time-less-p (current-time)
  532. (epg-sub-key-expiration-time
  533. (car pointer)))
  534. "\n\tExpires: %s"
  535. "\n\tExpired: %s")
  536. (condition-case nil
  537. (format-time-string "%Y-%m-%d"
  538. (epg-sub-key-expiration-time
  539. (car pointer)))
  540. (error "????-??-??")))
  541. "")
  542. "\n\tCapabilities: "
  543. (mapconcat #'symbol-name
  544. (epg-sub-key-capability (car pointer))
  545. " ")
  546. "\n\tFingerprint: "
  547. (epg-sub-key-fingerprint (car pointer))
  548. "\n")
  549. (setq pointer (cdr pointer)))
  550. (goto-char (point-min))
  551. (pop-to-buffer (current-buffer))))
  552. (defun epa-display-info (info)
  553. (if epa-popup-info-window
  554. (save-selected-window
  555. (unless (and epa-info-buffer (buffer-live-p epa-info-buffer))
  556. (setq epa-info-buffer (generate-new-buffer "*Info*")))
  557. (if (get-buffer-window epa-info-buffer)
  558. (delete-window (get-buffer-window epa-info-buffer)))
  559. (with-current-buffer epa-info-buffer
  560. (let ((inhibit-read-only t)
  561. buffer-read-only)
  562. (erase-buffer)
  563. (insert info))
  564. (epa-info-mode)
  565. (goto-char (point-min)))
  566. (if (> (window-height)
  567. epa-info-window-height)
  568. (set-window-buffer (split-window nil (- (window-height)
  569. epa-info-window-height))
  570. epa-info-buffer)
  571. (pop-to-buffer epa-info-buffer)
  572. (if (> (window-height) epa-info-window-height)
  573. (shrink-window (- (window-height) epa-info-window-height)))))
  574. (message "%s" info)))
  575. (defun epa-display-verify-result (verify-result)
  576. (epa-display-info (epg-verify-result-to-string verify-result)))
  577. (make-obsolete 'epa-display-verify-result 'epa-display-info "23.1")
  578. (defun epa-passphrase-callback-function (context key-id handback)
  579. (if (eq key-id 'SYM)
  580. (read-passwd
  581. (format "Passphrase for symmetric encryption%s: "
  582. ;; Add the file name to the prompt, if any.
  583. (if (stringp handback)
  584. (format " for %s" handback)
  585. ""))
  586. (eq (epg-context-operation context) 'encrypt))
  587. (read-passwd
  588. (if (eq key-id 'PIN)
  589. "Passphrase for PIN: "
  590. (let ((entry (assoc key-id epg-user-id-alist)))
  591. (if entry
  592. (format "Passphrase for %s %s: " key-id (cdr entry))
  593. (format "Passphrase for %s: " key-id)))))))
  594. (defun epa-progress-callback-function (_context what _char current total
  595. handback)
  596. (let ((prompt (or handback
  597. (format "Processing %s: " what))))
  598. ;; According to gnupg/doc/DETAIL: a "total" of 0 indicates that
  599. ;; the total amount is not known. The condition TOTAL && CUR ==
  600. ;; TOTAL may be used to detect the end of an operation.
  601. (if (> total 0)
  602. (if (= current total)
  603. (message "%s...done" prompt)
  604. (message "%s...%d%%" prompt
  605. (floor (* (/ current (float total)) 100))))
  606. (message "%s..." prompt))))
  607. ;;;###autoload
  608. (defun epa-decrypt-file (file)
  609. "Decrypt FILE."
  610. (interactive "fFile: ")
  611. (setq file (expand-file-name file))
  612. (let* ((default-name (file-name-sans-extension file))
  613. (plain (expand-file-name
  614. (read-file-name
  615. (concat "To file (default "
  616. (file-name-nondirectory default-name)
  617. ") ")
  618. (file-name-directory default-name)
  619. default-name)))
  620. (context (epg-make-context epa-protocol)))
  621. (epg-context-set-passphrase-callback context
  622. #'epa-passphrase-callback-function)
  623. (epg-context-set-progress-callback context
  624. (cons
  625. #'epa-progress-callback-function
  626. (format "Decrypting %s..."
  627. (file-name-nondirectory file))))
  628. (message "Decrypting %s..." (file-name-nondirectory file))
  629. (epg-decrypt-file context file plain)
  630. (message "Decrypting %s...wrote %s" (file-name-nondirectory file)
  631. (file-name-nondirectory plain))
  632. (if (epg-context-result-for context 'verify)
  633. (epa-display-info (epg-verify-result-to-string
  634. (epg-context-result-for context 'verify))))))
  635. ;;;###autoload
  636. (defun epa-verify-file (file)
  637. "Verify FILE."
  638. (interactive "fFile: ")
  639. (setq file (expand-file-name file))
  640. (let* ((context (epg-make-context epa-protocol))
  641. (plain (if (equal (file-name-extension file) "sig")
  642. (file-name-sans-extension file))))
  643. (epg-context-set-progress-callback context
  644. (cons
  645. #'epa-progress-callback-function
  646. (format "Verifying %s..."
  647. (file-name-nondirectory file))))
  648. (message "Verifying %s..." (file-name-nondirectory file))
  649. (epg-verify-file context file plain)
  650. (message "Verifying %s...done" (file-name-nondirectory file))
  651. (if (epg-context-result-for context 'verify)
  652. (epa-display-info (epg-verify-result-to-string
  653. (epg-context-result-for context 'verify))))))
  654. (defun epa--read-signature-type ()
  655. (let (type c)
  656. (while (null type)
  657. (message "Signature type (n,c,d,?) ")
  658. (setq c (read-char))
  659. (cond ((eq c ?c)
  660. (setq type 'clear))
  661. ((eq c ?d)
  662. (setq type 'detached))
  663. ((eq c ??)
  664. (with-output-to-temp-buffer "*Help*"
  665. (with-current-buffer standard-output
  666. (insert "\
  667. n - Create a normal signature
  668. c - Create a cleartext signature
  669. d - Create a detached signature
  670. ? - Show this help
  671. "))))
  672. (t
  673. (setq type 'normal))))
  674. type))
  675. ;;;###autoload
  676. (defun epa-sign-file (file signers mode)
  677. "Sign FILE by SIGNERS keys selected."
  678. (interactive
  679. (let ((verbose current-prefix-arg))
  680. (list (expand-file-name (read-file-name "File: "))
  681. (if verbose
  682. (epa-select-keys (epg-make-context epa-protocol)
  683. "Select keys for signing.
  684. If no one is selected, default secret key is used. "
  685. nil t))
  686. (if verbose
  687. (epa--read-signature-type)
  688. 'clear))))
  689. (let ((signature (concat file
  690. (if (eq epa-protocol 'OpenPGP)
  691. (if (or epa-armor
  692. (not (memq mode
  693. '(nil t normal detached))))
  694. ".asc"
  695. (if (memq mode '(t detached))
  696. ".sig"
  697. ".gpg"))
  698. (if (memq mode '(t detached))
  699. ".p7s"
  700. ".p7m"))))
  701. (context (epg-make-context epa-protocol)))
  702. (epg-context-set-armor context epa-armor)
  703. (epg-context-set-textmode context epa-textmode)
  704. (epg-context-set-signers context signers)
  705. (epg-context-set-passphrase-callback context
  706. #'epa-passphrase-callback-function)
  707. (epg-context-set-progress-callback context
  708. (cons
  709. #'epa-progress-callback-function
  710. (format "Signing %s..."
  711. (file-name-nondirectory file))))
  712. (message "Signing %s..." (file-name-nondirectory file))
  713. (epg-sign-file context file signature mode)
  714. (message "Signing %s...wrote %s" (file-name-nondirectory file)
  715. (file-name-nondirectory signature))))
  716. ;;;###autoload
  717. (defun epa-encrypt-file (file recipients)
  718. "Encrypt FILE for RECIPIENTS."
  719. (interactive
  720. (list (expand-file-name (read-file-name "File: "))
  721. (epa-select-keys (epg-make-context epa-protocol)
  722. "Select recipients for encryption.
  723. If no one is selected, symmetric encryption will be performed. ")))
  724. (let ((cipher (concat file (if (eq epa-protocol 'OpenPGP)
  725. (if epa-armor ".asc" ".gpg")
  726. ".p7m")))
  727. (context (epg-make-context epa-protocol)))
  728. (epg-context-set-armor context epa-armor)
  729. (epg-context-set-textmode context epa-textmode)
  730. (epg-context-set-passphrase-callback context
  731. #'epa-passphrase-callback-function)
  732. (epg-context-set-progress-callback context
  733. (cons
  734. #'epa-progress-callback-function
  735. (format "Encrypting %s..."
  736. (file-name-nondirectory file))))
  737. (message "Encrypting %s..." (file-name-nondirectory file))
  738. (epg-encrypt-file context file recipients cipher)
  739. (message "Encrypting %s...wrote %s" (file-name-nondirectory file)
  740. (file-name-nondirectory cipher))))
  741. ;;;###autoload
  742. (defun epa-decrypt-region (start end &optional make-buffer-function)
  743. "Decrypt the current region between START and END.
  744. If MAKE-BUFFER-FUNCTION is non-nil, call it to prepare an output buffer.
  745. It should return that buffer. If it copies the input, it should
  746. delete the text now being decrypted. It should leave point at the
  747. proper place to insert the plaintext.
  748. Be careful about using this command in Lisp programs!
  749. Since this function operates on regions, it does some tricks such
  750. as coding-system detection and unibyte/multibyte conversion. If
  751. you are sure how the data in the region should be treated, you
  752. should consider using the string based counterpart
  753. `epg-decrypt-string', or the file based counterpart
  754. `epg-decrypt-file' instead.
  755. For example:
  756. \(let ((context (epg-make-context 'OpenPGP)))
  757. (decode-coding-string
  758. (epg-decrypt-string context (buffer-substring start end))
  759. 'utf-8))"
  760. (interactive "r")
  761. (save-excursion
  762. (let ((context (epg-make-context epa-protocol))
  763. plain)
  764. (epg-context-set-passphrase-callback context
  765. #'epa-passphrase-callback-function)
  766. (epg-context-set-progress-callback context
  767. (cons
  768. #'epa-progress-callback-function
  769. "Decrypting..."))
  770. (message "Decrypting...")
  771. (setq plain (epg-decrypt-string context (buffer-substring start end)))
  772. (message "Decrypting...done")
  773. (setq plain (epa--decode-coding-string
  774. plain
  775. (or coding-system-for-read
  776. (get-text-property start 'epa-coding-system-used)
  777. 'undecided)))
  778. (if make-buffer-function
  779. (with-current-buffer (funcall make-buffer-function)
  780. (let ((inhibit-read-only t))
  781. (insert plain)))
  782. (if (y-or-n-p "Replace the original text? ")
  783. (let ((inhibit-read-only t))
  784. (delete-region start end)
  785. (goto-char start)
  786. (insert plain))
  787. (with-output-to-temp-buffer "*Temp*"
  788. (set-buffer standard-output)
  789. (insert plain)
  790. (epa-info-mode))))
  791. (if (epg-context-result-for context 'verify)
  792. (epa-display-info (epg-verify-result-to-string
  793. (epg-context-result-for context 'verify)))))))
  794. (defun epa--find-coding-system-for-mime-charset (mime-charset)
  795. (if (featurep 'xemacs)
  796. (if (fboundp 'find-coding-system)
  797. (find-coding-system mime-charset))
  798. ;; Find the first coding system which corresponds to MIME-CHARSET.
  799. (let ((pointer (coding-system-list)))
  800. (while (and pointer
  801. (not (eq (coding-system-get (car pointer) 'mime-charset)
  802. mime-charset)))
  803. (setq pointer (cdr pointer)))
  804. (car pointer))))
  805. ;;;###autoload
  806. (defun epa-decrypt-armor-in-region (start end)
  807. "Decrypt OpenPGP armors in the current region between START and END.
  808. Don't use this command in Lisp programs!
  809. See the reason described in the `epa-decrypt-region' documentation."
  810. (interactive "r")
  811. (save-excursion
  812. (save-restriction
  813. (narrow-to-region start end)
  814. (goto-char start)
  815. (let (armor-start armor-end)
  816. (while (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
  817. (setq armor-start (match-beginning 0)
  818. armor-end (re-search-forward "^-----END PGP MESSAGE-----$"
  819. nil t))
  820. (unless armor-end
  821. (error "Encryption armor beginning has no matching end"))
  822. (goto-char armor-start)
  823. (let ((coding-system-for-read
  824. (or coding-system-for-read
  825. (if (re-search-forward "^Charset: \\(.*\\)" armor-end t)
  826. (epa--find-coding-system-for-mime-charset
  827. (intern (downcase (match-string 1))))))))
  828. (goto-char armor-end)
  829. (epa-decrypt-region armor-start armor-end)))))))
  830. ;;;###autoload
  831. (defun epa-verify-region (start end)
  832. "Verify the current region between START and END.
  833. Don't use this command in Lisp programs!
  834. Since this function operates on regions, it does some tricks such
  835. as coding-system detection and unibyte/multibyte conversion. If
  836. you are sure how the data in the region should be treated, you
  837. should consider using the string based counterpart
  838. `epg-verify-string', or the file based counterpart
  839. `epg-verify-file' instead.
  840. For example:
  841. \(let ((context (epg-make-context 'OpenPGP)))
  842. (decode-coding-string
  843. (epg-verify-string context (buffer-substring start end))
  844. 'utf-8))"
  845. (interactive "r")
  846. (let ((context (epg-make-context epa-protocol))
  847. plain)
  848. (epg-context-set-progress-callback context
  849. (cons
  850. #'epa-progress-callback-function
  851. "Verifying..."))
  852. (message "Verifying...")
  853. (setq plain (epg-verify-string
  854. context
  855. (epa--encode-coding-string
  856. (buffer-substring start end)
  857. (or coding-system-for-write
  858. (get-text-property start 'epa-coding-system-used)))))
  859. (message "Verifying...done")
  860. (setq plain (epa--decode-coding-string
  861. plain
  862. (or coding-system-for-read
  863. (get-text-property start 'epa-coding-system-used)
  864. 'undecided)))
  865. (if (y-or-n-p "Replace the original text? ")
  866. (let ((inhibit-read-only t)
  867. buffer-read-only)
  868. (delete-region start end)
  869. (goto-char start)
  870. (insert plain))
  871. (with-output-to-temp-buffer "*Temp*"
  872. (set-buffer standard-output)
  873. (insert plain)
  874. (epa-info-mode)))
  875. (if (epg-context-result-for context 'verify)
  876. (epa-display-info (epg-verify-result-to-string
  877. (epg-context-result-for context 'verify))))))
  878. ;;;###autoload
  879. (defun epa-verify-cleartext-in-region (start end)
  880. "Verify OpenPGP cleartext signed messages in the current region
  881. between START and END.
  882. Don't use this command in Lisp programs!
  883. See the reason described in the `epa-verify-region' documentation."
  884. (interactive "r")
  885. (save-excursion
  886. (save-restriction
  887. (narrow-to-region start end)
  888. (goto-char start)
  889. (let (cleartext-start cleartext-end)
  890. (while (re-search-forward "-----BEGIN PGP SIGNED MESSAGE-----$"
  891. nil t)
  892. (setq cleartext-start (match-beginning 0))
  893. (unless (re-search-forward "^-----BEGIN PGP SIGNATURE-----$"
  894. nil t)
  895. (error "Invalid cleartext signed message"))
  896. (setq cleartext-end (re-search-forward
  897. "^-----END PGP SIGNATURE-----$"
  898. nil t))
  899. (unless cleartext-end
  900. (error "No cleartext tail"))
  901. (epa-verify-region cleartext-start cleartext-end))))))
  902. (eval-and-compile
  903. (if (fboundp 'select-safe-coding-system)
  904. (defalias 'epa--select-safe-coding-system 'select-safe-coding-system)
  905. (defun epa--select-safe-coding-system (_from _to)
  906. buffer-file-coding-system)))
  907. ;;;###autoload
  908. (defun epa-sign-region (start end signers mode)
  909. "Sign the current region between START and END by SIGNERS keys selected.
  910. Don't use this command in Lisp programs!
  911. Since this function operates on regions, it does some tricks such
  912. as coding-system detection and unibyte/multibyte conversion. If
  913. you are sure how the data should be treated, you should consider
  914. using the string based counterpart `epg-sign-string', or the file
  915. based counterpart `epg-sign-file' instead.
  916. For example:
  917. \(let ((context (epg-make-context 'OpenPGP)))
  918. (epg-sign-string
  919. context
  920. (encode-coding-string (buffer-substring start end) 'utf-8)))"
  921. (interactive
  922. (let ((verbose current-prefix-arg))
  923. (setq epa-last-coding-system-specified
  924. (or coding-system-for-write
  925. (epa--select-safe-coding-system
  926. (region-beginning) (region-end))))
  927. (list (region-beginning) (region-end)
  928. (if verbose
  929. (epa-select-keys (epg-make-context epa-protocol)
  930. "Select keys for signing.
  931. If no one is selected, default secret key is used. "
  932. nil t))
  933. (if verbose
  934. (epa--read-signature-type)
  935. 'clear))))
  936. (save-excursion
  937. (let ((context (epg-make-context epa-protocol))
  938. signature)
  939. ;;(epg-context-set-armor context epa-armor)
  940. (epg-context-set-armor context t)
  941. ;;(epg-context-set-textmode context epa-textmode)
  942. (epg-context-set-textmode context t)
  943. (epg-context-set-signers context signers)
  944. (epg-context-set-passphrase-callback context
  945. #'epa-passphrase-callback-function)
  946. (epg-context-set-progress-callback context
  947. (cons
  948. #'epa-progress-callback-function
  949. "Signing..."))
  950. (message "Signing...")
  951. (setq signature (epg-sign-string context
  952. (epa--encode-coding-string
  953. (buffer-substring start end)
  954. epa-last-coding-system-specified)
  955. mode))
  956. (message "Signing...done")
  957. (delete-region start end)
  958. (goto-char start)
  959. (add-text-properties (point)
  960. (progn
  961. (insert (epa--decode-coding-string
  962. signature
  963. (or coding-system-for-read
  964. epa-last-coding-system-specified)))
  965. (point))
  966. (list 'epa-coding-system-used
  967. epa-last-coding-system-specified
  968. 'front-sticky nil
  969. 'rear-nonsticky t
  970. 'start-open t
  971. 'end-open t)))))
  972. (eval-and-compile
  973. (if (fboundp 'derived-mode-p)
  974. (defalias 'epa--derived-mode-p 'derived-mode-p)
  975. (defun epa--derived-mode-p (&rest modes)
  976. "Non-nil if the current major mode is derived from one of MODES.
  977. Uses the `derived-mode-parent' property of the symbol to trace backwards."
  978. (let ((parent major-mode))
  979. (while (and (not (memq parent modes))
  980. (setq parent (get parent 'derived-mode-parent))))
  981. parent))))
  982. ;;;###autoload
  983. (defun epa-encrypt-region (start end recipients sign signers)
  984. "Encrypt the current region between START and END for RECIPIENTS.
  985. Don't use this command in Lisp programs!
  986. Since this function operates on regions, it does some tricks such
  987. as coding-system detection and unibyte/multibyte conversion. If
  988. you are sure how the data should be treated, you should consider
  989. using the string based counterpart `epg-encrypt-string', or the
  990. file based counterpart `epg-encrypt-file' instead.
  991. For example:
  992. \(let ((context (epg-make-context 'OpenPGP)))
  993. (epg-encrypt-string
  994. context
  995. (encode-coding-string (buffer-substring start end) 'utf-8)
  996. nil))"
  997. (interactive
  998. (let ((verbose current-prefix-arg)
  999. (context (epg-make-context epa-protocol))
  1000. sign)
  1001. (setq epa-last-coding-system-specified
  1002. (or coding-system-for-write
  1003. (epa--select-safe-coding-system
  1004. (region-beginning) (region-end))))
  1005. (list (region-beginning) (region-end)
  1006. (epa-select-keys context
  1007. "Select recipients for encryption.
  1008. If no one is selected, symmetric encryption will be performed. ")
  1009. (setq sign (if verbose (y-or-n-p "Sign? ")))
  1010. (if sign
  1011. (epa-select-keys context
  1012. "Select keys for signing. ")))))
  1013. (save-excursion
  1014. (let ((context (epg-make-context epa-protocol))
  1015. cipher)
  1016. ;;(epg-context-set-armor context epa-armor)
  1017. (epg-context-set-armor context t)
  1018. ;;(epg-context-set-textmode context epa-textmode)
  1019. (epg-context-set-textmode context t)
  1020. (if sign
  1021. (epg-context-set-signers context signers))
  1022. (epg-context-set-passphrase-callback context
  1023. #'epa-passphrase-callback-function)
  1024. (epg-context-set-progress-callback context
  1025. (cons
  1026. #'epa-progress-callback-function
  1027. "Encrypting..."))
  1028. (message "Encrypting...")
  1029. (setq cipher (epg-encrypt-string context
  1030. (epa--encode-coding-string
  1031. (buffer-substring start end)
  1032. epa-last-coding-system-specified)
  1033. recipients
  1034. sign))
  1035. (message "Encrypting...done")
  1036. (delete-region start end)
  1037. (goto-char start)
  1038. (add-text-properties (point)
  1039. (progn
  1040. (insert cipher)
  1041. (point))
  1042. (list 'epa-coding-system-used
  1043. epa-last-coding-system-specified
  1044. 'front-sticky nil
  1045. 'rear-nonsticky t
  1046. 'start-open t
  1047. 'end-open t)))))
  1048. ;;;###autoload
  1049. (defun epa-delete-keys (keys &optional allow-secret)
  1050. "Delete selected KEYS."
  1051. (interactive
  1052. (let ((keys (epa--marked-keys)))
  1053. (unless keys
  1054. (error "No keys selected"))
  1055. (list keys
  1056. (eq (nth 1 epa-list-keys-arguments) t))))
  1057. (let ((context (epg-make-context epa-protocol)))
  1058. (message "Deleting...")
  1059. (epg-delete-keys context keys allow-secret)
  1060. (message "Deleting...done")
  1061. (apply #'epa--list-keys epa-list-keys-arguments)))
  1062. ;;;###autoload
  1063. (defun epa-import-keys (file)
  1064. "Import keys from FILE."
  1065. (interactive "fFile: ")
  1066. (setq file (expand-file-name file))
  1067. (let ((context (epg-make-context epa-protocol)))
  1068. (message "Importing %s..." (file-name-nondirectory file))
  1069. (condition-case nil
  1070. (progn
  1071. (epg-import-keys-from-file context file)
  1072. (message "Importing %s...done" (file-name-nondirectory file)))
  1073. (error
  1074. (message "Importing %s...failed" (file-name-nondirectory file))))
  1075. (if (epg-context-result-for context 'import)
  1076. (epa-display-info (epg-import-result-to-string
  1077. (epg-context-result-for context 'import))))
  1078. (if (eq major-mode 'epa-key-list-mode)
  1079. (apply #'epa--list-keys epa-list-keys-arguments))))
  1080. ;;;###autoload
  1081. (defun epa-import-keys-region (start end)
  1082. "Import keys from the region."
  1083. (interactive "r")
  1084. (let ((context (epg-make-context epa-protocol)))
  1085. (message "Importing...")
  1086. (condition-case nil
  1087. (progn
  1088. (epg-import-keys-from-string context (buffer-substring start end))
  1089. (message "Importing...done"))
  1090. (error
  1091. (message "Importing...failed")))
  1092. (if (epg-context-result-for context 'import)
  1093. (epa-display-info (epg-import-result-to-string
  1094. (epg-context-result-for context 'import))))))
  1095. ;;;###autoload
  1096. (defun epa-import-armor-in-region (start end)
  1097. "Import keys in the OpenPGP armor format in the current region
  1098. between START and END."
  1099. (interactive "r")
  1100. (save-excursion
  1101. (save-restriction
  1102. (narrow-to-region start end)
  1103. (goto-char start)
  1104. (let (armor-start armor-end)
  1105. (while (re-search-forward
  1106. "-----BEGIN \\(PGP \\(PUBLIC\\|PRIVATE\\) KEY BLOCK\\)-----$"
  1107. nil t)
  1108. (setq armor-start (match-beginning 0)
  1109. armor-end (re-search-forward
  1110. (concat "^-----END " (match-string 1) "-----$")
  1111. nil t))
  1112. (unless armor-end
  1113. (error "No armor tail"))
  1114. (epa-import-keys-region armor-start armor-end))))))
  1115. ;;;###autoload
  1116. (defun epa-export-keys (keys file)
  1117. "Export selected KEYS to FILE."
  1118. (interactive
  1119. (let ((keys (epa--marked-keys))
  1120. default-name)
  1121. (unless keys
  1122. (error "No keys selected"))
  1123. (setq default-name
  1124. (expand-file-name
  1125. (concat (epg-sub-key-id (car (epg-key-sub-key-list (car keys))))
  1126. (if epa-armor ".asc" ".gpg"))
  1127. default-directory))
  1128. (list keys
  1129. (expand-file-name
  1130. (read-file-name
  1131. (concat "To file (default "
  1132. (file-name-nondirectory default-name)
  1133. ") ")
  1134. (file-name-directory default-name)
  1135. default-name)))))
  1136. (let ((context (epg-make-context epa-protocol)))
  1137. (epg-context-set-armor context epa-armor)
  1138. (message "Exporting to %s..." (file-name-nondirectory file))
  1139. (epg-export-keys-to-file context keys file)
  1140. (message "Exporting to %s...done" (file-name-nondirectory file))))
  1141. ;;;###autoload
  1142. (defun epa-insert-keys (keys)
  1143. "Insert selected KEYS after the point."
  1144. (interactive
  1145. (list (epa-select-keys (epg-make-context epa-protocol)
  1146. "Select keys to export.
  1147. If no one is selected, default public key is exported. ")))
  1148. (let ((context (epg-make-context epa-protocol)))
  1149. ;;(epg-context-set-armor context epa-armor)
  1150. (epg-context-set-armor context t)
  1151. (insert (epg-export-keys-to-string context keys))))
  1152. ;; (defun epa-sign-keys (keys &optional local)
  1153. ;; "Sign selected KEYS.
  1154. ;; If a prefix-arg is specified, the signature is marked as non exportable.
  1155. ;; Don't use this command in Lisp programs!"
  1156. ;; (interactive
  1157. ;; (let ((keys (epa--marked-keys)))
  1158. ;; (unless keys
  1159. ;; (error "No keys selected"))
  1160. ;; (list keys current-prefix-arg)))
  1161. ;; (let ((context (epg-make-context epa-protocol)))
  1162. ;; (epg-context-set-passphrase-callback context
  1163. ;; #'epa-passphrase-callback-function)
  1164. ;; (epg-context-set-progress-callback context
  1165. ;; (cons
  1166. ;; #'epa-progress-callback-function
  1167. ;; "Signing keys..."))
  1168. ;; (message "Signing keys...")
  1169. ;; (epg-sign-keys context keys local)
  1170. ;; (message "Signing keys...done")))
  1171. ;; (make-obsolete 'epa-sign-keys "Do not use.")
  1172. (provide 'epa)
  1173. ;;; epa.el ends here