EasyPG

EasyPG is an all-in-one GnuPG interface for Emacs. It has two aspects: convenient tools which allow to use GnuPG from Emacs (EasyPG Assistant), and a fully functional interface library to GnuPG (EasyPG Library).

Homepage:

Files

Setup for transparent, automatic encryption and decryption:

    (require 'epa-file)
    (epa-file-enable)

Now visit anything.gpg and it will encrypt it when you save the buffer.

See AutoEncryption for alternatives.

Using symmetric encryption always

To prevent EPG from prompting for a key every time you save a file, put the following at the top of your file:

    -*- epa-file-encrypt-to: ("your@email.address") -*-

EPA will prompt for the key only the first time you save the file, assuming you have the email address you specified in your keyring.

The following comments are outdated as of Emacs 23:

epa-file will prompt for which key to use for encryption each time you save a .gpg file. The following patch will stop it prompting, and cause it to always use symmetric encryption:

--- Backup/epa-file.el.~1~	2006-12-20 07:33:07.000000000 +0100
+++ epa-file.el	2007-02-11 13:57:20.000000000 +0100
@@ -186,13 +186,14 @@
 		 (epa-file--encode-coding-string (buffer-substring start end)
 						 coding-system))
 	       (unless (assoc file epa-file-passphrase-alist)
-		 (epa-select-keys
+		 '(epa-select-keys
 		  context
 		  "Select recipents for encryption.
 If no one is selected, symmetric encryption will be performed.  "
 		  (cond
 		   ((listp epa-file-encrypt-to) epa-file-encrypt-to)
-		   ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to)))))))
+		   ((stringp epa-file-encrypt-to) (list epa-file-encrypt-to))))
+		 nil)))
       (error
        (if (setq entry (assoc file epa-file-passphrase-alist))
 	   (setcdr entry nil))

The above patch appears to be included in Emacs 23.

Comments

Note that easy-pg consists of two different kind of modules, one is a library (epg.el) and the others are applications (epa-*.el). Auto-encryption (epa-file.el) is a part of the latter. As the docs says “The EasyPG Library dares to disable passphrase caching”, that is intended behavior. Caveat user, if you start using the library directly. ;)

How to use a non-graphical password prompt for gpg

In X, Emacs 23 seems to pop up a graphical window to ask you the keyphrase. How to let it ask the password in minibuffer?


I found the cause for it. The graphical window appears if you run gpg with the --use-agent option. EasyPG adds it (see epg.el) if it sees an environment variable like this one: GPG_AGENT_INFO=/tmp/seahorse-nDQm50/S.gpg-agent:6321:1 (check that with the env command). And you have this variable if for instance you have the program seahorse installed and running (which is the case in Ubuntu). If you uninstall Seahorse, the prompt will always be text instead of graphical. You may have to relogin to X to force Seahorse to close. --DanielClemente


I have the same problem. And in console emacs23 can pop up nothing, so it hang there, you have to use “C-g” quit it. For my gentoo system, I compile the package ‘pinentry’ without gtk qt3 ncurses. It caused emacs23 hang both in X or console. I notice that pinentry did not have the readline USE in recent version.

I found the thread to fix it. http://www.nabble.com/gnupg-interface-td17242718.html

1. Install the latest GnuPG 1.x along with 2.x and let epg-gpg-program to point the executable, or

2. Use other pinentry-program which interact through the windowing system


I generally don’t mind the graphical password prompt when I’m at my desk, but when logged into a remote terminal with multi-tty this can be darn inconvenient (I have to VNC into my desktop just to enter the password!)

Here is my solution that turns off the use of the agent in these cases: http://www.enigmacurry.com/2009/01/14/extending-emacs-with-advice/


How about (setenv “GPG_AGENT_INFO” nil) Note: another form is: (setenv (concat “GPG_AGENT_INFO” nil))

- this did it for me in emacs 23 : nice solution.


Yes but when you use the command line the pinentry widget will popup.

On the Gnupg homepage: GnuPG comes in two flavours: 1.4.9 is the well known and portable standalone version, whereas 2.0.11 is the enhanced and somewhat harder to build version.

IMHO The best solution seem to use the 1.4.9 version.

--ThierryVolpiatto?


