October 24, 2004 11:49 PM
Gnu Privacy Guard (gpg) provides powerful public key cryptography to the
masses. I believe there are a number of applications that provide
support for gpg within emacs. But I just wanted a quick function that
will sign and encrypt a buffer with the recipient as myself. PGG1
has no easy way to do this in Emacs 21.3.1. So I wrote this function
which actually is a minimal version of the actual pgp-encrypt
encrypting the whole buffer with the recipient as self.
Code below updated on 2004.12.05.
;make sure pgg-gpg-user-id is set like so ;(setq pgg-gpg-user-id "Your user id") ;;; emacs-wiki-pgg settings (defgroup emacs-wiki-pgg nil "Options controlling the behavior of Emacs Wiki PGG Interface." :group 'emacs-wiki) (defcustom emacs-wiki-pgg-interface 'pgg-encrypt-show "Interfacing function to invoke pgg with. pgg-encrypt-show asks for recipients via the minibuffer. pgg-encrypt-sign-self encrypts with recipient as self and signs if emacs-wiki-pgg-sign is non-nil." :type 'function :group 'emacs-wiki-pgg) (defcustom emacs-wiki-pgg-sign nil "Signs the message after encrypting if emacs-wiki-pgg-interface is pgg-encrypt-sign-self." :type 'boolean :group 'emacs-wiki-pgg) ;;; PGG Functions (defun pgg-encrypt-sign-self (&optional start end) "Encrypt the current buffer for self. Signs the message if emacs-wiki-pgg-sign is non-nil. If optional arguments START and END are specified, only encrypt within the region." (interactive "*") (let* ((rcpts (list pgg-gpg-user-id)) (start (or start (point-min))) (end (or end (point-max))) (status (pgg-encrypt-region start end rcpts emacs-wiki-pgg-sign))) (pgg-display-output-buffer start end status) status)) (defun pgg-encrypt-show (&optional start end) "Encrypt and sign the current buffer for self. If optional arguments START and END are specified, only encrypt within the region." (interactive "*") (let* ((start (or start (point-min))) (end (or end (point-max)))) (push-mark start t t) (goto-char end) (call-interactively 'pgg-encrypt-region) )) (defun pgg-decrypt-show (&optional start end) "Decrypt the current buffer. If optional arguments START and END are specified, only decrypt within the region." (interactive "*") (let* ((start (or start (point-min))) (end (or end (point-max))) (status (pgg-decrypt-region start end))) (pgg-display-output-buffer start end status) status))
This function can be easily used to act just like the built-in
pgg-encrypt-region
function by wrapping it around another
interactive function which takes point and mark as arguments.
;encrypting version (defun pgg-encrypt-sign-self-region (start end) "Encrypt and sign the current region for self." (interactive "*r") (pgg-encrypt-sign-self start end t)) ;decrypting version (defun pgg-decrypt-self-region (start end) "Decrypt the current region." (interactive "*r") (pgg-encrypt-sign-self start end t))
These two handy functions are useful especially within emacs-wiki
mode. Consider text enclosed between gpg
tags in an emacs-wiki
source file. While in emacs-wiki mode, pressing C-c C-S-e
encrypts
and signs the text between each gpg tag with the recipient as
yourself2. Similarly, C-c C-S-d
decrypts text between each gpg tag. A
simple handler for the gpg tags in emacs-wiki causes text between gpg
tags to be published just like as if they were enclosed in the example
tag.
As an example, consider:
<gpg>Test data</gpg>
Press C-c C-S-e to get:
-----BEGIN PGP MESSAGE----- Version: GnuPG v1.2.4 (GNU/Linux) [Imagine encrypted text] -----END PGP MESSAGE-----
Pressing C-c C-S-d gives:
<gpg>Test data</gpg>
The elisp code to do all this is:
;;; Interactive Emacs Wiki mode Functions (defun emacs-wiki-encrypt-gpg (&optional entirewiki) "Find all gpg tags and encrypt their contents. When called with C-u prefix, encrypt entire buffer." (interactive "P") (if entirewiki (funcall emacs-wiki-pgg-interface) (let (tagbegin tagend) (save-excursion (goto-char 0) (while (re-search-forward "<gpg>" nil t) (setq tagbegin (match-end 0)) (re-search-forward "</gpg>" nil t) (setq tagend (match-beginning 0)) (funcall emacs-wiki-pgg-interface tagbegin tagend)))))) (defun emacs-wiki-decrypt-gpg (&optional entirewiki) "Find all gpg tags and decrypt their contents. When called with C-u prefix, decrypt entire buffer." (interactive "P") (if entirewiki (pgg-decrypt-show) (let (tagbegin tagend) (save-excursion (goto-char 0) (while (re-search-forward "<gpg>" nil t) (setq tagbegin (match-end 0)) (if (re-search-forward "</gpg>" nil t) (progn (setq tagend (match-beginning 0)) (pgg-decrypt-show tagbegin tagend)) (message "No closing gpg tags found"))))))) ;key bindings (define-key emacs-wiki-mode-map [(control ?c) (control ?E)] 'emacs-wiki-encrypt-gpg) (define-key emacs-wiki-mode-map [(control ?c) (control ?D)] 'emacs-wiki-decrypt-gpg) ;wiki handler of gpg tag (defun emacs-wiki-gpg-tag (beg end highlight-p) (if highlight-p (progn (emacs-wiki-multiline-maybe beg end) (goto-char end)) (insert "<pre class=\"example\">") (when (< (point) end) (goto-char end)) (insert "</pre>") (add-text-properties beg end '(rear-nonsticky (read-only) read-only t)))) (push '("gpg" t nil t emacs-wiki-gpg-tag) emacs-wiki-markup-tags)
Another implementation of these functions is to rewrite
emacs-wiki-gpg-tag
function in such a way that it encrypts the data
between the tags. This way, you have unencrypted data in your wiki
source file and encrypted data in your published html file between
gpge
tags. The code to do that is:
;wiki handler of gpge tag (defun emacs-wiki-gpg-encrypt-tag (beg end highlight-p) (if highlight-p (progn (emacs-wiki-multiline-maybe beg end) (goto-char end)) (insert "<pre class=\"example\">") (pgg-encrypt-sign-self (point) end t) (when (< (point) end) (goto-char end)) (insert "</pre>") (add-text-properties beg (point) '(rear-nonsticky (read-only) read-only t)))) (push '("gpge" t nil t emacs-wiki-gpg-encrypt-tag) emacs-wiki-markup-tags)
[1] PGG is an interface library between Emacs and various
tools for secure communication. PGG also provides a simple user
interface to encrypt, decrypt, sign, and verify MIME messages.
[2] This, of course can be customized.