Fixed.
[elisp/epg.git] / epg.el
diff --git a/epg.el b/epg.el
index 13156bc..4cf1a67 100644 (file)
--- a/epg.el
+++ b/epg.el
@@ -39,7 +39,7 @@
   :group 'epg
   :type 'string)
 
-(defconst epg-version-number "0.0.1")
+(defconst epg-version-number "0.0.4")
 
 (defvar epg-user-id nil
   "GnuPG ID of your default identity.")
@@ -48,6 +48,7 @@
   "An alist mapping from key ID to user ID.")
 
 (defvar epg-read-point nil)
+(defvar epg-process-filter-running nil)
 (defvar epg-pending-status-list nil)
 (defvar epg-key-id nil)
 (defvar epg-context nil)
@@ -759,15 +760,14 @@ This function is for internal use only."
           ((eq (epg-signature-status signature) 'no-pubkey)
            "No public key for "))
      (epg-signature-key-id signature)
-     " "
      (if user-id
-        (concat (if (stringp user-id)
+        (concat " "
+                (if (stringp user-id)
                     user-id
-                  (epg-decode-dn user-id))
-                " ")
+                  (epg-decode-dn user-id)))
        "")
      (if (epg-signature-validity signature)
-        (format "(trust %s)"  (epg-signature-validity signature))
+        (format " (trust %s)"  (epg-signature-validity signature))
        ""))))
 
 (defun epg-verify-result-to-string (verify-result)
@@ -829,6 +829,8 @@ This function is for internal use only."
     (with-current-buffer buffer
       (make-local-variable 'epg-read-point)
       (setq epg-read-point (point-min))
+      (make-local-variable 'epg-process-filter-running)
+      (setq epg-process-filter-running nil)
       (make-local-variable 'epg-pending-status-list)
       (setq epg-pending-status-list nil)
       (make-local-variable 'epg-key-id)
@@ -861,21 +863,26 @@ This function is for internal use only."
        (set-buffer (process-buffer process))
        (goto-char (point-max))
        (insert input)
-       (goto-char epg-read-point)
-       (beginning-of-line)
-       (while (looking-at ".*\n")      ;the input line finished
-         (save-excursion
-           (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
-               (let* ((status (match-string 1))
-                      (string (match-string 2))
-                      (symbol (intern-soft (concat "epg--status-" status))))
-                 (if (member status epg-pending-status-list)
-                     (setq epg-pending-status-list nil))
-                 (if (and symbol
-                          (fboundp symbol))
-                     (funcall symbol process string)))))
-         (forward-line))
-       (setq epg-read-point (point)))))
+       (unless epg-process-filter-running
+         (unwind-protect
+             (progn
+               (setq epg-process-filter-running t)
+               (goto-char epg-read-point)
+               (beginning-of-line)
+               (while (looking-at ".*\n") ;the input line finished
+                 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
+                     (let* ((status (match-string 1))
+                            (string (match-string 2))
+                            (symbol (intern-soft (concat "epg--status-"
+                                                         status))))
+                       (if (member status epg-pending-status-list)
+                           (setq epg-pending-status-list nil))
+                       (if (and symbol
+                                (fboundp symbol))
+                           (funcall symbol epg-context string))))
+                 (forward-line)
+                 (setq epg-read-point (point))))
+           (setq epg-process-filter-running nil))))))
 
 (defun epg-read-output (context)
   "Read the output file CONTEXT and return the content as a string."
@@ -913,7 +920,7 @@ This function is for internal use only."
           (file-exists-p (epg-context-output-file context)))
       (delete-file (epg-context-output-file context))))
 
-(defun epg--status-USERID_HINT (process string)
+(defun epg--status-USERID_HINT (context string)
   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
       (let* ((key-id (match-string 1 string))
             (user-id (match-string 2 string))
@@ -923,17 +930,17 @@ This function is for internal use only."
          (setq epg-user-id-alist (cons (cons key-id user-id)
                                        epg-user-id-alist))))))
 