Uninstalling seahorse doesn’t work for me (gentoo) - even though GPG_AGENT_INFO is unset I still get the graphical password prompt *scowl*


I use this to temporarily unset the GPG_AGENT_INFO environment variable if running in terminal:

    ;; Do not use gpg agent when runing in terminal
    (defadvice epg--start (around advice-epg-disable-agent activate)
      (let ((agent (getenv "GPG_AGENT_INFO")))
        (when (not (display-graphic-p))
          (setenv "GPG_AGENT_INFO" nil))
        ad-do-it
        (when (not (display-graphic-p))
          (setenv "GPG_AGENT_INFO" agent))))

If you use emacsclient and sometimes over plaintext ssh, sometimes in X, this will alter the behavious on-the-fly:

    (defadvice epg--start (around advice-epg-disable-agent disable)
      "Don't allow epg--start to use gpg-agent in plain text
    terminals."
      (if (display-graphic-p)
          ad-do-it
        (let ((agent (getenv "GPG_AGENT_INFO")))
          (setenv "GPG_AGENT_INFO" nil) ; give us a usable text password prompt
          ad-do-it
          (setenv "GPG_AGENT_INFO" agent))))
    (ad-enable-advice 'epg--start 'around 'advice-epg-disable-agent)
    (ad-activate 'epg--start)

Note also there’s a bug in pinentry in GnuPG2, if you run Arch Linux you could install gnupg1 and do (when (file-executable-p "/usr/bin/gpg1") (setq epg-gpg-program "/usr/bin/gpg1")) to make it use gpg1 on your Arch boxen.


I have removed ‘gpg-agent’. Of course, it totally solved the problem with the GUI dialog. In Ubuntu, ‘gpg-agent’ is used by default as a replacement for ‘ssh-agent’. When ‘gpg-agent’ is deleted, ‘ssh-agent’ is used. So, no visible losses. --DmitriMinaev


There’s another, more straightforward solution, which should yield the desired result with both gpg1 and gpg2, and doesn’t require you to disable the GPG agent. Add the following line to ~/.gnupg/gpg-agent.conf:

    pinentry-program /usr/bin/pinentry-curses

Kludging GPG_TTY to get appropriate pinentry for each terminal or GUI frame

gpg-agent adheres to DISPLAY if set, and GPG_TTY if otherwise, to decide where and how to perform pinentry. If you use emacs --daemon with a mix of GUI and console terminal, GPG_TTY was probably inherited from emacs --daemon’s shell and will be totally irrelevant and wrong; on the other hand, if you open even one GUI emacsclient frame at any time, gpg-agent/pinentry will attempt to use that frame’s setting of DISPLAY. So I made this small function to manipulate DISPLAY and GPG_TTY when the user changes emacsclients.

(defun wg/kludge-gpg-agent
    ()
  (if
      (display-graphic-p)
      (setenv "DISPLAY"
              (terminal-name))
    (setenv "GPG_TTY"
            (terminal-name))
    (setenv "DISPLAY")))

(add-hook 'window-configuration-change-hook 'wg/kludge-gpg-agent)

N.B.: This hack used to use after-make-frame-functions, but window-configuration-change-hook works more smoothly, as it now handles the case of switching between existing emacsclient frames as well as making new ones.

--wgreenhouse

Problems Decrypting

With Emacs 23 and the default epg that comes bundled. I am able to save (and encrypt) a *.gpg file, but when I try to reopen it in emacs, I get the following: ‘File exists, but cannot be read’. I am able to decrypt it fine outside of emacs with gpg -d Running ‘M-x epa-decrypt-file RET FILENAME’ on the same file gives the following error: ‘Decrypting test4.gpg…0% (0/674) epg-decrypt-file: Wrong type argument: listp, exit ‘

 Any thoughts or comments would be much appreciated!!

You can use public key to save(encrypt) a *.gpg file, and only use private key to (re)open(or decrypt) it. If you are the public key’s owner, you can use command

   gpg -o [fn] --export-private-keys -a

to get it and import it to your system.


I was getting the error ‘File exists, but cannot be read’ because emacs could not find the gpg command.

Another way to test if emacs can find it would be to do M-x epa-list-keys

 -johan


With Emacs 23 epa-list-keys was working correctly but trying to open a gpg file gave me the error: ‘File exists, but cannot be read’ Downgrading to gpg 1.4.11 from 2.0.16 allowed me to open gpg files again.

 -goibhniu

goibhniu: I think this may be a problem with the gpg-agent. I’ve had it on a Mac and was able to fix it by uninstalling and reinstalling GPG Tools. Here are some useful links:

http://comments.gmane.org/gmane.emacs.bugs/65815 (Hehe, apparently rms himself ran into a problem.)

http://support.gpgtools.org/discussions/everything/2128-gpg-error

 -dm

One reason for ‘File exists, but cannot be read’ can be that it cannot find gpg. It is a shame that the error message is so bad.

To fix, you can either set epg-gpg-program to the full path (e.g. /sw/bin/gpg2) or set it to a relative path (e.g. gpg2) and make sure that exec-path contains the right directory. Setting $PATH from inside Emacs is NOT adequate, it has to be in exec-path. (Setting $PATH outside Emacs would probably do but with Emacs.app invoked from Finder that might not be convenient.)

 -rjk

Problems Encrypting Mails

I found a problem when I use Wanderlust Version 201107150352 with EasyPG 0.0.16(is this the last one?). I changed Wanderlust throught the emacs customization to put a default “Bcc” pointing to my own mail so I have copies of whatever I send.

    ; In ~/.emacs says:
    '(wl-bcc "My name <my-mail@the-server.com>

When I try to send an encrypted mail, for example to myself, it’s says something like

    "No public key for my-mail@the-server.com,my-mail@the-server.com; skip it?".

To solve this problem, you must download the source code of epg, and edit epa-mail.el. In the implementation of the function epa-mail-encrypt:

    ;;;###autoload
    (defun epa-mail-encrypt (start end recipients sign signers)

there are some lines that says as follow:

       (if recipients
           (setq recipients (delete ""
                                    (split-string recipients "[ \t\n]+"))))

Just change them to this ones:

       (if recipients
           (setq recipients (delete ""
                                    (split-string recipients "[, \t\n]+"))))

Customized the function epa-mail-encrypt (EasyPG version 23.1; Emacs 23.4.1) to encrypt a body of the Gnus message (compatible with the mymail-crypt Chrome extension):

(require 'epa-mail)

(defun epa-mail-encrypt-message ()
  "Encrypt the current mail message."
  (interactive)
  (save-excursion
    (let ((verbose current-prefix-arg)
          (context (epg-make-context epa-protocol)))

      (goto-char (point-min))
      (save-restriction
        (setq recipients
              (mail-strip-quoted-names
               (mapconcat #'identity
                          (nconc (mail-fetch-field "to" nil nil t)
                                 (mail-fetch-field "cc" nil nil t)
                                 (mail-fetch-field "bcc" nil nil t))
                          ","))))
      (if recipients
          (setq recipients (delete ""
                                   (split-string recipients "[, \t\n]+"))))
      (setq epa-last-coding-system-specified
            (or coding-system-for-write
                (epa--select-safe-coding-system (point) (point-max))))
      (let ((recipient-keys
             (if verbose
                 (epa-select-keys
                  context "Select recipients for encryption."
                  recipients)
               (if recipients
                   (mapcar
                    (lambda (recipient)
                      (setq recipient-key
                            (epa-mail--find-usable-key
                             (epg-list-keys
                              (epg-make-context epa-protocol)
                              (concat "<" recipient ">"))
                             'encrypt))
                      (unless (or recipient-key
                                  (y-or-n-p
                                   (format
                                    "No public key for %s; skip it? "
                                    recipient)))
                        (error "No public key for %s" recipient))
                      recipient-key)
                    recipients)))))
        (print recipient-keys)
        (message-goto-body)
        (epa-encrypt-region (point) (point-max) recipient-keys nil nil)))))

;; run as the last when the message buffer has been initialized
(add-hook
 'message-setup-hook
 (lambda ()
   (define-key message-mode-map "\C-c\C-mcb" 'epa-mail-encrypt-message)))


Documentation

Being difficult to find it online I decided to extract and publish the EasyPG Assistant User’s Manual found within the package of Emacs 23.1.

You can find the manual here:

- http://virgo977virgo.blogspot.com/2009/09/easypg-assistant-users-manual-from.html

- http://www.gnu.org/software/emacs/manual/epa.html

Gnus

AFAIK Gnus now prefers EasyPG for mail encryption (over PGG, mailcrypt…).

A working customization code (April 2011, using Debian, Emacs 23, No Gnus 0.16 (git version) and GnuPG 1) follows:

(require 'epg-config)
 (setq mml2015-use 'epg

       mml2015-verbose t
       epg-user-id gpgpgpkeyID
       mml2015-encrypt-to-self t
       mml2015-always-trust nil
       mml2015-cache-passphrase t
       mml2015-passphrase-cache-expiry '36000
       mml2015-sign-with-sender t

       gnus-message-replyencrypt t
       gnus-message-replysign t
       gnus-message-replysignencrypted t
       gnus-treat-x-pgp-sig t

;;       mm-sign-option 'guided
;;       mm-encrypt-option 'guided
       mm-verify-option 'always
       mm-decrypt-option 'always

       gnus-buttonized-mime-types
       '("multipart/alternative"
         "multipart/encrypted"
         "multipart/signed")

      epg-debug t ;;  then read the *epg-debug*" buffer
)

To solve problems first suppress any “encrypt-to” in your ~/.gnupg/gpg.conf (beware: it can lead to new problems because you may therefore produce cyphered files/mail NOT cyphered using your key)

OS X

I could not get decrypting to work in emacs on OS X - emacs would background a pinentry-curses process which I wouldn’t be able to access, since emacs was not launched from a terminal. Having installed MacGPG2 I get a graphical prompt for my gpg key.

 -sh

Caching Password for Symmetric Encription

Warning! This is risky if other people than you can access your own session. Despite you should always have to lock the screen when you leave your computer turned on, it is recommended you use this with caution.

For some reason, using Emacs 24 and enabling epa-file-cache-passphrase-for-symmetric-encryption doesn’t work and this is so because there’s no elisp code for handling passphrase at the epg library (that have the base functions to interact with GPG tool).

So we need to edit epg--start function adding this behaviour. Apply this patch to the epg.el file:

*** epg.el	2014-11-14 18:42:27.809875834 -0300
--- epg-modified.el	2014-11-14 18:42:59.660206317 -0300
***************
*** 1140,1145 ****
--- 1140,1148 ----
  		       (if (and (not (eq (epg-context-protocol context) 'CMS))
  				(epg-context-progress-callback context))
  			   '("--enable-progress-filter"))
+ 		       (if (and (not (eq (epg-context-protocol context) 'CMS))
+ 				(epg-context-passphrase-callback context))
+ 			   '("--passphrase-fd" "0"))
  		       (if epg-gpg-home-directory
  			   (list "--homedir" epg-gpg-home-directory))
  		       (unless (eq (epg-context-protocol context) 'CMS)
***************
*** 1191,1199 ****
  			 epg-gpg-program)
  		       args)))
        (set-default-file-modes orig-mode))
      (set-process-filter process #'epg--process-filter)
!     (epg-context-set-process context process)))
  
  (defun epg--process-filter (process input)
    (if epg-debug
        (save-excursion
--- 1194,1224 ----
  			 epg-gpg-program)
  		       args)))
        (set-default-file-modes orig-mode))
+     (process-sending-password process context)
      (set-process-filter process #'epg--process-filter)
!     (epg-context-set-process context process)
!     ))
! 
  
+ (defun process-sending-password (process context)
+   (let ((passphrase (funcall
+ 		     (car (epg-context-passphrase-callback context))
+ 		     context 
+ 		     'SYM
+ 		     (cdr (epg-context-passphrase-callback context))))
+ 	)
+     (process-send-string process (concat passphrase "\n"))    
+     )
+   (with-current-buffer (process-buffer process)
+     (save-excursion
+       (goto-char (point-min))
+       (when (search-forward "DECRYPTION_FAILED" nil t)
+ 	(message "Decryption Failed... Password may be wrong?")
+ 	(setq epa-file-passphrase-alist nil)
+ 	)
+       )
+     )
+   )
  (defun epg--process-filter (process input)
    (if epg-debug
        (save-excursion

CategoryCryptography CategoryInterface