Bug 1637458 - Implement "message security info" for received OpenPGP messages. r=PatrickBrunschwig,mkmelin a=wsmwk
authorKai Engert <kaie@kuix.de>
Mon, 11 May 2020 16:58:15 +0200
changeset 39037 1e4fca1274f33c5ceca5dd9f8363a339e16d853b
parent 39036 9fca35e15ac48caa904855c1a32eaf3133892bd0
child 39038 099d4b4bb77c368a5477186037fc68af757f2cc3
push id401
push userclokep@gmail.com
push dateMon, 01 Jun 2020 20:41:59 +0000
reviewersPatrickBrunschwig, mkmelin, wsmwk
bugs1637458
Bug 1637458 - Implement "message security info" for received OpenPGP messages. r=PatrickBrunschwig,mkmelin a=wsmwk Differential Revision: https://phabricator.services.mozilla.com/D74988
mail/base/content/msgHdrView.inc.xhtml
mail/extensions/openpgp/content/modules/RNP.jsm
mail/extensions/openpgp/content/modules/RNPLib.jsm
mail/extensions/openpgp/content/modules/constants.jsm
mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
mail/extensions/openpgp/content/strings/msgReadStatus.dtd
mail/extensions/openpgp/content/strings/msgReadStatus.properties
mail/extensions/openpgp/content/ui/enigmailCommon.js
mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
mail/extensions/openpgp/content/ui/enigmailMsgHdrViewOverlay.js
mail/extensions/openpgp/content/ui/msgReadStatus.js
mail/extensions/openpgp/content/ui/msgReadStatus.xhtml
mail/extensions/openpgp/jar.mn
mail/extensions/smime/content/msgHdrViewSMIMEOverlay.js
mail/locales/en-US/chrome/messenger-smime/msgReadSecurityInfo.dtd
mail/themes/linux/mail/smime/msgReadSecurityInfo.css
mail/themes/osx/mail/smime/msgReadSecurityInfo.css
mail/themes/shared/jar.inc.mn
mail/themes/shared/openpgp/msgReadStatus.css
mail/themes/windows/mail/smime/msgReadSecurityInfo.css
mailnews/extensions/smime/content/msgReadSMIMEOverlay.js
mailnews/extensions/smime/content/msgReadSecurityInfo.js
mailnews/extensions/smime/content/msgReadSecurityInfo.xhtml
--- a/mail/base/content/msgHdrView.inc.xhtml
+++ b/mail/base/content/msgHdrView.inc.xhtml
@@ -429,17 +429,17 @@
                                                         aria-labelledby="expandeduser-agentLabel"/>
                                     </html:td>
                                   </html:tr>
                                 </html:table>
 
                                 <!-- perhaps this should be a customizable toolbar too -->
                                 <vbox id="otherActionsBox" align="end">
                                   <hbox id="dateValueBox" align="start">
-                                    <hbox id="smimeBox" collapsed="true">
+                                    <hbox id="cryptoBox" collapsed="true">
                                       <image id="signedHdrIcon"
                                              onclick="showMessageReadSecurityInfo();" collapsed="true"/>
                                       <image id="encryptedHdrIcon"
                                              onclick="showMessageReadSecurityInfo();" collapsed="true"/>
                                     </hbox>
                                     <label id="dateLabel" class="dateLabel" flex="1" role="textbox"
                                            aria-readonly="true"/>
                                   </hbox>
--- a/mail/extensions/openpgp/content/modules/RNP.jsm
+++ b/mail/extensions/openpgp/content/modules/RNP.jsm
@@ -253,17 +253,16 @@ var RNP = {
         if (keyObj) {
           keys.push(keyObj);
         }
       }
 
       RNPLib.rnp_identifier_iterator_destroy(iter);
     }
 