-(defun epg--status-NEED_PASSPHRASE (process string)
+(defun epg--status-NEED_PASSPHRASE (context string)
   (if (string-match "\\`\\([^ ]+\\)" string)
       (setq epg-key-id (match-string 1 string))))
 
-(defun epg--status-NEED_PASSPHRASE_SYM (process string)
+(defun epg--status-NEED_PASSPHRASE_SYM (context string)
   (setq epg-key-id 'SYM))
 
-(defun epg--status-NEED_PASSPHRASE_PIN (process string)
+(defun epg--status-NEED_PASSPHRASE_PIN (context string)
   (setq epg-key-id 'PIN))
 
-(defun epg--status-GET_HIDDEN (process string)
+(defun epg--status-GET_HIDDEN (context string)
   (if (and epg-key-id
           (string-match "\\`passphrase\\." string))
       (let (inhibit-quit
@@ -944,73 +951,72 @@ This function is for internal use only."
                (progn
                  (setq passphrase
                        (funcall
-                        (if (consp (epg-context-passphrase-callback
-                                    epg-context))
-                            (car (epg-context-passphrase-callback
-                                  epg-context))
-                          (epg-context-passphrase-callback epg-context))
-                        epg-context
+                        (if (consp (epg-context-passphrase-callback context))
+                            (car (epg-context-passphrase-callback context))
+                          (epg-context-passphrase-callback context))
+                        context
                         epg-key-id
-                        (if (consp (epg-context-passphrase-callback
-                                    epg-context))
-                            (cdr (epg-context-passphrase-callback
-                                  epg-context)))))
+                        (if (consp (epg-context-passphrase-callback context))
+                            (cdr (epg-context-passphrase-callback context)))))
                  (when passphrase
                    (setq passphrase-with-new-line (concat passphrase "\n"))
                    (fillarray passphrase 0)
                    (setq passphrase nil)
-                   (process-send-string process passphrase-with-new-line)))
+                   (process-send-string (epg-context-process context)
+                                        passphrase-with-new-line)))
              (quit
               (epg-context-set-result-for
-               epg-context 'error
+               context 'error
                (cons '(quit)
-                     (epg-context-result-for epg-context 'error)))
-              (delete-process process)))
+                     (epg-context-result-for context 'error)))
+              (delete-process (epg-context-process context))))
          (if passphrase
              (fillarray passphrase 0))
          (if passphrase-with-new-line
              (fillarray passphrase-with-new-line 0))))))
 
-(defun epg--status-GET_BOOL (process string)
+(defun epg--status-GET_BOOL (context string)
   (let ((entry (assoc string epg-prompt-alist))
        inhibit-quit)
     (condition-case nil
       (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
-         (process-send-string process "y\n")
-       (process-send-string process "n\n"))
+         (process-send-string (epg-context-process context) "y\n")
+       (process-send-string (epg-context-process context) "n\n"))
       (quit
        (epg-context-set-result-for
-       epg-context 'error
+       context 'error
        (cons '(quit)
-             (epg-context-result-for epg-context 'error)))
-       (delete-process process)))))
+             (epg-context-result-for context 'error)))
+       (delete-process (epg-context-process context))))))
 
-(defun epg--status-GET_LINE (process string)
+(defun epg--status-GET_LINE (context string)
   (let ((entry (assoc string epg-prompt-alist))
        inhibit-quit)
     (condition-case nil
-       (process-send-string
-        process
-        (concat (read-string (if entry (cdr entry) (concat string ": ")))
-                "\n"))
+       (process-send-string (epg-context-process context)
+                            (concat (read-string
+                                     (if entry
+                                         (cdr entry)
+                                       (concat string ": ")))
+                                    "\n"))
       (quit
        (epg-context-set-result-for
-       epg-context 'error
+       context 'error
        (cons '(quit)
-             (epg-context-result-for epg-context 'error)))
-       (delete-process process)))))
+             (epg-context-result-for context 'error)))
+       (delete-process (epg-context-process context))))))
 
-(defun epg--status-*SIG (status string)
+(defun epg--status-*SIG (context status string)
   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
       (let* ((key-id (match-string 1 string))
             (user-id (match-string 2 string))
             (entry (assoc key-id epg-user-id-alist)))
        (epg-context-set-result-for
-        epg-context
+        context
         'verify
         (cons (epg-make-signature status key-id)
-              (epg-context-result-for epg-context 'verify)))
-       (if (eq (epg-context-protocol epg-context) 'CMS)
+              (epg-context-result-for context 'verify)))
+       (if (eq (epg-context-protocol context) 'CMS)
            (condition-case nil
                (setq user-id (epg-dn-from-string user-id))
              (error)))
@@ -1019,38 +1025,48 @@ This function is for internal use only."
          (setq epg-user-id-alist
                (cons (cons key-id user-id) epg-user-id-alist))))
     (epg-context-set-result-for
-     epg-context
+     context
      'verify
      (cons (epg-make-signature status)
-          (epg-context-result-for epg-context 'verify)))))
+          (epg-context-result-for context 'verify)))))
 
-(defun epg--status-GOODSIG (process string)
-  (epg--status-*SIG 'good string))
+(defun epg--status-GOODSIG (context string)
+  (epg--status-*SIG context 'good string))
 
-(defun epg--status-EXPSIG (process string)
-  (epg--status-*SIG 'expired string))
+(defun epg--status-EXPSIG (context string)
+  (epg--status-*SIG context 'expired string))
 
-(defun epg--status-EXPKEYSIG (process string)
-  (epg--status-*SIG 'expired-key string))
+(defun epg--status-EXPKEYSIG (context string)
+  (epg--status-*SIG context 'expired-key string))
 
-(defun epg--status-REVKEYSIG (process string)
-  (epg--status-*SIG 'revoked-key string))
+(defun epg--status-REVKEYSIG (context string)
+  (epg--status-*SIG context 'revoked-key string))
 
-(defun epg--status-BADSIG (process string)
-  (epg--status-*SIG 'bad string))
+(defun epg--status-BADSIG (context string)
+  (epg--status-*SIG context 'bad string))
 
-(defun epg--status-NO_PUBKEY (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-NO_PUBKEY (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
-            (eq (epg-signature-status signature) 'error))
+            (eq (epg-signature-status signature) 'error)
+            (equal (epg-signature-key-id signature) string))
        (epg-signature-set-status signature 'no-pubkey))))
 
-(defun epg--status-ERRSIG (process string)
+(defun epg--time-from-seconds (seconds)
+  (let ((number-seconds (string-to-number (concat seconds ".0"))))
+    (cons (floor (/ number-seconds 65536))
+         (floor (mod number-seconds 65536)))))
+
+(defun epg--status-ERRSIG (context string)
   (if (string-match "\\`\\([^ ]+\\) \\([0-9]+\\) \\([0-9]+\\) \
 \\([0-9A-Fa-f][0-9A-Fa-f]\\) \\([^ ]+\\) \\([0-9]+\\)"
                    string)
       (let ((signature (epg-make-signature 'error)))
-       (epg-context-set-result-for epg-context 'verify (list signature))
+       (epg-context-set-result-for
+        context
+        'verify
+        (cons signature
+              (epg-context-result-for context 'verify)))
        (epg-signature-set-key-id
         signature
         (match-string 1 string))
@@ -1065,10 +1081,10 @@ This function is for internal use only."
         (string-to-number (match-string 4 string) 16))
        (epg-signature-set-creation-time
         signature
-        (match-string 5 string)))))
+        (epg--time-from-seconds (match-string 5 string))))))
 
-(defun epg--status-VALIDSIG (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-VALIDSIG (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (when (and signature
               (eq (epg-signature-status signature) 'good)
               (string-match "\\`\\([^ ]+\\) [^ ]+ \\([^ ]+\\) \\([^ ]+\\) \
@@ -1080,10 +1096,10 @@ This function is for internal use only."
        (match-string 1 string))
       (epg-signature-set-creation-time
        signature
-       (match-string 2 string))
+       (epg--time-from-seconds (match-string 2 string)))
       (epg-signature-set-expiration-time
        signature
-       (match-string 3 string))
+       (epg--time-from-seconds (match-string 3 string)))
       (epg-signature-set-version
        signature
        (string-to-number (match-string 4 string)))
@@ -1097,141 +1113,142 @@ This function is for internal use only."
        signature
        (string-to-number (match-string 7 string) 16)))))
 
-(defun epg--status-TRUST_UNDEFINED (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-TRUST_UNDEFINED (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
             (eq (epg-signature-status signature) 'good))
        (epg-signature-set-validity signature 'undefined))))
 
-(defun epg--status-TRUST_NEVER (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-TRUST_NEVER (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
             (eq (epg-signature-status signature) 'good))
        (epg-signature-set-validity signature 'never))))
 
-(defun epg--status-TRUST_MARGINAL (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-TRUST_MARGINAL (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
             (eq (epg-signature-status signature) 'marginal))
        (epg-signature-set-validity signature 'marginal))))
 
-(defun epg--status-TRUST_FULLY (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-TRUST_FULLY (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
             (eq (epg-signature-status signature) 'good))
        (epg-signature-set-validity signature 'full))))
 
-(defun epg--status-TRUST_ULTIMATE (process string)
-  (let ((signature (car (epg-context-result-for epg-context 'verify))))
+(defun epg--status-TRUST_ULTIMATE (context string)
+  (let ((signature (car (epg-context-result-for context 'verify))))
     (if (and signature
             (eq (epg-signature-status signature) 'good))
        (epg-signature-set-validity signature 'ultimate))))
 
-(defun epg--status-PROGRESS (process string)
+(defun epg--status-PROGRESS (context string)
   (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
                    string)
-      (funcall (if (consp (epg-context-progress-callback epg-context))
-                  (car (epg-context-progress-callback epg-context))
-                (epg-context-progress-callback epg-context))
-              epg-context
+      (funcall (if (consp (epg-context-progress-callback context))
+                  (car (epg-context-progress-callback context))
+                (epg-context-progress-callback context))
+              context
               (match-string 1 string)
               (match-string 2 string)
               (string-to-number (match-string 3 string))
               (string-to-number (match-string 4 string))
-              (if (consp (epg-context-progress-callback epg-context))
-                  (cdr (epg-context-progress-callback epg-context))))))
+              (if (consp (epg-context-progress-callback context))
+                  (cdr (epg-context-progress-callback context))))))
 
-(defun epg--status-DECRYPTION_FAILED (process string)
+(defun epg--status-DECRYPTION_FAILED (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons '(decryption-failed)
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-NODATA (process string)
+(defun epg--status-NODATA (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons (list 'no-data (cons 'reason (string-to-number string)))
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-UNEXPECTED (process string)
+(defun epg--status-UNEXPECTED (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons (list 'unexpected (cons 'reason (string-to-number string)))
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-KEYEXPIRED (process string)
+(defun epg--status-KEYEXPIRED (context string)
   (epg-context-set-result-for
-   epg-context 'error
-   (cons (list 'key-expired (cons 'expiration-time string))
-        (epg-context-result-for epg-context 'error))))
+   context 'error
+   (cons (list 'key-expired (cons 'expiration-time
+                                 (epg--time-from-seconds string)))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-KEYREVOKED (process string)
+(defun epg--status-KEYREVOKED (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons '(key-revoked)
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-BADARMOR (process string)
+(defun epg--status-BADARMOR (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons '(bad-armor)
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-INV_RECP (process string)
+(defun epg--status-INV_RECP (context string)
   (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
       (epg-context-set-result-for
-       epg-context 'error
+       context 'error
        (cons (list 'invalid-recipient
                   (cons 'reason
                         (string-to-number (match-string 1 string)))
                   (cons 'requested-recipient
                         (match-string 2 string)))
-            (epg-context-result-for epg-context 'error)))))
+            (epg-context-result-for context 'error)))))
 
-(defun epg--status-NO_RECP (process string)
+(defun epg--status-NO_RECP (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons '(no-recipients)
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-DELETE_PROBLEM (process string)
+(defun epg--status-DELETE_PROBLEM (context string)
   (if (string-match "\\`\\([0-9]+\\)" string)
       (epg-context-set-result-for
-       epg-context 'error
+       context 'error
        (cons (list 'delete-problem
                   (cons 'reason (string-to-number (match-string 1 string))))
-            (epg-context-result-for epg-context 'error)))))
+            (epg-context-result-for context 'error)))))
 
-(defun epg--status-SIG_CREATED (process string)
+(defun epg--status-SIG_CREATED (context string)
   (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
       (epg-context-set-result-for
-       epg-context 'sign
+       context 'sign
        (cons (epg-make-new-signature
              (cdr (assq (aref (match-string 1 string) 0)
                         epg-new-signature-type-alist))
              (string-to-number (match-string 2 string))
              (string-to-number (match-string 3 string))
              (string-to-number (match-string 4 string) 16)
-             (match-string 5 string)
+             (epg--time-from-seconds (match-string 5 string))
              (substring string (match-end 0)))
-            (epg-context-result-for epg-context 'sign)))))
+            (epg-context-result-for context 'sign)))))
 
-(defun epg--status-KEY_CREATED (process string)
+(defun epg--status-KEY_CREATED (context string)
   (if (string-match "\\`\\([BPS]\\) \\([^ ]+\\)" string)
       (epg-context-set-result-for
-       epg-context 'generate-key
+       context 'generate-key
        (cons (list (cons 'type (string-to-char (match-string 1 string)))
                   (cons 'fingerprint (match-string 2 string)))
-            (epg-context-result-for epg-context 'generate-key)))))
+            (epg-context-result-for context 'generate-key)))))
 
-(defun epg--status-KEY_NOT_CREATED (process string)
+(defun epg--status-KEY_NOT_CREATED (context string)
   (epg-context-set-result-for
-   epg-context 'error
+   context 'error
    (cons '(key-not-created)
-        (epg-context-result-for epg-context 'error))))
+        (epg-context-result-for context 'error))))
 
-(defun epg--status-IMPORTED (process string)
+(defun epg--status-IMPORTED (context string)
   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
       (let* ((key-id (match-string 1 string))
             (user-id (match-string 2 string))
@@ -1241,13 +1258,13 @@ This function is for internal use only."
          (setq epg-user-id-alist (cons (cons key-id user-id)
                                        epg-user-id-alist)))
        (epg-context-set-result-for
-        epg-context 'import
+        context 'import
         (cons (list (cons 'key-id key-id)
                     (cons 'user-id user-id))
-              (epg-context-result-for epg-context 'import))))))
+              (epg-context-result-for context 'import))))))
 
-(defun epg--status-IMPORT_OK (process string)
-  (let ((result (epg-context-result-for epg-context 'import)))
+(defun epg--status-IMPORT_OK (context string)
+  (let ((result (epg-context-result-for context 'import)))
     (if (and result
             (string-match "\\`\\([0-9]+\\)\\( \\(.+\\)\\)?" string))
        (setcar result
@@ -1259,10 +1276,10 @@ This function is for internal use only."
                                        (match-string 3 string))))
                        (car result))))))
 
-(defun epg--status-IMPORT_PROBLEM (process string)
+(defun epg--status-IMPORT_PROBLEM (context string)
   (if (string-match "\\`\\([0-9]+\\)\\( \\(.+\\)\\)?" string)
       (epg-context-set-result-for
-       epg-context 'error
+       context 'error
        (cons (cons 'import-problem
                   (append (list (cons 'reason
                                       (string-to-number
@@ -1270,7 +1287,7 @@ This function is for internal use only."
                           (if (match-beginning 2)
                               (list (cons 'fingerprint
                                           (match-string 3 string))))))
-            (epg-context-result-for epg-context 'error)))))
+            (epg-context-result-for context 'error)))))
 
 (defun epg-passphrase-callback-function (context key-id handback)
   (if (eq key-id 'SYM)
@@ -1288,6 +1305,7 @@ This function is for internal use only."
                                               handback)
   (message "%s: %d%%/%d%%" what current total))
 
+;;;###autoload
 (defun epg-configuration ()
   "Return a list of internal configuration parameters of `epg-gpg-program'."
   (let (config type)
@@ -1308,6 +1326,26 @@ This function is for internal use only."
                           config))))
     config))
 
+;;;###autoload
+(defun epg-check-configuration (configuration)
+  "Verify that CONFIGURATION is sufficient."
+  (let ((entry (assq 'version configuration))
+       major minor teeny)
+    (unless (and entry
+                (stringp (cdr entry))
+                (string-match "\\`\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)"
+                              (cdr entry)))
+      (error "Undetermined version: %S" entry))
+    (setq major (string-to-number (match-string 1 (cdr entry)))
+         minor (string-to-number (match-string 2 (cdr entry)))
+         teeny (string-to-number (match-string 3 (cdr entry))))
+    (unless (or (> major 1)
+               (and (= major 1)
+                    (or (> minor 4)
+                        (and (= minor 4)
+                             (>= teeny 3)))))
+      (error "Unsupported version: %s" (cdr entry)))))
+
 (defun epg--list-keys-1 (context name mode)
   (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
                            "--with-fingerprint"
@@ -1351,8 +1389,8 @@ This function is for internal use only."
    (string-to-number (aref line 3))
    (string-to-number (aref line 2))
    (aref line 4)
-   (aref line 5)
-   (aref line 6)))
+   (epg--time-from-seconds (aref line 5))
+   (epg--time-from-seconds (aref line 6))))
 
 ;;;###autoload
 (defun epg-list-keys (context &optional name mode)
@@ -1407,8 +1445,8 @@ signatures should be included."
                          epg-key-validity-alist)))
           (string-to-number (aref (car lines) 3))
           (aref (car lines) 4)
-          (aref (car lines) 5)
-          (aref (car lines) 6)
+          (epg--time-from-seconds (aref (car lines) 5))
+          (epg--time-from-seconds (aref (car lines) 6))
           (aref (car lines) 9)
           (string-to-number (aref (car lines) 10) 16)
           (eq (aref (aref (car lines) 10) 2) ?x))
@@ -1764,9 +1802,13 @@ If you are unsure, use synchronous version of this function
                     (if sign
                         (cons "--sign"
                               (apply #'nconc
-                                     (mapcar (lambda (signer)
-                                               (list "-u" signer))
-                                             (epg-context-signers context)))))
+                                     (mapcar
+                                      (lambda (signer)
+                                        (list "-u"
+                                              (epg-sub-key-id
+                                               (car (epg-key-sub-key-list
+                                                     signer)))))
+                                      (epg-context-signers context)))))
                     (apply #'nconc
                            (mapcar
                             (lambda (recipient)
@@ -1898,7 +1940,9 @@ If you are unsure, use synchronous version of this function
 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
   (epg-context-set-operation context 'import-keys)
   (epg-context-set-result context nil)
-  (epg--start context (list "--import" (epg-data-file keys)))
+  (epg--start context (if (epg-data-file keys)
+                         (list "--import" (epg-data-file keys))
+                       (list "--import")))
   (when (epg-data-string keys)
     (if (eq (process-status (epg-context-process context)) 'run)
        (process-send-string (epg-context-process context)