epa.el 44 KB

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