-    console.debug(keys);
     return keys;
   },
 
   // return false if handle refers to subkey and should be ignored
   getKeyInfoFromHandle(ffi, handle, keyObj, usePrimaryIfSubkey, forListing) {
     keyObj.ownerTrust = null;
     keyObj.userId = null;
     keyObj.userIds = [];
@@ -605,26 +604,32 @@ var RNP = {
 
     let result = {};
     result.decryptedData = "";
     result.statusFlags = 0;
     result.extStatusFlags = 0;
 
     result.userId = "";
     result.keyId = "";
+    result.encToDetails = "";
 
     let verify_op = new RNPLib.rnp_op_verify_t();
     result.exitCode = RNPLib.rnp_op_verify_create(
       verify_op.address(),
       RNPLib.ffi,
       input_from_memory,
       output_to_memory
     );
 
+    RNPLib.password_cb_collected_info = {};
     result.exitCode = RNPLib.rnp_op_verify_execute(verify_op);
+    let rnplib_context = RNPLib.password_cb_collected_info;
+    if (rnplib_context.context == "decrypt") {
+      result.encToDetails = rnplib_context.keyId;
+    }
 
     let useDecryptedData;
     let processSignature;
     switch (result.exitCode) {
       case RNPLib.RNP_SUCCESS:
         useDecryptedData = true;
         processSignature = true;
         break;
@@ -633,19 +638,33 @@ var RNP = {
         useDecryptedData = true;
         processSignature = false;
         break;
       case RNPLib.RNP_ERROR_SIGNATURE_EXPIRED:
         useDecryptedData = true;
         processSignature = false;
         result.statusFlags |= EnigmailConstants.EXPIRED_SIGNATURE;
         break;
+      case RNPLib.RNP_ERROR_DECRYPT_FAILED:
+        useDecryptedData = false;
+        processSignature = false;
+        result.statusFlags |= EnigmailConstants.DECRYPTION_FAILED;
+        break;
+      case RNPLib.RNP_ERROR_NO_SUITABLE_KEY:
+        useDecryptedData = false;
+        processSignature = false;
+        result.statusFlags |=
+          EnigmailConstants.DECRYPTION_FAILED | EnigmailConstants.NO_SECKEY;
+        break;
       default:
         useDecryptedData = false;
         processSignature = false;
+        console.debug(
+          "rnp_op_verify_execute returned unexpected: " + result.exitCode
+        );
         break;
     }
 
     if (useDecryptedData) {
       let result_buf = new ctypes.uint8_t.ptr();
       let result_len = new ctypes.size_t();
       let rv = RNPLib.rnp_output_memory_get_buf(
         output_to_memory,
@@ -817,60 +836,68 @@ var RNP = {
       }
 
       let useUndecided = true;
 
       if (keyInfo.secretAvailable) {
         if (fromMatchesAnyUid) {
           result.extStatusFlags |= EnigmailConstants.EXT_SELF_IDENTITY;
           useUndecided = false;
+        } else {
+          result.statusFlags |= EnigmailConstants.INVALID_RECIPIENT;
+          useUndecided = true;
         }
       } else if (result.statusFlags & EnigmailConstants.GOOD_SIGNATURE) {
-        let acceptanceResult = {};
-        try {
-          await PgpSqliteDb2.getAcceptance(
-            keyInfo.fpr,
-            fromLower,
-            acceptanceResult
-          );
-        } catch (ex) {
-          console.debug("getAcceptance failed: " + ex);
-        }
-
-        // unverified key acceptance means, we consider the signature OK,
-        //   but it's not a trusted identity.
-        // unverified signature means, we cannot decide if the signature
-        //   is ok.
+        if (!fromMatchesAnyUid) {
+          /* At the time the user had accepted the key,
+           * a different set of email addresses might have been
+           * contained inside the key. In the meantime, we might
+           * have refreshed the key, a email addresses
+           * might have been removed or revoked.
+           * If the current from was removed/revoked, we'd still
+           * get an acceptance match, but the from is no longer found
+           * in the key's UID list. That should get "undecided".
+           */
+          result.statusFlags |= EnigmailConstants.INVALID_RECIPIENT;
+          useUndecided = true;
+        } else {
+          let acceptanceResult = {};
+          try {
+            await PgpSqliteDb2.getAcceptance(
+              keyInfo.fpr,
+              fromLower,
+              acceptanceResult
+            );
+          } catch (ex) {
+            console.debug("getAcceptance failed: " + ex);
+          }
 
-        if (
-          "emailDecided" in acceptanceResult &&
-          acceptanceResult.emailDecided &&
-          "fingerprintAcceptance" in acceptanceResult &&
-          acceptanceResult.fingerprintAcceptance != "undecided"
-        ) {
-          if (acceptanceResult.fingerprintAcceptance == "rejected") {
-            result.statusFlags &= ~EnigmailConstants.GOOD_SIGNATURE;
-            result.statusFlags |= EnigmailConstants.BAD_SIGNATURE;
-            useUndecided = false;
-          } else if (!fromMatchesAnyUid) {
-            /* At the time the user had accepted the key,
-             * a different set of email addresses might have been
-             * contained inside the key. In the meantime, we might
-             * have refreshed the key, a email addresses
-             * might have been removed or revoked.
-             * If the current from was removed/revoked, we'd still
-             * get an acceptance match, but the from is no longer found
-             * in the key's UID list. That should get "undecided".
-             */
-            useUndecided = true;
-          } else if (acceptanceResult.fingerprintAcceptance == "verified") {
-            result.statusFlags |= EnigmailConstants.TRUSTED_IDENTITY;
-            useUndecided = false;
-          } else if (acceptanceResult.fingerprintAcceptance == "unverified") {
-            useUndecided = false;
+          // unverified key acceptance means, we consider the signature OK,
+          //   but it's not a trusted identity.
+          // unverified signature means, we cannot decide if the signature
+          //   is ok.
+
+          if (
+            "emailDecided" in acceptanceResult &&
+            acceptanceResult.emailDecided &&
+            "fingerprintAcceptance" in acceptanceResult &&
+            acceptanceResult.fingerprintAcceptance != "undecided"
+          ) {
+            if (acceptanceResult.fingerprintAcceptance == "rejected") {
+              result.statusFlags &= ~EnigmailConstants.GOOD_SIGNATURE;
+              result.statusFlags |=
+                EnigmailConstants.BAD_SIGNATURE |
+                EnigmailConstants.INVALID_RECIPIENT;
+              useUndecided = false;
+            } else if (acceptanceResult.fingerprintAcceptance == "verified") {
+              result.statusFlags |= EnigmailConstants.TRUSTED_IDENTITY;
+              useUndecided = false;
+            } else if (acceptanceResult.fingerprintAcceptance == "unverified") {
+              useUndecided = false;
+            }
           }
         }
       }
 
       if (useUndecided) {
         result.statusFlags &= ~EnigmailConstants.GOOD_SIGNATURE;
         result.statusFlags |= EnigmailConstants.UNCERTAIN_SIGNATURE;
       }
@@ -1133,23 +1160,25 @@ var RNP = {
       flags,
       jsonInfo.address()
     );
 
     // TODO: parse jsonInfo and return a list of keys,
     // as seen in keyRing.importKeyAsync.
     // (should prevent the incorrect popup "no keys imported".)
 
+    /*
     if (!rv) {
       console.debug(
         "result key listing, rv= %s, result= %s",
         rv,
         jsonInfo.readString()
       );
     }
+    */
 
     RNPLib.rnp_buffer_destroy(jsonInfo);
     RNPLib.rnp_input_destroy(input_from_memory);
 
     return rv;
   },
 
   isSimpleASCII(str) {
@@ -2046,18 +2075,16 @@ var RNP = {
     let result_len = new ctypes.size_t();
     let exitCode = RNPLib.rnp_output_memory_get_buf(
       out_final,
       result_buf.address(),
       result_len.address(),
       false
     );
 
-    console.debug(exitCode);
-
     if (!exitCode) {
       let char_array = ctypes.cast(
         result_buf,
         ctypes.char.array(result_len.value).ptr
       ).contents;
       result = char_array.readString();
     }
 
--- a/mail/extensions/openpgp/content/modules/RNPLib.jsm
+++ b/mail/extensions/openpgp/content/modules/RNPLib.jsm
@@ -237,21 +237,76 @@ function enableRNPLibJS() {
       this.rnp_output_destroy(out2);
 
       output_to_path = null;
       out2 = null;
     },
 
     keep_password_cb_alive: null,
 
+    password_cb_collected_info: {},
+
     password_cb(ffi, app_ctx, key, pgp_context, buf, buf_len) {
-      console.log(
-        "in RNPLib.password_cb, context: " + pgp_context.readString()
-      );
-      console.log("max_len: " + buf_len);
+      // Before we fullfil the request, we collect context information.
+
+      RNPLib.password_cb_collected_info.context = pgp_context.readString();
+
+      if (RNPLib.password_cb_collected_info.context == "decrypt") {
+        // Get the key ID of the key used to decrypt. If it's a subkey,
+        // we use the ID of the primary key.
+
+        let usePrimaryHandle = false;
+        let primaryHandle = null;
+
+        let is_subkey = new ctypes.bool();
+        if (RNPLib.rnp_key_is_sub(key, is_subkey.address())) {
+          throw new Error("rnp_key_is_sub failed");
+        }
+        if (is_subkey.value) {
+          let primary_grip = new ctypes.char.ptr();
+          if (RNPLib.rnp_key_get_primary_grip(key, primary_grip.address())) {
+            throw new Error("rnp_key_get_primary_grip failed");
+          }
+          if (!primary_grip.isNull()) {
+            primaryHandle = new RNPLib.rnp_key_handle_t();
+            if (
+              RNPLib.rnp_locate_key(
+                ffi,
+                "grip",
+                primary_grip,
+                primaryHandle.address()
+              )
+            ) {
+              throw new Error("rnp_locate_key failed");
+            }
+            if (!primaryHandle.isNull()) {
+              usePrimaryHandle = true;
+            }
+            RNPLib.rnp_buffer_destroy(primary_grip);
+          }
+        }
+
+        let key_id = new ctypes.char.ptr();
+        if (
+          RNPLib.rnp_key_get_keyid(
+            usePrimaryHandle ? primaryHandle : key,
+            key_id.address()
+          )
+        ) {
+          throw new Error("rnp_key_get_keyid failed");
+        }
+        RNPLib.password_cb_collected_info.keyId = key_id.readString();
+        RNPLib.rnp_buffer_destroy(key_id);
+
+        if (primaryHandle) {
+          RNPLib.rnp_key_handle_destroy(primaryHandle);
+        }
+      }
+
+      // Now do what we've been asked to do.
 
       let pass = OpenPGPMasterpass.retrieveOpenPGPPassword();
       var passCTypes = ctypes.char.array()(pass); // UTF-8
       let passLen = passCTypes.length;
 
       if (buf_len < passLen) {
         return false;
       }
--- a/mail/extensions/openpgp/content/modules/constants.jsm
+++ b/mail/extensions/openpgp/content/modules/constants.jsm
@@ -108,18 +108,35 @@ var EnigmailConstants = {
   PHOTO_AVAILABLE: 0x02000000,
   OVERFLOWED: 0x04000000,
   CARDCTRL: 0x08000000,
   SC_OP_FAILURE: 0x10000000,
   UNKNOWN_ALGO: 0x20000000,
   SIG_CREATED: 0x40000000,
   END_ENCRYPTION: 0x80000000,
 
+  /* Extended status flags */
   EXT_SELF_IDENTITY: 0x00000001,
 
+  /* UI message status flags */
+  MSG_SIG_NONE: 0,
+  MSG_SIG_VALID_SELF: 1,
+  MSG_SIG_VALID_KEY_VERIFIED: 2,
+  MSG_SIG_VALID_KEY_UNVERIFIED: 3,
+  MSG_SIG_UNCERTAIN_KEY_UNAVAILABLE: 4,
+  MSG_SIG_UNCERTAIN_UID_MISMATCH: 5,
+  MSG_SIG_UNCERTAIN_KEY_NOT_ACCEPTED: 6,
+  MSG_SIG_INVALID: 7,
+  MSG_SIG_INVALID_KEY_REJECTED: 8,
+
+  MSG_ENC_NONE: 0,
+  MSG_ENC_OK: 1,
+  MSG_ENC_FAILURE: 2,
+  MSG_ENC_NO_SECRET_KEY: 3,
+
   /*** key handling functions ***/
 
   EXTRACT_SECRET_KEY: 0x01,
 
   /* Keyserver Action Flags */
   SEARCH_KEY: 1,
   DOWNLOAD_KEY: 2,
   UPLOAD_KEY: 3,
--- a/mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
+++ b/mail/extensions/openpgp/content/modules/mimeDecrypt.jsm
@@ -561,16 +561,17 @@ MimeDecryptHandler.prototype = {
       if (!options.fromAddr) {
         var win2 = Services.wm.getMostRecentWindow(null);
         options.fromAddr = EnigmailDecryption.getFromAddr(win2);
       }
 
       const cApi = EnigmailCryptoAPI();
       EnigmailLog.DEBUG("mimeDecrypt.jsm: got API: " + cApi.api_name + "\n");
       this.returnStatus = cApi.sync(cApi.decryptMime(this.outQueue, options));
+
       if (!this.returnStatus) {
         this.returnStatus = {
           decryptedData: "",
           exitCode: -1,
           statusFlags: EnigmailConstants.DECRYPTION_FAILED,
         };
       }
 
new file mode 100644
--- /dev/null
+++ b/mail/extensions/openpgp/content/strings/msgReadStatus.dtd
@@ -0,0 +1,9 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!ENTITY ViewSignerKey "View signer key">
+<!ENTITY ViewYourEncryptionKey "View your recipient key">
+
+<!-- LOCALIZATION NOTE(OpenPGP): This a name for a technical standard. You should not translate it, but if applicable, you may write it using localized characters. -->
+<!ENTITY OpenPGP "OpenPGP">
new file mode 100644
--- /dev/null
+++ b/mail/extensions/openpgp/content/strings/msgReadStatus.properties
@@ -0,0 +1,22 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+NoSig=No Digital Signature
+UncertainSig=Uncertain Digital Signature
+InvalidSig=Invalid Digital Signature
+GoodSig=Good Digital Signature
+
+SigUncertainNoKey=This message contains a digital signature, but it is uncertain if it is correct. To verify the signature, you need to obtain a copy of the sender's public key.
+SigUncertainUidMismatch=This message contains a digital signature, but a mismatch was detected. The message was sent from an email address that doesn't match the signer's public key.
+SigUncertainNotAccepted=This message contains a digital signature, but you haven't yet decided if the signer's key is acceptable to you.
+SigInvalidRejected=This message contains a digital signature, but you have previously decided to reject the signer key.
+SigInvalidTechnicalProblem=This message contains a digital signature, but a technical error was detected. Either the message has been corrupted, or the message has been modified by someone else.
+SigValidUnverified=This message includes a valid digital signature from a key that you have already accepted. However, you have not yet verified that the key is really owned by the sender.
+SigValidVerified=This message includes a valid digital signature from a verified key.
+SigValidOwnKey=This message includes a valid digital signature from your personal key.
+
+#SenderAddress=Sender's email address: %s
+
+SigKeyId=Signer key ID: %S
+EncKeyId=Recipient key ID: %S
--- a/mail/extensions/openpgp/content/ui/enigmailCommon.js
+++ b/mail/extensions/openpgp/content/ui/enigmailCommon.js
@@ -145,17 +145,16 @@ const ENIG_IMG_NOT_SELECTED = "chrome://
 const ENIG_IMG_SELECTED = "chrome://openpgp/content/ui/check1.png";
 const ENIG_IMG_DISABLED = "chrome://openpgp/content/ui/check2.png";
 
 // UsePGPMimeOption values
 const PGP_MIME_NEVER = 0;
 const PGP_MIME_POSSIBLE = 1;
 const PGP_MIME_ALWAYS = 2;
 
-const ENIG_POSSIBLE_PGPMIME = EnigmailConstants.POSSIBLE_PGPMIME;
 const ENIG_PGP_DESKTOP_ATT = -2082;
 
 var gUsePGPMimeOptionList = [
   "usePGPMimeNever",
   "usePGPMimePossible",
   "usePGPMimeAlways",
 ];
 
--- a/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMessengerOverlay.js
@@ -203,23 +203,25 @@ Enigmail.msg = {
         }
       }
     }
 
     Enigmail.msg.messagePane = document.getElementById("messagepane");
 
     EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Startup\n");
 
+    /*
     // Override SMIME ui
     overrideAttribute(
       ["cmd_viewSecurityStatus"],
       "Enigmail.msg.viewSecurityInfo(null, true);",
       "",
       ""
     );
+    */
 
     // Override print command
     var printElementIds = [
       "cmd_print",
       "cmd_printpreview",
       "key_print",
       "button-print",
       "mailContext-print",
@@ -305,16 +307,17 @@ Enigmail.msg = {
 
     EnigmailMsgRead.ensureExtraAddonHeaders();
     gMessageListeners.push(Enigmail.msg.messageListener);
     Enigmail.msg.messageListener.onEndHeaders();
   },
 
   messageListener: {
     onStartHeaders() {
+      Enigmail.hdrView.reset();
       Enigmail.msg.mimeParts = null;
       let b = document.getElementById("openpgpKeyBox");
       b.setAttribute("hidden", true);
       b.removeAttribute("keydata");
 
       let b2 = document.getElementById("signatureKeyBox");
       b2.setAttribute("hidden", true);
       b2.removeAttribute("keyid");
@@ -327,42 +330,33 @@ Enigmail.msg = {
       if ("openpgp" in gExpandedHeaderView) {
         delete gExpandedHeaderView.openpgp;
       }
     },
     onEndHeaders() {},
     onEndAttachments() {},
   },
 
+  /*
   viewSecurityInfo(event, displaySmimeMsg) {
     EnigmailLog.DEBUG("enigmailMessengerOverlay.js: viewSecurityInfo\n");
 
     if (event && event.button !== 0) {
       return;
     }
 
     if (gSignatureStatus >= 0 || gEncryptionStatus >= 0) {
       showMessageReadSecurityInfo();
     } else if (Enigmail.msg.securityInfo) {
       this.viewOpenpgpInfo();
     } else {
       showMessageReadSecurityInfo();
     }
   },
-
-  viewOpenpgpInfo() {
-    if (Enigmail.msg.securityInfo) {
-      // Thunderbird
-      EnigmailDialog.info(
-        window,
-        EnigmailLocale.getString("securityInfo") +
-          Enigmail.msg.securityInfo.statusInfo
-      );
-    }
-  },
+  */
 
   clearLastMessage() {
     const { EnigmailSingletons } = ChromeUtils.import(
       "chrome://openpgp/content/modules/singletons.jsm"
     );
     EnigmailSingletons.clearLastDecryptedMessage();
   },
 
--- a/mail/extensions/openpgp/content/ui/enigmailMsgHdrViewOverlay.js
+++ b/mail/extensions/openpgp/content/ui/enigmailMsgHdrViewOverlay.js
@@ -2,17 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  */
 
 "use strict";
 
 /* Globals from Thunderbird: */
-/* global gFolderDisplay: false, currentAttachments: false, gSMIMEContainer: false, gSignedUINode: false, gEncryptedUINode: false */
+/* global gFolderDisplay: false, currentAttachments: false, gCryptoContainer: false, gSignedUINode: false, gEncryptedUINode: false */
 /* global gDBView: false, msgWindow: false, messageHeaderSink: false, gMessageListeners: false, findEmailNodeFromPopupNode: true */
 /* global gExpandedHeaderView: false, CanDetachAttachments: true, gEncryptedURIService: false, FillAttachmentListPopup: false */
 /* global attachmentList: false, MailOfflineMgr: false, currentHeaderData: false, ContentTypeIsSMIME: false */
 
 /* import-globals-from ../BondOpenPGP.jsm */
 
 var EnigmailCore = ChromeUtils.import(
   "chrome://openpgp/content/modules/core.jsm"
@@ -88,22 +88,31 @@ var EnigmailCompat = ChromeUtils.import(
   "chrome://openpgp/content/modules/compat.jsm"
 ).EnigmailCompat;
 
 if (!Enigmail) {
   var Enigmail = {};
 }
 
 Enigmail.hdrView = {
-  //enigmailBox: null,
   lastEncryptedMsgKey: null,
   lastEncryptedUri: null,
   flexbuttonAction: null,
-  isEncrypted: "",
-  isSigned: "",
+
+  msgSignatureState: EnigmailConstants.MSG_SIG_NONE,
+  msgEncryptionState: EnigmailConstants.MSG_ENC_NONE,
+  msgSignatureKeyId: "",
+  msgEncryptionKeyId: "",
+
+  reset() {
+    this.msgSignatureState = EnigmailConstants.MSG_SIG_NONE;
+    this.msgEncryptionState = EnigmailConstants.MSG_ENC_NONE;
+    this.msgSignatureKeyId = "";
+    this.msgEncryptionKeyId = "";
+  },
 
   hdrViewLoad() {
     EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.hdrViewLoad\n");
 
     // THE FOLLOWING OVERRIDES CODE IN msgHdrViewOverlay.js
     // which wouldn't work otherwise
 
     this.origCanDetachAttachments = CanDetachAttachments;
@@ -130,18 +139,16 @@ Enigmail.hdrView = {
     if (encryptedHdrElement) {
       encryptedHdrElement.setAttribute(
         "onclick",
         "Enigmail.msg.viewSecurityInfo(event, true);"
       );
     }
     */
 
-    //this.enigmailBox = document.getElementById("enigmailBox");
-
     let addrPopup = document.getElementById("emailAddressPopup");
     if (addrPopup) {
       addrPopup.addEventListener(
         "popupshowing",
         Enigmail.hdrView.displayAddressPopup.bind(addrPopup)
       );
     }
 
@@ -158,41 +165,54 @@ Enigmail.hdrView = {
   displayAddressPopup(event) {
     let target = event.target;
     EnigmailFuncs.collapseAdvanced(target, "hidden");
   },
 
   statusBarHide() {
     /* elements might not have been set yet, so we try and ignore */
     try {
-      this.isSigned = null;
-      this.isEncrypted = null;
-      //this.enigmailBox.setAttribute("collapsed", "true");
+      this.reset();
 
       Enigmail.msg.setAttachmentReveal(null);
       if (Enigmail.msg.securityInfo) {
         Enigmail.msg.securityInfo.statusFlags = 0;
-        Enigmail.msg.securityInfo.msgSigned = 0;
-        Enigmail.msg.securityInfo.msgEncrypted = 0;
       }
 
-      //let enigMsgPane = document.getElementById("enigmailMsgDisplay");
       let bodyElement = document.getElementById("messagepane");
-      //enigMsgPane.setAttribute("collapsed", true);
       bodyElement.removeAttribute("collapsed");
     } catch (ex) {
       console.debug(ex);
     }
   },
 
-  setStatusText(txt) {
-    // TODO: replace with other information display, tracker bug 1595227
-    if (txt) {
-      console.debug(txt);
+  viewOpenpgpInfo() {
+    let params = {};
+    params.msgSignatureState = this.msgSignatureState;
+    params.msgEncryptionState = this.msgEncryptionState;
+    params.msgSignatureKeyId = this.msgSignatureKeyId;
+    params.msgEncryptionKeyId = this.msgEncryptionKeyId;
+    params.from = "";
+
+    if ("from" in currentHeaderData) {
+      try {
+        params.from = EnigmailFuncs.stripEmail(
+          currentHeaderData.from.headerValue
+        ).toLowerCase();
+      } catch (ex) {
+        console.debug(ex);
+      }
     }
+
+    window.openDialog(
+      "chrome://openpgp/content/ui/msgReadStatus.xhtml",
+      "",
+      "chrome,resizable,modal,dialog,centerscreen",
+      params
+    );
   },
 
   updateHdrIcons(
     exitCode,
     statusFlags,
     extStatusFlags,
     keyId,
     userId,
@@ -224,27 +244,27 @@ Enigmail.hdrView = {
       Enigmail.msg.securityInfo &&
       Enigmail.msg.securityInfo.xtraStatus &&
       Enigmail.msg.securityInfo.xtraStatus === "wks-request"
     ) {
       return;
     }
     */
 
-    //this.enigmailBox = document.getElementById("enigmailBox");
-
     if (
       gFolderDisplay.selectedMessageUris &&
       gFolderDisplay.selectedMessageUris.length > 0
     ) {
       this.lastEncryptedMsgKey = gFolderDisplay.selectedMessageUris[0];
     }
 
     if (!errorMsg) {
       errorMsg = "";
+    } else {
+      console.debug("OpenPGP error status: " + errorMsg);
     }
 
     var replaceUid = null;
     if (keyId && gFolderDisplay.selectedMessage) {
       replaceUid = EnigmailMsgRead.matchUidToSender(
         keyId,
         gFolderDisplay.selectedMessage.author
       );
@@ -268,24 +288,22 @@ Enigmail.hdrView = {
 
     if (userId && replaceUid) {
       // no EnigConvertGpgToUnicode() here; strings are already UTF-8
       replaceUid = replaceUid.replace(/\\[xe]3a/gi, ":");
       errorMsg = errorMsg.replace(userId, replaceUid);
     }
 
     var errorLines = "";
-    var fullStatusInfo = "";
 
     if (exitCode == EnigmailConstants.POSSIBLE_PGPMIME) {
       exitCode = 0;
     } else if (errorMsg) {
       // no EnigConvertGpgToUnicode() here; strings are already UTF-8
       errorLines = errorMsg.split(/\r?\n/);
-      fullStatusInfo = errorMsg;
     }
 
     if (errorLines && errorLines.length > 22) {
       // Retain only first twenty lines and last two lines of error message
       var lastLines =
         errorLines[errorLines.length - 2] +
         "\n" +
         errorLines[errorLines.length - 1] +
@@ -293,147 +311,64 @@ Enigmail.hdrView = {
 
       while (errorLines.length > 20) {
         errorLines.pop();
       }
 
       errorMsg = errorLines.join("\n") + "\n...\n" + lastLines;
     }
 
-    var statusInfo = "";
-
-    if (statusFlags & EnigmailConstants.NODATA) {
-      if (statusFlags & EnigmailConstants.PGP_MIME_SIGNED) {
-        statusFlags |= EnigmailConstants.UNCERTAIN_SIGNATURE;
-      }
-
-      if (statusFlags & EnigmailConstants.PGP_MIME_ENCRYPTED) {
-        statusFlags |= EnigmailConstants.DECRYPTION_INCOMPLETE;
-      }
-    }
-
     if (!(statusFlags & EnigmailConstants.PGP_MIME_ENCRYPTED)) {
       encMimePartNumber = "";
     }
 
     if (
       statusFlags & EnigmailConstants.PARTIALLY_PGP &&
       statusFlags & EnigmailConstants.BAD_SIGNATURE
     ) {
       statusFlags &= ~(
         EnigmailConstants.PARTIALLY_PGP | EnigmailConstants.BAD_SIGNATURE
       );
       if (statusFlags === 0) {
         errorMsg = "";
-        fullStatusInfo = "";
       }
+      throw new Error("unhandled partial PGP message with bad signature");
     }
 
     var msgSigned =
       statusFlags &
       (EnigmailConstants.BAD_SIGNATURE |
         EnigmailConstants.GOOD_SIGNATURE |
         EnigmailConstants.EXPIRED_KEY_SIGNATURE |
         EnigmailConstants.EXPIRED_SIGNATURE |
         EnigmailConstants.UNCERTAIN_SIGNATURE |
         EnigmailConstants.REVOKED_KEY |
         EnigmailConstants.EXPIRED_KEY_SIGNATURE |
         EnigmailConstants.EXPIRED_SIGNATURE);
-    /*
-    var msgEncrypted =
-      statusFlags &
-      (EnigmailConstants.DECRYPTION_OKAY |
-        EnigmailConstants.DECRYPTION_INCOMPLETE |
-        EnigmailConstants.DECRYPTION_FAILED);
-    */
 
-    /*
     if (msgSigned && statusFlags & EnigmailConstants.IMPORTED_KEY) {
+      console.debug("unhandled status IMPORTED_KEY");
       statusFlags &= ~EnigmailConstants.IMPORTED_KEY;
     }
-    */
 
     // TODO: visualize the following signature attributes,
     // cross-check with corresponding email attributes
     // - date
     // - signer uid
     // - signer key
     // - signing and hash alg
 
-    // - process failed decryptions first because they imply bad signature handling
-    if (statusFlags & EnigmailConstants.BAD_PASSPHRASE) {
-      statusInfo = EnigmailLocale.getString("badPhrase");
-    } else if (statusFlags & EnigmailConstants.DECRYPTION_FAILED) {
-      if (statusFlags & EnigmailConstants.MISSING_MDC) {
-        statusInfo = EnigmailLocale.getString("missingMdcError");
-      } else if (statusFlags & EnigmailConstants.MISSING_PASSPHRASE) {
-        statusInfo = EnigmailLocale.getString("missingPassphrase");
-      } else if (statusFlags & EnigmailConstants.NO_SECKEY) {
-        statusInfo = EnigmailLocale.getString("needKey");
-      } else {
-        statusInfo = EnigmailLocale.getString("failedDecrypt");
-      }
-    } else if (statusFlags & EnigmailConstants.UNCERTAIN_SIGNATURE) {
-      statusInfo = EnigmailLocale.getString("uncertainSig");
-      if (statusFlags & EnigmailConstants.NO_PUBKEY) {
-        let b = document.getElementById("signatureKeyBox");
-        b.setAttribute("hidden", false);
-        b.setAttribute("keyid", keyId);
-      }
-    } else if (statusFlags & EnigmailConstants.GOOD_SIGNATURE) {
-      statusInfo = EnigmailLocale.getString("goodSig", [keyId]);
-    } else if (
-      statusFlags &
-      (EnigmailConstants.BAD_SIGNATURE |
-        EnigmailConstants.EXPIRED_SIGNATURE |
-        EnigmailConstants.EXPIRED_KEY_SIGNATURE)
-    ) {
-      statusInfo = EnigmailLocale.getString("badSig");
-    } else if (statusFlags & EnigmailConstants.DECRYPTION_OKAY) {
-      statusInfo = EnigmailLocale.getString("decryptedMsg");
-    } else if (statusFlags & EnigmailConstants.DECRYPTION_INCOMPLETE) {
-      statusInfo = EnigmailLocale.getString("incompleteDecrypt");
-    } else if (statusFlags & EnigmailConstants.IMPORTED_KEY) {
-      statusInfo = "";
-      EnigmailDialog.info(window, errorMsg);
-    }
-    // add key infos if available
-    if (keyId) {
-      var si = EnigmailLocale.getString("uncertainSig"); // "Uncertain signature"
-      if (statusInfo === "") {
-        statusInfo += si;
-      }
-      statusInfo += "\n" + EnigmailLocale.getString("signatureFrom", [keyId]);
-    }
-    //statusInfo += "\n\n" + errorMsg;
-
-    if (
-      statusFlags & EnigmailConstants.DECRYPTION_OKAY ||
-      this.isEncrypted === "ok"
-    ) {
-      var statusMsg;
-      if (xtraStatus && xtraStatus == "buggyMailFormat") {
-        statusMsg = EnigmailLocale.getString("decryptedMsgWithFormatError");
-      } else {
-        statusMsg = EnigmailLocale.getString("decryptedMsg");
-      }
-      if (!statusInfo) {
-        statusInfo = statusMsg;
-      } else {
-        statusInfo = statusMsg + "\n" + statusInfo;
-      }
-    }
+    this.msgSignatureKeyId = keyId;
+    this.msgEncryptionKeyId = encToDetails;
 
     if (statusFlags & EnigmailConstants.PARTIALLY_PGP) {
-      statusInfo = "";
+      console.debug("unhandled PARTIALLY_PGP => statusFlags = 0");
+      statusFlags = 0;
     }
 
-    // TODO: if encToDetails.length then make it available in status
-    // EnigmailLocale.getString("encryptKeysNote", [encToDetails]);
-
     /*
     if (xtraStatus === "process-manually") {
       let buttonLabel = "";
       if (statusFlags & EnigmailConstants.UNCERTAIN_SIGNATURE) {
         statusLine = EnigmailLocale.getString("msgPart", [
           EnigmailLocale.getString("msgSigned"),
         ]);
         statusLine += EnigmailLocale.getString("verifyManually");
@@ -453,18 +388,16 @@ Enigmail.hdrView = {
     */
 
     let tmp = {
       statusFlags,
       extStatusFlags,
       keyId,
       userId,
       msgSigned,
-      statusInfo,
-      fullStatusInfo,
       blockSeparation,
       xtraStatus,
       encryptedMimePart: encMimePartNumber,
     };
     Enigmail.msg.securityInfo = tmp;
 
     //Enigmail.msg.createArtificialAutocryptHeader();
 
@@ -513,49 +446,16 @@ Enigmail.hdrView = {
       EnigmailLog.DEBUG(
         "enigmailMsgHdrViewOverlay.js: checkWksConfirmRequest failed condition\n"
       );
     }
   },
   */
 
   /**
-   * Display Enigmail header with text and specific button
-   *
-   * @param {String} hdrMessage: Message to be displayed in header
-   * @param {String} buttonLabel: Label of button
-   * @param {String} requestType: action to be performed
-   */
-  displayFlexAction(hdrMessage, buttonLabel, requestType) {
-    if (!Enigmail.msg.securityInfo) {
-      Enigmail.msg.securityInfo = {};
-    }
-    Enigmail.msg.securityInfo.xtraStatus = requestType;
-    Enigmail.msg.securityInfo.statusInfo = hdrMessage;
-
-    // Thunderbird
-    this.setStatusText(hdrMessage);
-    //this.enigmailBox.removeAttribute("collapsed");
-    //let button = document.getElementById("enigmail_flexActionButton");
-    //button.setAttribute("label", buttonLabel);
-    //button.removeAttribute("hidden");
-    /*
-    document
-      .getElementById("enigmail_importKey")
-      .setAttribute("hidden", "true");
-    */
-    /*
-    this.enigmailBox.setAttribute(
-      "class",
-      "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"
-    );
-    */
-  },
-
-  /**
    * Display a localized message in lieu of the original message text
    */
   /*
   displayWksMessage() {
     EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: displayWksMessage()\n");
 
     if (Enigmail.msg.securityInfo.xtraStatus === "wks-request") {
       let enigMsgPane = document.getElementById("enigmailMsgDisplay");
@@ -624,317 +524,112 @@ Enigmail.hdrView = {
    */
   /*
   displayAutoCryptSetupMsgHeader() {
     Enigmail.hdrView.displayFlexAction(
       EnigmailLocale.getString("autocryptSetupReq"),
       EnigmailLocale.getString("autocryptSetupReq.button.label"),
       "autocrypt-setup"
     );
-    //view.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown");
     this.displayAutocryptMessage(true);
   },
 
   displayAutocryptMessage(allowImport) {
     EnigmailLog.DEBUG(
       "enigmailMsgHdrViewOverlay.js: displayAutocryptMessage()\n"
     );
   },
   */
 
   displayStatusBar() {
-    let bodyElement = document.getElementById("messagepanebox");
-
     let secInfo = Enigmail.msg.securityInfo;
     let statusFlags = secInfo.statusFlags;
     let extStatusFlags =
       "extStatusFlags" in secInfo ? secInfo.extStatusFlags : 0;
-    let sMimeContainer, encryptedUINode, signedUINode;
-
-    if (secInfo.statusInfo) {
-      this.setStatusText(secInfo.statusInfo + " ");
-      //this.enigmailBox.removeAttribute("collapsed");
+    let cryptoContainer, encryptedUINode, signedUINode;
 
-      /*
-      if (
-        (secInfo.keyId &&
-          statusFlags & EnigmailConstants.UNCERTAIN_SIGNATURE) ||
-        statusFlags & EnigmailConstants.INLINE_KEY
-      ) {
-        document.getElementById("enigmail_importKey").removeAttribute("hidden");
-      } else {
-        document
-          .getElementById("enigmail_importKey")
-          .setAttribute("hidden", "true");
-      }
-      document
-        .getElementById("enigmail_flexActionButton")
-        .setAttribute("hidden", "true");
-      */
-    } else {
-      this.setStatusText("");
-      //this.enigmailBox.setAttribute("collapsed", "true");
-    }
-
-    sMimeContainer = gSMIMEContainer;
+    cryptoContainer = gCryptoContainer;
     signedUINode = gSignedUINode;
     encryptedUINode = gEncryptedUINode;
 
-    /* eslint block-scoped-var: 0*/
-    if (typeof sMimeContainer !== "object") {
-      return;
-    }
-    if (!sMimeContainer) {
-      return;
-    }
-
-    // Update icons and header-box css-class
-    try {
-      sMimeContainer.collapsed = false;
-      signedUINode.collapsed = false;
-      encryptedUINode.collapsed = false;
-
-      if (
-        statusFlags & EnigmailConstants.BAD_SIGNATURE &&
-        !(statusFlags & EnigmailConstants.GOOD_SIGNATURE)
-      ) {
-        // Display untrusted/bad signature icon
-        signedUINode.setAttribute("signed", "notok");
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"
-        );
-        */
-        this.isSigned = "notok";
-      } else if (
-        statusFlags & EnigmailConstants.GOOD_SIGNATURE &&
-        !(
-          statusFlags &
-          (EnigmailConstants.REVOKED_KEY |
-            EnigmailConstants.EXPIRED_KEY_SIGNATURE |
-            EnigmailConstants.EXPIRED_SIGNATURE)
-        )
-      ) {
-        let val;
-        if (extStatusFlags & EnigmailConstants.EXT_SELF_IDENTITY) {
-          val = "ok";
-        } else if (statusFlags & EnigmailConstants.TRUSTED_IDENTITY) {
-          val = "verified";
-        } else {
-          val = "unverified";
-        }
-
-        // Display trusted good signature icon
-        signedUINode.setAttribute("signed", val);
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"
-        );
-        */
-        this.isSigned = val;
-        bodyElement.setAttribute("enigSigned", val);
-      } else if (statusFlags & EnigmailConstants.UNCERTAIN_SIGNATURE) {
-        // Display uncertain signature icon
-        signedUINode.setAttribute("signed", "unknown");
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"
-        );
-        */
-        this.isSigned = "unknown";
-      } else if (
-        statusFlags &
-        (EnigmailConstants.REVOKED_KEY |
-          EnigmailConstants.EXPIRED_KEY_SIGNATURE |
-          EnigmailConstants.EXPIRED_SIGNATURE)
-      ) {
-        signedUINode.setAttribute("signed", "notok");
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureVerified"
-        );
-        */
-        this.isSigned = "notok";
-      } else if (statusFlags & EnigmailConstants.INLINE_KEY) {
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"
-        );
-        */
-      } else {
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelNoSignature"
-        );
-        */
-      }
+    cryptoContainer.collapsed = false;
+    cryptoContainer.setAttribute("tech", "OpenPGP");
+    signedUINode.collapsed = false;
+    encryptedUINode.collapsed = false;
 
-      if (statusFlags & EnigmailConstants.DECRYPTION_OKAY) {
-        EnigmailURIs.rememberEncryptedUri(this.lastEncryptedMsgKey);
-
-        // Display encrypted icon
-        encryptedUINode.setAttribute("encrypted", "ok");
-        this.isEncrypted = "ok";
-      } else if (
-        statusFlags &
-        (EnigmailConstants.DECRYPTION_INCOMPLETE |
-          EnigmailConstants.DECRYPTION_FAILED)
-      ) {
-        // Display un-encrypted icon
-        encryptedUINode.setAttribute("encrypted", "notok");
-        this.isEncrypted = "notok";
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelSignatureNotOk"
-        );
-        */
-      }
-
-      // special handling after trying to fix buggy mail format (see buggyExchangeEmailContent in code)
-      if (secInfo.xtraStatus && secInfo.xtraStatus == "buggyMailFormat") {
-        /*
-        this.enigmailBox.setAttribute(
-          "class",
-          "expandedEnigmailBox enigmailHeaderBoxLabelBuggyMailFormat"
-        );
-        */
+    if (
+      statusFlags &
+      (EnigmailConstants.DECRYPTION_FAILED |
+        EnigmailConstants.DECRYPTION_INCOMPLETE)
+    ) {
+      encryptedUINode.setAttribute("encrypted", "notok");
+      if (statusFlags & EnigmailConstants.NO_SECKEY) {
+        this.msgEncryptionState = EnigmailConstants.MSG_ENC_NO_SECRET_KEY;
+      } else {
+        this.msgEncryptionState = EnigmailConstants.MSG_ENC_FAILURE;
       }
-    } catch (ex) {
-      EnigmailLog.writeException("displayStatusBar", ex);
-    }
-  },
-
-  dispSecurityContext() {
-    try {
-      if (Enigmail.msg.securityInfo) {
-        if (
-          Enigmail.msg.securityInfo.statusFlags & EnigmailConstants.NODATA &&
-          Enigmail.msg.securityInfo.statusFlags &
-            (EnigmailConstants.PGP_MIME_SIGNED |
-              EnigmailConstants.PGP_MIME_ENCRYPTED)
-        ) {
-          document
-            .getElementById("enigmail_reloadMessage")
-            .removeAttribute("hidden");
-        } else {
-          document
-            .getElementById("enigmail_reloadMessage")
-            .setAttribute("hidden", "true");
-        }
-      }
-
-      var optList = ["pgpSecurityInfo", "copySecurityInfo"];
-      for (var j = 0; j < optList.length; j++) {
-        var menuElement = document.getElementById("enigmail_" + optList[j]);
-        if (Enigmail.msg.securityInfo) {
-          menuElement.removeAttribute("disabled");
-        } else {
-          menuElement.setAttribute("disabled", "true");
-        }
-      }
-
-      this.setSenderStatus(
-        "signSenderKey",
-        "editSenderKeyTrust",
-        "showPhoto",
-        "dispKeyDetails"
-      );
-    } catch (ex) {
-      EnigmailLog.ERROR(
-        "error on displaying Security menu:\n" + ex.toString() + "\n"
-      );
-    }
-  },
-
-  updateSendersKeyMenu() {
-    this.setSenderStatus(
-      "keyMgmtSignKey",
-      "keyMgmtKeyTrust",
-      "keyMgmtShowPhoto",
-      "keyMgmtDispKeyDetails",
-      "importpublickey"
-    );
-  },
-
-  setSenderStatus(elemSign, elemTrust, elemPhoto, elemKeyProps, elemImportKey) {
-    function setElemStatus(elemName, disabledValue) {
-      document
-        .getElementById("enigmail_" + elemName)
-        .setAttribute("disabled", !disabledValue);
-
-      let secondElem = document.getElementById("enigmail_" + elemName + "2");
-      if (secondElem) {
-        secondElem.setAttribute("disabled", !disabledValue);
+      this.msgSignatureState = EnigmailConstants.MSG_SIG_NONE;
+    } else if (statusFlags & EnigmailConstants.DECRYPTION_OKAY) {
+      EnigmailURIs.rememberEncryptedUri(this.lastEncryptedMsgKey);
+      encryptedUINode.setAttribute("encrypted", "ok");
+      this.msgEncryptionState = EnigmailConstants.MSG_ENC_OK;
+      if (secInfo.xtraStatus && secInfo.xtraStatus == "buggyMailFormat") {
+        console.log(EnigmailLocale.getString("decryptedMsgWithFormatError"));
       }
     }
 
-    var photo = false;
-    var sign = false;
-    var trust = false;
-    var unknown = false;
-    var signedMsg = false;
-    var keyObj = null;
-
-    if (Enigmail.msg.securityInfo) {
-      if (
-        Enigmail.msg.securityInfo.statusFlags &
-        EnigmailConstants.PHOTO_AVAILABLE
-      ) {
-        photo = true;
+    if (
+      statusFlags &
+      (EnigmailConstants.BAD_SIGNATURE |
+        EnigmailConstants.REVOKED_KEY |
+        EnigmailConstants.EXPIRED_KEY_SIGNATURE |
+        EnigmailConstants.EXPIRED_SIGNATURE)
+    ) {
+      if (statusFlags & EnigmailConstants.INVALID_RECIPIENT) {
+        this.msgSignatureState = EnigmailConstants.MSG_SIG_INVALID_KEY_REJECTED;
+      } else {
+        this.msgSignatureState = EnigmailConstants.MSG_SIG_INVALID;
       }
-      if (Enigmail.msg.securityInfo.keyId) {
-        keyObj = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId);
+      signedUINode.setAttribute("signed", "notok");
+    } else if (statusFlags & EnigmailConstants.GOOD_SIGNATURE) {
+      let val;
+      if (statusFlags & EnigmailConstants.TRUSTED_IDENTITY) {
+        this.msgSignatureState = EnigmailConstants.MSG_SIG_VALID_KEY_VERIFIED;
+        val = "verified";
+      } else if (extStatusFlags & EnigmailConstants.EXT_SELF_IDENTITY) {
+        val = "ok";
+        this.msgSignatureState = EnigmailConstants.MSG_SIG_VALID_SELF;
+      } else {
+        val = "unverified";
+        this.msgSignatureState = EnigmailConstants.MSG_SIG_VALID_KEY_UNVERIFIED;
       }
-      if (Enigmail.msg.securityInfo.msgSigned) {
-        signedMsg = true;
-        if (
-          !(
-            Enigmail.msg.securityInfo.statusFlags &
-            (EnigmailConstants.REVOKED_KEY |
-              EnigmailConstants.EXPIRED_KEY_SIGNATURE |
-              EnigmailConstants.UNCERTAIN_SIGNATURE)
-          )
-        ) {
-          sign = true;
-        }
-        if (keyObj && keyObj.isOwnerTrustUseful()) {
-          trust = true;
-        }
+      signedUINode.setAttribute("signed", val);
+    } else if (statusFlags & EnigmailConstants.UNCERTAIN_SIGNATURE) {
+      if (statusFlags & EnigmailConstants.INVALID_RECIPIENT) {
+        this.msgSignatureState =
+          EnigmailConstants.MSG_SIG_UNCERTAIN_UID_MISMATCH;
+      } else if (statusFlags & EnigmailConstants.NO_PUBKEY) {
+        this.msgSignatureState =
+          EnigmailConstants.MSG_SIG_UNCERTAIN_KEY_UNAVAILABLE;
+        let b = document.getElementById("signatureKeyBox");
+        b.setAttribute("hidden", false);
+        b.setAttribute("keyid", secInfo.keyId);
+      } else {
+        this.msgSignatureState =
+          EnigmailConstants.MSG_SIG_UNCERTAIN_KEY_NOT_ACCEPTED;
+      }
+      signedUINode.setAttribute("signed", "mismatch");
+    }
+    // (statusFlags & EnigmailConstants.INLINE_KEY) ???
 
-        if (
-          Enigmail.msg.securityInfo.statusFlags &
-          EnigmailConstants.UNCERTAIN_SIGNATURE
-        ) {
-          unknown = true;
-        }
-      }
-    }
-
-    if (elemTrust) {
-      setElemStatus(elemTrust, trust);
+    /*
+    // special handling after trying to fix buggy mail format (see buggyExchangeEmailContent in code)
+    if (secInfo.xtraStatus && secInfo.xtraStatus == "buggyMailFormat") {
     }
-    if (elemSign) {
-      setElemStatus(elemSign, sign);
-    }
-    if (elemPhoto) {
-      setElemStatus(elemPhoto, photo);
-    }
-    if (elemKeyProps) {
-      setElemStatus(elemKeyProps, signedMsg && !unknown);
-    }
-    if (elemImportKey) {
-      setElemStatus(elemImportKey, unknown);
-    }
+    */
   },
 
   editKeyExpiry() {
     EnigmailWindows.editKeyExpiry(
       window,
       [Enigmail.msg.securityInfo.userId],
       [Enigmail.msg.securityInfo.keyId]
     );
@@ -963,35 +658,27 @@ Enigmail.hdrView = {
     );
     gDBView.reloadMessageWithAllParts();
   },
 
   msgHdrViewLoad() {
     EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.msgHdrViewLoad\n");
 
     this.messageListener = {
-      //enigmailBox: document.getElementById("enigmailBox"),
       onStartHeaders() {
         EnigmailLog.DEBUG(
           "enigmailMsgHdrViewOverlay.js: _listener_onStartHeaders\n"
         );
 
         try {
           Enigmail.hdrView.statusBarHide();
           EnigmailVerify.setMsgWindow(
             msgWindow,
             Enigmail.msg.getCurrentMsgUriSpec()
           );
-          Enigmail.hdrView.setStatusText("");
-          /*
-          this.enigmailBox.setAttribute(
-            "class",
-            "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"
-          );
-          */
 
           let msgFrame = document.getElementById("messagepane").contentDocument;
 
           if (msgFrame) {
             msgFrame.addEventListener(
               "unload",
               Enigmail.hdrView.messageUnload.bind(Enigmail.hdrView),
               true
@@ -1012,22 +699,16 @@ Enigmail.hdrView = {
 
       onEndHeaders() {
         EnigmailLog.DEBUG(
           "enigmailMsgHdrViewOverlay.js: _listener_onEndHeaders\n"
         );
 
         try {
           Enigmail.hdrView.statusBarHide();
-          /*
-          this.enigmailBox.setAttribute(
-            "class",
-            "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"
-          );
-          */
         } catch (ex) {}
       },
 
       beforeStartHeaders() {
         return true;
       },
     };
 
@@ -1050,24 +731,16 @@ Enigmail.hdrView = {
 
   messageLoad(event) {
     EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.messageLoad\n");
 
     Enigmail.msg.messageAutoDecrypt();
     Enigmail.msg.handleAttchmentEvent();
   },
 
-  copyStatusInfo() {
-    if (Enigmail.msg.securityInfo) {
-      EnigmailClipboard.setClipboardContent(
-        Enigmail.msg.securityInfo.statusInfo
-      );
-    }
-  },
-
   showPhoto() {
     if (!Enigmail.msg.securityInfo) {
       return;
     }
 
     let key = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId);
 
     EnigmailWindows.showPhoto(
@@ -1198,17 +871,17 @@ Enigmail.hdrView = {
     EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.updateMsgDb\n");
     var msg = gFolderDisplay.selectedMessage;
     if (!msg || !msg.folder) {
       return;
     }
 
     var msgHdr = msg.folder.GetMessageHeader(msg.messageKey);
 
-    if (this.isEncrypted === "ok") {
+    if (this.msgEncryptionState === EnigmailConstants.MSG_ENC_OK) {
       Enigmail.msg.securityInfo.statusFlags |=
         EnigmailConstants.DECRYPTION_OKAY;
     }
     msgHdr.setUint32Property("enigmail", Enigmail.msg.securityInfo.statusFlags);
   },
 
   enigCanDetachAttachments() {
     EnigmailLog.DEBUG(
@@ -1672,16 +1345,17 @@ Enigmail.hdrView = {
       return this._smimeHeaderSink.encryptionStatus(
         aNestingLevel,
         aEncryptionStatus,
         aRecipientCert
       );
     },
   },
 
+  /*
   onUnloadEnigmail() {
     window.removeEventListener("load-enigmail", Enigmail.hdrView.hdrViewLoad);
     for (let i = 0; i < gMessageListeners.length; i++) {
       if (gMessageListeners[i] === Enigmail.hdrView.messageListener) {
         gMessageListeners.splice(i, 1);
         break;
       }
     }
@@ -1725,14 +1399,15 @@ Enigmail.hdrView = {
         Enigmail.hdrView.messageUnload,
         true
       );
       msgFrame.removeEventListener("load", Enigmail.hdrView.messageLoad);
     }
 
     CanDetachAttachments = Enigmail.hdrView.origCanDetachAttachments;
   },
+  */
 };
 
 window.addEventListener(
   "load-enigmail",
   Enigmail.hdrView.hdrViewLoad.bind(Enigmail.hdrView)
 );
new file mode 100644
--- /dev/null
+++ b/mail/extensions/openpgp/content/ui/msgReadStatus.js
@@ -0,0 +1,185 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+var { EnigmailConstants } = ChromeUtils.import(
+  "chrome://openpgp/content/modules/constants.jsm"
+);
+var { EnigmailWindows } = ChromeUtils.import(
+  "chrome://openpgp/content/modules/windows.jsm"
+);
+var { EnigmailKeyRing } = ChromeUtils.import(
+  "chrome://openpgp/content/modules/keyRing.jsm"
+);
+
+let gSigKeyId;
+let gEncKeyId;
+
+function setText(id, value) {
+  var element = document.getElementById(id);
+  if (!element) {
+    return;
+  }
+  if (element.hasChildNodes()) {
+    element.firstElementChild.remove();
+  }
+  var textNode = document.createTextNode(value);
+  element.appendChild(textNode);
+}
+
+/* eslint-disable complexity */
+function onLoad() {
+  let params = window.arguments[0];
+
+  var sBundle = document.getElementById("bundle_smime_read_info");
+  var oBundle = document.getElementById("bundle_openpgp_read_info");
+
+  if (!sBundle || !oBundle) {
+    return;
+  }
+
+  var hasAnySig = true;
+  var hasAnyEnc = true;
+
+  var sigInfoLabel = null;
+  var sigInfo = null;
+
+  switch (params.msgSignatureState) {
+    case EnigmailConstants.MSG_SIG_NONE:
+      sigInfoLabel = oBundle.getString("NoSig");
+      sigInfo = sBundle.getString("SINone");
+      hasAnySig = false;
+      break;
+
+    case EnigmailConstants.MSG_SIG_UNCERTAIN_KEY_UNAVAILABLE:
+      sigInfoLabel = oBundle.getString("UncertainSig");
+      sigInfo = oBundle.getString("SigUncertainNoKey");
+      break;
+
+    case EnigmailConstants.MSG_SIG_UNCERTAIN_UID_MISMATCH:
+      sigInfoLabel = oBundle.getString("UncertainSig");
+      sigInfo = oBundle.getString("SigUncertainUidMismatch");
+      break;
+
+    case EnigmailConstants.MSG_SIG_UNCERTAIN_KEY_NOT_ACCEPTED:
+      sigInfoLabel = oBundle.getString("UncertainSig");
+      sigInfo = oBundle.getString("SigUncertainNotAccepted");
+      break;
+
+    case EnigmailConstants.MSG_SIG_INVALID_KEY_REJECTED:
+      sigInfoLabel = oBundle.getString("InvalidSig");
+      sigInfo = oBundle.getString("SigInvalidRejected");
+      break;
+
+    case EnigmailConstants.MSG_SIG_INVALID:
+      sigInfoLabel = oBundle.getString("InvalidSig");
+      sigInfo = oBundle.getString("SigInvalidTechnicalProblem");
+      break;
+
+    case EnigmailConstants.MSG_SIG_VALID_KEY_UNVERIFIED:
+      sigInfoLabel = oBundle.getString("GoodSig");
+      sigInfo = oBundle.getString("SigValidUnverified");
+      break;
+
+    case EnigmailConstants.MSG_SIG_VALID_KEY_VERIFIED:
+      sigInfoLabel = oBundle.getString("GoodSig");
+      sigInfo = oBundle.getString("SigValidVerified");
+      break;
+
+    case EnigmailConstants.MSG_SIG_VALID_SELF:
+      sigInfoLabel = oBundle.getString("GoodSig");
+      sigInfo = oBundle.getString("SigValidOwnKey");
+      break;
+
+    default:
+      Cu.reportError(
+        "Unexpected msgSignatureState: " + params.msgSignatureState
+      );
+  }
+
+  document.getElementById("signatureLabel").value = sigInfoLabel;
+  setText("signatureExplanation", sigInfo);
+
+  var encInfoLabel = null;
+  var encInfo = null;
+
+  switch (params.msgEncryptionState) {
+    case EnigmailConstants.MSG_ENC_NONE:
+      encInfoLabel = sBundle.getString("EINoneLabel2");
+      encInfo = sBundle.getString("EINone");
+      hasAnyEnc = false;
+      break;
+
+    case EnigmailConstants.MSG_ENC_NO_SECRET_KEY:
+      encInfoLabel = sBundle.getString("EIInvalidLabel");
+      encInfo = sBundle.getString("EIInvalidHeader");
+      break;
+
+    case EnigmailConstants.MSG_ENC_FAILURE:
+      encInfoLabel = sBundle.getString("EIInvalidLabel");
+      encInfo = sBundle.getString("EIClueless");
+      break;
+
+    case EnigmailConstants.MSG_ENC_OK:
+      encInfoLabel = sBundle.getString("EIValidLabel");
+      encInfo = sBundle.getString("EIValid");
+      break;
+
+    default:
+      Cu.reportError(
+        "Unexpected msgEncryptionState: " + params.msgEncryptionState
+      );
+  }
+
+  if (hasAnyEnc || hasAnySig) {
+    document.getElementById("techLabel").collapsed = false;
+  }
+
+  document.getElementById("encryptionLabel").value = encInfoLabel;
+  setText("encryptionExplanation", encInfo);
+
+  if (params.msgSignatureKeyId) {
+    let idElement = document.getElementById("signatureKeyId");
+    idElement.collapsed = false;
+    idElement.value = oBundle.getFormattedString("SigKeyId", [
+      "0x" + params.msgSignatureKeyId,
+    ]);
+
+    if (EnigmailKeyRing.getKeyById(params.msgSignatureKeyId)) {
+      document.getElementById("viewSignatureKey").collapsed = false;
+      gSigKeyId = params.msgSignatureKeyId;
+    }
+  }
+
+  if (params.msgEncryptionKeyId) {
+    let idElement = document.getElementById("encryptionKeyId");
+    idElement.collapsed = false;
+    idElement.value = oBundle.getFormattedString("EncKeyId", [
+      "0x" + params.msgEncryptionKeyId,
+    ]);
+
+    if (EnigmailKeyRing.getKeyById(params.msgEncryptionKeyId)) {
+      document.getElementById("viewEncryptionKey").collapsed = false;
+      gEncKeyId = params.msgEncryptionKeyId;
+    }
+  }
+}
+/* eslint-enable complexity */
+
+function viewKeyHelper(keyId) {
+  EnigmailWindows.openKeyDetails(window, keyId, false);
+}
+
+function viewSignatureKey() {
+  if (gSigKeyId) {
+    viewKeyHelper(gSigKeyId);
+  }
+}
+
+function viewEncryptionKey() {
+  if (gEncKeyId) {
+    viewKeyHelper(gEncKeyId);
+  }
+}
copy from mailnews/extensions/smime/content/msgReadSecurityInfo.xhtml
copy to mail/extensions/openpgp/content/ui/msgReadStatus.xhtml
--- a/mailnews/extensions/smime/content/msgReadSecurityInfo.xhtml
+++ b/mail/extensions/openpgp/content/ui/msgReadStatus.xhtml
@@ -1,69 +1,53 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
-<?xml-stylesheet href="chrome://messenger/skin/smime/msgReadSecurityInfo.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/openpgp/msgReadStatus.css" type="text/css"?>
 
-<!DOCTYPE window SYSTEM "chrome://messenger-smime/locale/msgReadSecurityInfo.dtd">
+<!DOCTYPE window [
+<!ENTITY % smimeDTD SYSTEM "chrome://messenger-smime/locale/msgReadSecurityInfo.dtd" >
+%smimeDTD;
+<!ENTITY % openpgpDTD SYSTEM "chrome://openpgp/content/strings/msgReadStatus.dtd" >
+%openpgpDTD;
+]>
 
 <window title="&status.label;"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml"
-        style="width: 40em;"
+        style="width: 40em; height: 15em"
         onload="onLoad();">
-<dialog id="msgReadSecurityInfo"
+<dialog id="msgReadStatus"
         buttons="accept">
-  <script src="chrome://messenger-smime/content/msgReadSecurityInfo.js"/>
+  <script src="chrome://openpgp/content/ui/msgReadStatus.js"/>
 
   <stringbundle id="bundle_smime_read_info" src="chrome://messenger-smime/locale/msgSecurityInfo.properties"/>
+  <stringbundle id="bundle_openpgp_read_info" src="chrome://openpgp/content/strings/msgReadStatus.properties"/>
 
   <vbox flex="1">
+    <label id="techLabel" value="&OpenPGP;" collapsed="true"/>
+
     <label id="signatureLabel"/>
-    <label id="signatureHeader" collapsed="true"/>
     <description id="signatureExplanation"/>
-    <vbox id="signatureCert" collapsed="true">
-      <hbox>
-        <label id="signedByLabel">&signer.name;</label>
-        <description id="signedBy"/>
-      </hbox>
+    <vbox id="signatureKey">
+      <label id="signatureKeyId" collapsed="true"/>
       <hbox>
-        <label id="signerEmailLabel">&email.address;</label>
-        <description id="signerEmail"/>
-      </hbox>
-      <hbox>
-        <label id="sigCertIssuedByLabel">&issuer.name;</label>
-        <description id="sigCertIssuedBy"/>
-      </hbox>
-      <hbox>
-        <button id="signatureCertView" label="&signatureCert.label;"
-                oncommand="viewSignatureCert()"/>
+        <button id="viewSignatureKey" label="&ViewSignerKey;"
+                oncommand="viewSignatureKey()" collapsed="true"/>
       </hbox>
     </vbox>
 
     <separator/>
 
     <label id="encryptionLabel"/>
-    <label id="encryptionHeader" collapsed="true"/>
     <description id="encryptionExplanation"/>
-    <vbox id="encryptionCert" collapsed="true">
-      <hbox>
-        <label id="encryptedForLabel">&recipient.name;</label>
-        <description id="encryptedFor"/>
-      </hbox>
+    <vbox id="encryptionKey">
+      <label id="encryptionKeyId" collapsed="true"/>
       <hbox>
-        <label id="recipientEmailLabel">&email.address;</label>
-        <description id="recipientEmail"/>
-      </hbox>
-      <hbox>
-        <label id="encCertIssuedByLabel">&issuer.name;</label>
-        <description id="encCertIssuedBy"/>
-      </hbox>
-      <hbox>
-        <button id="encryptionCertView" label="&encryptionCert.label;"
-                oncommand="viewEncryptionCert()"/>
+        <button id="viewEncryptionKey" label="&ViewYourEncryptionKey;"
+                oncommand="viewEncryptionKey()" collapsed="true"/>
       </hbox>
     </vbox>
   </vbox>
 </dialog>
 </window>
--- a/mail/extensions/openpgp/jar.mn
+++ b/mail/extensions/openpgp/jar.mn
@@ -10,15 +10,17 @@ openpgp.jar:
   content/openpgp/modules/stdlib               (content/modules/stdlib/*.js*)
   content/openpgp/modules/cryptoAPI            (content/modules/cryptoAPI/*.js*)
   content/openpgp/strings/enigmail.properties  (content/strings/enigmail.properties)
   content/openpgp/strings/enigmail.dtd         (content/strings/enigmail.dtd)
   content/openpgp/strings/oneRecipientStatus.properties (content/strings/oneRecipientStatus.properties)
   content/openpgp/strings/oneRecipientStatus.dtd        (content/strings/oneRecipientStatus.dtd)
   content/openpgp/strings/composeKeyStatus.properties   (content/strings/composeKeyStatus.properties)
   content/openpgp/strings/composeKeyStatus.dtd          (content/strings/composeKeyStatus.dtd)
+  content/openpgp/strings/msgReadStatus.properties     (content/strings/msgReadStatus.properties)
+  content/openpgp/strings/msgReadStatus.dtd            (content/strings/msgReadStatus.dtd)
   content/openpgp/strings/bond.dtd             (content/strings/bond.dtd)
   content/openpgp/ui                           (content/ui/*.js)
   content/openpgp/ui                           (content/ui/*.xhtml)
   content/openpgp/ui                           (content/ui/*.css)
 
 [localization] @AB_CD@.jar:
   openpgp/content/ui/keyPicker.ftl             (content/ui/keyPicker.ftl)
--- a/mail/extensions/smime/content/msgHdrViewSMIMEOverlay.js
+++ b/mail/extensions/smime/content/msgHdrViewSMIMEOverlay.js
@@ -5,17 +5,17 @@
 
 /* import-globals-from ../../../../mailnews/extensions/smime/content/msgReadSMIMEOverlay.js */
 /* import-globals-from ../../../base/content/folderDisplay.js */
 /* import-globals-from ../../../base/content/mailWindow.js */
 /* import-globals-from ../../../base/content/msgHdrView.js */
 
 var gSignedUINode = null;
 var gEncryptedUINode = null;
-var gSMIMEContainer = null;
+var gCryptoContainer = null;
 var gStatusBar = null;
 
 var gEncryptedURIService = null;
 var gMyLastEncryptedURI = null;
 
 var gSMIMEBundle = null;
 
 var gSignatureStatusForURI = null;
@@ -74,17 +74,18 @@ var smimeHeaderSink = {
         return;
       }
     }
 
     gSignatureStatusForURI = aMsgNeckoURL;
     gSignatureStatus = aSignatureStatus;
     gSignerCert = aSignerCert;
 
-    gSMIMEContainer.collapsed = false;
+    gCryptoContainer.collapsed = false;
+    gCryptoContainer.setAttribute("tech", "S/MIME");
     gSignedUINode.collapsed = false;
 
     switch (aSignatureStatus) {
       case Ci.nsICMSMessageErrors.SUCCESS:
         gSignedUINode.setAttribute("signed", "ok");
         gStatusBar.setAttribute("signed", "ok");
         break;
 
@@ -164,17 +165,18 @@ var smimeHeaderSink = {
         return;
       }
     }
 
     gEncryptionStatusForURI = aMsgNeckoURL;
     gEncryptionStatus = aEncryptionStatus;
     gEncryptionCert = aRecipientCert;
 
-    gSMIMEContainer.collapsed = false;
+    gCryptoContainer.collapsed = false;
+    gCryptoContainer.setAttribute("tech", "S/MIME");
     gEncryptedUINode.collapsed = false;
 
     if (Ci.nsICMSMessageErrors.SUCCESS == aEncryptionStatus) {
       gEncryptedUINode.setAttribute("encrypted", "ok");
       gStatusBar.setAttribute("encrypted", "ok");
     } else {
       gEncryptedUINode.setAttribute("encrypted", "notok");
       gStatusBar.setAttribute("encrypted", "notok");
@@ -242,17 +244,18 @@ function onSMIMEStartHeaders() {
   gSignatureStatus = -1;
 
   gSignatureStatusForURI = null;
   gEncryptionStatusForURI = null;
 
   gSignerCert = null;
   gEncryptionCert = null;
 
-  gSMIMEContainer.collapsed = true;
+  gCryptoContainer.collapsed = true;
+  gCryptoContainer.removeAttribute("tech");
 
   gSignedUINode.collapsed = true;
   gSignedUINode.removeAttribute("signed");
   gStatusBar.removeAttribute("signed");
 
   gEncryptedUINode.collapsed = true;
   gEncryptedUINode.removeAttribute("encrypted");
   gStatusBar.removeAttribute("encrypted");
@@ -291,17 +294,17 @@ function msgHdrViewSMIMEOnLoad(event) {
   }
 
   // we want to register our security header sink as an opaque nsISupports
   // on the msgHdrSink used by mail.....
   msgWindow.msgHeaderSink.securityInfo = smimeHeaderSink;
 
   gSignedUINode = document.getElementById("signedHdrIcon");
   gEncryptedUINode = document.getElementById("encryptedHdrIcon");
-  gSMIMEContainer = document.getElementById("smimeBox");
+  gCryptoContainer = document.getElementById("cryptoBox");
   gStatusBar = document.getElementById("status-bar");
 
   // Add ourself to the list of message display listeners so we get notified
   // when we are about to display a message.
   var listener = {};
   listener.onStartHeaders = onSMIMEStartHeaders;
   listener.onEndHeaders = onSMIMEEndHeaders;
   listener.onBeforeShowHeaderPane = onSMIMEBeforeShowHeaderPane;
@@ -327,24 +330,24 @@ function msgHdrViewSMIMEOnUnload(event) 
   removeEventListener(
     "messagepane-unhide",
     msgHdrViewSMIMEOnMessagePaneUnhide,
     true
   );
 }
 
 function msgHdrViewSMIMEOnMessagePaneHide() {
-  gSMIMEContainer.collapsed = true;
+  gCryptoContainer.collapsed = true;
   gSignedUINode.collapsed = true;
   gEncryptedUINode.collapsed = true;
 }
 
 function msgHdrViewSMIMEOnMessagePaneUnhide() {
   if (gEncryptionStatus != -1 || gSignatureStatus != -1) {
-    gSMIMEContainer.collapsed = false;
+    gCryptoContainer.collapsed = false;
 
     if (gSignatureStatus != -1) {
       gSignedUINode.collapsed = false;
     }
 
     if (gEncryptionStatus != -1) {
       gEncryptedUINode.collapsed = false;
     }
--- a/mail/locales/en-US/chrome/messenger-smime/msgReadSecurityInfo.dtd
+++ b/mail/locales/en-US/chrome/messenger-smime/msgReadSecurityInfo.dtd
@@ -7,8 +7,11 @@
 <!ENTITY status.label "Message Security">
 <!ENTITY signatureCert.label "View Signature Certificate">
 <!ENTITY encryptionCert.label "View Encryption Certificate">
 
 <!ENTITY signer.name "Signed by:">
 <!ENTITY recipient.name "Encrypted for:">
 <!ENTITY email.address "Email address:">
 <!ENTITY issuer.name "Certificate issued by:">
+
+<!-- LOCALIZATION NOTE(SMIME.label): This a name for a technical standard. You should not translate it, but if applicable, you may write it using localized characters. -->
+<!ENTITY SMIME.label "S/MIME">
--- a/mail/themes/linux/mail/smime/msgReadSecurityInfo.css
+++ b/mail/themes/linux/mail/smime/msgReadSecurityInfo.css
@@ -5,16 +5,21 @@
 /* ===== msgReadSecurityInfo.css ========================================
   == Styles for the security info window when displaying received mail.
   ======================================================================= */
 
 @import url("chrome://messenger/skin/messenger.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
+#techLabel {
+  font-weight: bold;
+  text-align: right;
+}
+
 #signatureLabel {
   font-weight: bold;
 }
 
 #signatureCert {
   margin: 5px;
 }
 
--- a/mail/themes/osx/mail/smime/msgReadSecurityInfo.css
+++ b/mail/themes/osx/mail/smime/msgReadSecurityInfo.css
@@ -5,16 +5,21 @@
 /* ===== msgReadSecurityInfo.css ========================================
   == Styles for the security info window when displaying received mail.
   ======================================================================= */
 
 @import url("chrome://messenger/skin/messenger.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
+#techLabel {
+  font-weight: bold;
+  text-align: right;
+}
+
 #signatureLabel {
   font-weight: bold;
 }
 
 #signatureCert {
   margin: 5px;
 }
 
--- a/mail/themes/shared/jar.inc.mn
+++ b/mail/themes/shared/jar.inc.mn
@@ -245,8 +245,9 @@
   skin/classic/messenger/openpgp/sign-disabled-18.svg         (../shared/openpgp/sign-disabled-18.svg)
   skin/classic/messenger/openpgp/sign-inactive-18.svg         (../shared/openpgp/sign-inactive-18.svg)
   skin/classic/messenger/openpgp/spinning-wheel.png           (../shared/openpgp/spinning-wheel.png)
   skin/classic/messenger/openpgp/twisty-clsd.png              (../shared/openpgp/twisty-clsd.png)
   skin/classic/messenger/openpgp/twisty-open.png              (../shared/openpgp/twisty-open.png)
   skin/classic/messenger/openpgp/warning-16.png               (../shared/openpgp/warning-16.png)
   skin/classic/messenger/openpgp/composeKeyStatus.css         (../shared/openpgp/composeKeyStatus.css)
   skin/classic/messenger/openpgp/oneRecipientStatus.css       (../shared/openpgp/oneRecipientStatus.css)
+  skin/classic/messenger/openpgp/msgReadStatus.css            (../shared/openpgp/msgReadStatus.css)
new file mode 100644
--- /dev/null
+++ b/mail/themes/shared/openpgp/msgReadStatus.css
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@import url("chrome://messenger/skin/messenger.css");
+
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+#techLabel {
+  font-weight: bold;
+  text-align: right;
+}
+
+#signatureLabel {
+  font-weight: bold;
+}
+
+#signatureKey {
+  margin: 5px;
+}
+
+#encryptionLabel {
+  font-weight: bold;
+}
+
+#encryptionKey {
+  margin: 5px;
+}
--- a/mail/themes/windows/mail/smime/msgReadSecurityInfo.css
+++ b/mail/themes/windows/mail/smime/msgReadSecurityInfo.css
@@ -5,16 +5,21 @@
 /* ===== msgReadSecurityInfo.css ========================================
   == Styles for the security info window when displaying received mail.
   ======================================================================= */
 
 @import url("chrome://messenger/skin/messenger.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
+#techLabel {
+  font-weight: bold;
+  text-align: right;
+}
+
 #signatureLabel {
   font-weight: bold;
 }
 
 #signatureCert {
   margin: 5px;
 }
 
--- a/mailnews/extensions/smime/content/msgReadSMIMEOverlay.js
+++ b/mailnews/extensions/smime/content/msgReadSMIMEOverlay.js
@@ -1,14 +1,15 @@
 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* globals gDBView, GetNumSelectedMessages */
+/* globals MailConstants, Enigmail, BondOpenPGP */
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var gEncryptionStatus = -1;
 var gSignatureStatus = -1;
 var gSignerCert = null;
 var gEncryptionCert = null;
 
@@ -38,16 +39,26 @@ function showImapSignatureUnknown() {
       readSmimeBundle.getString("ImapOnDemand")
     )
   ) {
     gDBView.reloadMessageWithAllParts();
   }
 }
 
 function showMessageReadSecurityInfo() {
+  if (MailConstants.MOZ_OPENPGP && BondOpenPGP.allDependenciesLoaded()) {
+    let box = document.getElementById("cryptoBox");
+    let tech = box.getAttribute("tech");
+    if (tech && tech === "OpenPGP") {
+      Enigmail.hdrView.viewOpenpgpInfo();
+      return;
+    }
+  }
+
+  // S/MIME
   let gSignedUINode = document.getElementById("signedHdrIcon");
   if (gSignedUINode && gSignedUINode.getAttribute("signed") == "unknown") {
     showImapSignatureUnknown();
     return;
   }
 
   let params = Cc["@mozilla.org/embedcomp/dialogparam;1"].createInstance(
     Ci.nsIDialogParamBlock
--- a/mailnews/extensions/smime/content/msgReadSecurityInfo.js
+++ b/mailnews/extensions/smime/content/msgReadSecurityInfo.js
@@ -38,29 +38,33 @@ function onLoad() {
   } catch (e) {} // maybe null
   try {
     gEncryptionCert = paramBlock.objects.queryElementAt(1, nsIX509Cert);
   } catch (e) {} // maybe null
 
   gSignatureStatus = paramBlock.GetInt(1);
   gEncryptionStatus = paramBlock.GetInt(2);
 
+  var hasAnySig = true;
+  var hasAnyEnc = true;
+
   var bundle = document.getElementById("bundle_smime_read_info");
 
   if (bundle) {
     var sigInfoLabel = null;
     var sigInfoHeader = null;
     var sigInfo = null;
     var sigInfo_clueless = false;
 
     switch (gSignatureStatus) {
       case -1:
       case nsICMSMessageErrors.VERIFY_NOT_SIGNED:
         sigInfoLabel = "SINoneLabel";
         sigInfo = "SINone";
+        hasAnySig = false;
         break;
 
       case nsICMSMessageErrors.SUCCESS:
         sigInfoLabel = "SIValidLabel";
         sigInfo = "SIValid";
         break;
 
       case nsICMSMessageErrors.VERIFY_BAD_SIGNATURE:
@@ -137,16 +141,17 @@ function onLoad() {
     var encInfoHeader = null;
     var encInfo = null;
     var encInfo_clueless = false;
 
     switch (gEncryptionStatus) {
       case -1:
         encInfoLabel = "EINoneLabel2";
         encInfo = "EINone";
+        hasAnyEnc = false;
         break;
 
       case nsICMSMessageErrors.SUCCESS:
         encInfoLabel = "EIValidLabel";
         encInfo = "EIValid";
         break;
 
       case nsICMSMessageErrors.ENCRYPT_INCOMPLETE:
@@ -158,16 +163,20 @@ function onLoad() {
         encInfoLabel = "EIInvalidLabel";
         encInfoHeader = "EIInvalidHeader";
         encInfo_clueless = 1;
         break;
       default:
         Cu.reportError("Unexpected gEncryptionStatus: " + gEncryptionStatus);
     }
 
+    if (hasAnyEnc || hasAnySig) {
+      document.getElementById("techLabel").collapsed = false;
+    }
+
     document.getElementById("encryptionLabel").value = bundle.getString(
       encInfoLabel
     );
 
     if (encInfoHeader) {
       label = document.getElementById("encryptionHeader");
       label.collapsed = false;
       label.value = bundle.getString(encInfoHeader);
--- a/mailnews/extensions/smime/content/msgReadSecurityInfo.xhtml
+++ b/mailnews/extensions/smime/content/msgReadSecurityInfo.xhtml
@@ -14,16 +14,18 @@
         onload="onLoad();">
 <dialog id="msgReadSecurityInfo"
         buttons="accept">
   <script src="chrome://messenger-smime/content/msgReadSecurityInfo.js"/>
 
   <stringbundle id="bundle_smime_read_info" src="chrome://messenger-smime/locale/msgSecurityInfo.properties"/>
 
   <vbox flex="1">
+    <label id="techLabel" value="&SMIME.label;" collapsed="true"/>
+
     <label id="signatureLabel"/>
     <label id="signatureHeader" collapsed="true"/>
     <description id="signatureExplanation"/>
     <vbox id="signatureCert" collapsed="true">
       <hbox>
         <label id="signedByLabel">&signer.name;</label>
         <description id="signedBy"/>
       </hbox>