Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / org / org-crypt.el
CommitLineData
8d642074
CD
1;;; org-crypt.el --- Public key encryption for org-mode entries
2
73b0cd50 3;; Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc.
8d642074
CD
4
5;; Emacs Lisp Archive Entry
6;; Filename: org-crypt.el
acedf35c 7;; Version: 7.4
8d642074
CD
8;; Keywords: org-mode
9;; Author: John Wiegley <johnw@gnu.org>
10;; Maintainer: Peter Jones <pjones@pmade.com>
11;; Description: Adds public key encryption to org-mode buffers
12;; URL: http://www.newartisans.com/software/emacs.html
13;; Compatibility: Emacs22
14
15;; This file is part of GNU Emacs.
16;;
17;; GNU Emacs is free software: you can redistribute it and/or modify
18;; it under the terms of the GNU General Public License as published by
19;; the Free Software Foundation, either version 3 of the License, or
20;; (at your option) any later version.
21
22;; GNU Emacs is distributed in the hope that it will be useful,
23;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25;; GNU General Public License for more details.
26
27;; You should have received a copy of the GNU General Public License
28;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
29
30;;; Commentary:
31
32;; Right now this is just a set of functions to play with. It depends
33;; on the epg library. Here's how you would use it:
34;;
35;; 1. To mark an entry for encryption, tag the heading with "crypt".
36;; You can change the tag to any complex tag matching string by
37;; setting the `org-crypt-tag-matcher' variable.
38;;
39;; 2. Set the encryption key to use in the `org-crypt-key' variable,
40;; or use `M-x org-set-property' to set the property CRYPTKEY to
41;; any address in your public keyring. The text of the entry (but
42;; not its properties or headline) will be encrypted for this user.
43;; For them to read it, the corresponding secret key must be
44;; located in the secret key ring of the account where you try to
45;; decrypt it. This makes it possible to leave secure notes that
46;; only the intended recipient can read in a shared-org-mode-files
47;; scenario.
86fbb8ca 48;; If the key is not set, org-crypt will default to symmetric encryption.
8d642074
CD
49;;
50;; 3. To later decrypt an entry, use `org-decrypt-entries' or
51;; `org-decrypt-entry'. It might be useful to bind this to a key,
52;; like C-c C-/. I hope that in the future, C-c C-r can be might
53;; overloaded to also decrypt an entry if it's encrypted, since
54;; that fits nicely with the meaning of "reveal".
55;;
56;; 4. To automatically encrypt all necessary entries when saving a
57;; file, call `org-crypt-use-before-save-magic' after loading
58;; org-crypt.el.
59;;
60;; TODO:
61;; - Allow symmetric encryption as well
62
63;;; Thanks:
64
65;; - Carsten Dominik
66;; - Vitaly Ostanin
67
68(require 'org)
69
86fbb8ca
CD
70;;; Code:
71
8d642074
CD
72(declare-function epg-decrypt-string "epg" (context cipher))
73(declare-function epg-list-keys "epg" (context &optional name mode))
74(declare-function epg-make-context "epg"
75 (&optional protocol armor textmode include-certs
76 cipher-algorithm digest-algorithm
77 compress-algorithm))
78(declare-function epg-encrypt-string "epg"
79 (context plain recipients &optional sign always-trust))
80
81(defgroup org-crypt nil
82 "Org Crypt"
83 :tag "Org Crypt" :group 'org)
84
85(defcustom org-crypt-tag-matcher "crypt"
86fbb8ca
CD
86 "The tag matcher used to find headings whose contents should be encrypted.
87
88See the \"Match syntax\" section of the org manual for more details."
8d642074
CD
89 :type 'string :group 'org-crypt)
90
91(defcustom org-crypt-key nil
86fbb8ca
CD
92 "The default key to use when encrypting the contents of a heading.
93
94This setting can also be overridden in the CRYPTKEY property."
8d642074
CD
95 :type 'string :group 'org-crypt)
96
97(defun org-crypt-key-for-heading ()
86fbb8ca 98 "Return the encryption key for the current heading."
8d642074
CD
99 (save-excursion
100 (org-back-to-heading t)
ed21c5c8 101 (or (org-entry-get nil "CRYPTKEY" 'selective)
8d642074
CD
102 org-crypt-key
103 (and (boundp 'epa-file-encrypt-to) epa-file-encrypt-to)
86fbb8ca 104 (message "No crypt key set, using symmetric encryption."))))
8d642074
CD
105
106(defun org-encrypt-entry ()
107 "Encrypt the content of the current headline."
108 (interactive)
109 (require 'epg)
110 (save-excursion
111 (org-back-to-heading t)
86fbb8ca
CD
112 (let ((start-heading (point)))
113 (forward-line)
114 (when (not (looking-at "-----BEGIN PGP MESSAGE-----"))
115 (let ((folded (org-invisible-p))
116 (epg-context (epg-make-context nil t t))
117 (crypt-key (org-crypt-key-for-heading))
118 (beg (point))
119 end encrypted-text)
120 (goto-char start-heading)
121 (org-end-of-subtree t t)
122 (org-back-over-empty-lines)
123 (setq end (point)
124 encrypted-text
125 (epg-encrypt-string
126 epg-context
127 (buffer-substring-no-properties beg end)
128 (epg-list-keys epg-context crypt-key)))
129 (delete-region beg end)
130 (insert encrypted-text)
131 (when folded
132 (goto-char start-heading)
133 (hide-subtree))
134 nil)))))
8d642074
CD
135
136(defun org-decrypt-entry ()
ed21c5c8 137 "Decrypt the content of the current headline."
8d642074
CD
138 (interactive)
139 (require 'epg)
86fbb8ca
CD
140 (unless (org-before-first-heading-p)
141 (save-excursion
142 (org-back-to-heading t)
143 (forward-line)
144 (when (looking-at "-----BEGIN PGP MESSAGE-----")
145 (let* ((beg (point))
146 (end (save-excursion
147 (search-forward "-----END PGP MESSAGE-----")
148 (forward-line)
149 (point)))
150 (epg-context (epg-make-context nil t t))
151 (decrypted-text
152 (decode-coding-string
153 (epg-decrypt-string
154 epg-context
155 (buffer-substring-no-properties beg end))
156 'utf-8)))
157 (delete-region beg end)
158 (insert decrypted-text)
159 nil)))))
8d642074
CD
160
161(defun org-encrypt-entries ()
ed21c5c8 162 "Encrypt all top-level entries in the current buffer."
8d642074
CD
163 (interactive)
164 (org-scan-tags
165 'org-encrypt-entry
166 (cdr (org-make-tags-matcher org-crypt-tag-matcher))))
167
168(defun org-decrypt-entries ()
ed21c5c8 169 "Decrypt all entries in the current buffer."
8d642074 170 (interactive)
ed21c5c8 171 (org-scan-tags
8d642074
CD
172 'org-decrypt-entry
173 (cdr (org-make-tags-matcher org-crypt-tag-matcher))))
174
175(defun org-crypt-use-before-save-magic ()
86fbb8ca 176 "Add a hook to automatically encrypt entries before a file is saved to disk."
ed21c5c8
CD
177 (add-hook
178 'org-mode-hook
8d642074 179 (lambda () (add-hook 'before-save-hook 'org-encrypt-entries nil t))))
ed21c5c8
CD
180
181(add-hook 'org-reveal-start-hook 'org-decrypt-entry)
182
8d642074
CD
183(provide 'org-crypt)
184
8d642074
CD
185
186;;; org-crypt.el ends here