(require 'font-lock)
(require 'widget)
(eval-when-compile (require 'wid-edit))
+(require 'mail-utils)
+(require 'derived)
(defgroup epa nil
"The EasyPG Assistant"
(delete-window (get-buffer-window epa-keys-buffer)))
(kill-buffer epa-keys-buffer))))
+(defun epa--format-fingerprint-1 (fingerprint unit-size block-size)
+ (let ((unit 0))
+ (with-temp-buffer
+ (insert fingerprint)
+ (goto-char (point-min))
+ (while (progn
+ (goto-char (+ (point) unit-size))
+ (not (eobp)))
+ (setq unit (1+ unit))
+ (insert (if (= (% unit block-size) 0) " " " ")))
+ (buffer-string))))
+
+(defun epa--format-fingerprint (fingerprint)
+ (if fingerprint
+ (if (= (length fingerprint) 40)
+ ;; 1234 5678 9ABC DEF0 1234 5678 9ABC DEF0 1234 5678
+ (epa--format-fingerprint-1 fingerprint 4 5)
+ ;; 12 34 56 78 9A BC DE F0 12 34 56 78 9A BC DE F0
+ (epa--format-fingerprint-1 fingerprint 2 8))))
+
(defun epa--show-key (key)
(let* ((primary-sub-key (car (epg-key-sub-key-list key)))
(entry (assoc (epg-sub-key-id primary-sub-key)
(epg-sub-key-capability (car pointer))
" ")
"\n\tFingerprint: "
- (epg-sub-key-fingerprint (car pointer))
+ (epa--format-fingerprint (epg-sub-key-fingerprint (car pointer)))
"\n")
(setq pointer (cdr pointer)))
(goto-char (point-min))
(epa-display-info (epg-verify-result-to-string
(epg-context-result-for context 'verify))))))
+(defun epa--read-signature-type ()
+ (let (type c)
+ (while (null type)
+ (message "Signature type (n,c,d,?) ")
+ (setq c (read-char))
+ (cond ((eq c ?c)
+ (setq type 'clear))
+ ((eq c ?d)
+ (setq type 'detached))
+ ((eq c ??)
+ (with-output-to-temp-buffer "*Help*"
+ (save-excursion
+ (set-buffer standard-output)
+ (insert "\
+n - Create a normal signature
+c - Create a cleartext signature
+d - Create a detached signature
+? - Show this help
+"))))
+ (t
+ (setq type 'normal))))))
+
;;;###autoload
(defun epa-sign-file (file signers mode)
"Sign FILE by SIGNERS keys selected."
(interactive
(list (expand-file-name (read-file-name "File: "))
- (epa-select-keys (epg-make-context epa-protocol)
- "Select keys for signing.
+ (if current-prefix-arg
+ (epa-select-keys (epg-make-context epa-protocol)
+ "Select keys for signing.
If no one is selected, default secret key is used. "
- nil t)
- (catch 'done
- (while t
- (message "Signature type (n,c,d,?) ")
- (let ((c (read-char)))
- (cond ((eq c ?c)
- (throw 'done 'clear))
- ((eq c ?d)
- (throw 'done 'detached))
- ((eq c ??)
- (with-output-to-temp-buffer "*Help*"
- (save-excursion
- (set-buffer standard-output)
- (insert "\
-n - Create a normal signature
-c - Create a cleartext signature
-d - Create a detached signature
-? - Show this help
-"))))
- (t
- (throw 'done nil))))))))
+ nil t))
+ (if current-prefix-arg
+ (epa--read-signature-type)
+ 'clear)))
(let ((signature (concat file
(if (eq epa-protocol 'OpenPGP)
(if (or epa-armor
(setq coding-system (intern (downcase charset)))
(setq coding-system 'utf-8)))
(let ((coding-system-for-read coding-system))
- (epa-decrypt-region start end)))))))
+ (epa-decrypt-region armor-start armor-end)))))))
+
+;;;###autoload
+(defun epa-decrypt ()
+ "Decrypt OpenPGP armors in the current buffer.
+
+Don't use this command in Lisp programs!"
+ (interactive)
+ (epa-decrypt-armor-in-region (point-min) (point-max)))
(if (fboundp 'select-safe-coding-system)
(defalias 'epa--select-safe-coding-system 'select-safe-coding-system)
(epa-verify-region armor-start armor-end))))))
;;;###autoload
+(defun epa-verify ()
+ "Verify OpenPGP cleartext signed messages in the current buffer.
+
+Don't use this command in Lisp programs!"
+ (epa-verify-cleartext-in-region (point-min) (point-max)))
+
+;;;###autoload
(defun epa-sign-region (start end signers mode)
"Sign the current region between START and END by SIGNERS keys selected.
(progn
(setq epa-last-coding-system-specified
(or coding-system-for-write
- (epa--select-safe-coding-system (region-beginning)
- (region-end))))
+ (epa--select-safe-coding-system
+ (region-beginning) (region-end))))
(list (region-beginning) (region-end)
- (epa-select-keys (epg-make-context epa-protocol)
- "Select keys for signing.
+ (if current-prefix-arg
+ (epa-select-keys (epg-make-context epa-protocol)
+ "Select keys for signing.
If no one is selected, default secret key is used. "
- nil t)
- (catch 'done
- (while t
- (message "Signature type (n,c,d,?) ")
- (let ((c (read-char)))
- (cond ((eq c ?c)
- (throw 'done 'clear))
- ((eq c ?d)
- (throw 'done 'detached))
- ((eq c ??)
- (with-output-to-temp-buffer "*Help*"
- (save-excursion
- (set-buffer standard-output)
- (insert "\
-n - Create a normal signature
-c - Create a cleartext signature
-d - Create a detached signature
-? - Show this help
-"))))
- (t
- (throw 'done nil)))))))))
+ nil t))
+ (if current-prefix-arg
+ (epa--read-signature-type)
+ 'clear))))
(save-excursion
(let ((context (epg-make-context epa-protocol))
signature)
'end-open t)))))
;;;###autoload
+(defun epa-sign (start end signers mode)
+ "Sign the current buffer.
+
+Don't use this command in Lisp programs!"
+ (interactive
+ (progn
+ (goto-char (point-min))
+ (if (and (or (eq major-mode 'mail-mode)
+ (eq (derived-mode-class major-mode) 'mail-mode))
+ (search-forward mail-header-separator nil t))
+ (forward-line))
+ (setq epa-last-coding-system-specified
+ (or coding-system-for-write
+ (epa--select-safe-coding-system (point) (point-max))))
+ (list (point) (point-max)
+ (if current-prefix-arg
+ (epa-select-keys (epg-make-context epa-protocol)
+ "Select keys for signing.
+If no one is selected, default secret key is used. "
+ nil t))
+ (if current-prefix-arg
+ (epa--read-signature-type)
+ 'clear))))
+ (epa-sign-region start end signers mode))
+
+;;;###autoload
(defun epa-encrypt-region (start end recipients)
"Encrypt the current region between START and END for RECIPIENTS.
(progn
(setq epa-last-coding-system-specified
(or coding-system-for-write
- (epa--select-safe-coding-system (region-beginning)
- (region-end))))
+ (epa--select-safe-coding-system
+ (region-beginning) (region-end))))
(list (region-beginning) (region-end)
(epa-select-keys (epg-make-context epa-protocol)
"Select recipients for encryption.
'end-open t)))))
;;;###autoload
+(defun epa-encrypt (start end recipients)
+ "Encrypt the current buffer.
+
+Don't use this command in Lisp programs!"
+ (interactive
+ (let (recipients)
+ (goto-char (point-min))
+ (when (or (eq major-mode 'mail-mode)
+ (eq (derived-mode-class major-mode) 'mail-mode))
+ (save-restriction
+ (narrow-to-region (point)
+ (progn
+ (search-forward mail-header-separator nil 0)
+ (match-beginning 0)))
+ (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]+"))))
+ (goto-char (point-min))
+ (if (search-forward mail-header-separator nil t)
+ (forward-line)))
+ (setq epa-last-coding-system-specified
+ (or coding-system-for-write
+ (epa--select-safe-coding-system (point) (point-max))))
+ (list (point) (point-max)
+ (if current-prefix-arg
+ (epa-select-keys
+ (epg-make-context epa-protocol)
+ "Select recipients for encryption.
+If no one is selected, symmetric encryption will be performed. "
+ recipients)
+ (if recipients
+ (delq nil
+ (apply #'nconc
+ (mapcar
+ (lambda (recipient)
+ (epg-list-keys (epg-make-context epa-protocol)
+ (concat "<" recipient ">")))
+ recipients))))))))
+ (epa-encrypt-region start end recipients))
+
+;;;###autoload
(defun epa-delete-keys (keys &optional allow-secret)
"Delete selected KEYS.
(epg-context-result-for context 'import))))))
;;;###autoload
+(defun epa-import-armor-in-region (start end)
+ "Import keys in the OpenPGP armor format in the current region
+between START and END.
+
+Don't use this command in Lisp programs!"
+ (interactive "r")
+ (save-excursion
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char start)
+ (let (armor-start armor-end)
+ (while (re-search-forward
+ "-----BEGIN \\(PGP \\(PUBLIC\\|PRIVATE\\) KEY BLOCK\\)-----$"
+ nil t)
+ (setq armor-start (match-beginning 0)
+ armor-end (re-search-forward
+ (concat "^-----END " (match-string 1) "-----$")
+ nil t))
+ (unless armor-end
+ (error "No armor tail"))
+ (epa-import-keys-region armor-start armor-end))))))
+
+;;;###autoload
+(defun epa-import ()
+ "Import keys in the OpenPGP armor format in the current buffer.
+
+Don't use this command in Lisp programs!"
+ (interactive)
+ (epa-import-armor-in-region (point-min) (point-max)))
+
+;;;###autoload
(defun epa-export-keys (keys file)
"Export selected KEYS to FILE.