Merge with default OUT-431
authorThomas
Thu, 17 May 2018 11:26:23 +0200
branchOUT-431
changeset 2200 c578f001cfe5
parent 2184 71d798d2b545 (current diff)
parent 2199 5c8c43f38243 (diff)
child 2201 5c9f9d4ec13f
Merge with default
CryptableMailItem.cs
MsgProcessor.cs
--- a/CryptableMailItem.cs	Thu May 10 12:38:22 2018 +0200
+++ b/CryptableMailItem.cs	Thu May 17 11:26:23 2018 +0200
@@ -97,12 +97,6 @@
         public delegate void OriginallyEncryptedStatusUpdateHandler(object sender, EventArgs e);
         public event OriginallyEncryptedStatusUpdateHandler OriginallyEncryptedStatusUpdated;
 
-        /// <summary>
-        /// Event handler for when a sync message is being detected during decryption.
-        /// </summary>
-        public delegate void SyncMessageReceivedHandler(object sender, CryptableMailItem.SyncMessageEventArgs e);
-        public static event SyncMessageReceivedHandler SyncMessageReceived;
-
         private pEpRating            _LastProcessedRating;
         private Globals.ReturnStatus _LastProcessedStatus;
 
@@ -1227,9 +1221,18 @@
                         // Wait for the other thread to finish
                         if (isAlreadyBeingDecrypted)
                         {
-                            Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
-                            Thread.Sleep(sleepTime);
-                            curWaitTime += sleepTime;
+                            // Do not process multiple times if it is an automatic message
+                            if (this.internalMailItem.GetIsAutoConsume())
+                            {
+                                curWaitTime = maxWaitTime + 1;
+                                Log.Verbose("ProcessAndGetRating: Setting timeout for AutoConsume message.");
+                            }
+                            else
+                            {
+                                Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
+                                Thread.Sleep(sleepTime);
+                                curWaitTime += sleepTime;
+                            }
                         }
                     }
                     while ((isAlreadyBeingDecrypted) && (curWaitTime < maxWaitTime));
@@ -1443,14 +1446,13 @@
                     // Process mail item
                     sts1 = PEPMessage.Create(this.internalMailItem, out message);
 
-                    // Block while KeySyncWizard is open and Trustwords haven't been accepted
-                    while ((KeySyncWizard.Wizard?.State == KeySyncWizard.WizardState.Step2) &&
-                            (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
-                            (message.To?.Count == 1) &&
-                            (message.From?.EqualsByAddress(message.To[0]) == true))
+                    // If Key Import Wizard is open, add mail to list to process later
+                    if ((KeySyncWizard.Wizard?.IsVisible == true) &&
+                        (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
+                        (message.To?.Count == 1) &&
+                        (message.From?.EqualsByAddress(message.To[0]) == true))
                     {
-                        Log.Verbose("ProcessAndGetRating: KeySyncWizard in Step 2. Blocking decryption.");
-                        Thread.Sleep(100);
+                        KeySyncWizard.Wizard?.AddToReceivedSyncMessages(message);
                     }
 
                     // Define decryption flags
@@ -1494,9 +1496,6 @@
                         }
                         else
                         {
-                            // Check for sync message
-                            this.CheckForSyncMessage((processedRating == pEpRating.pEpRatingUnencrypted) ? message : processedMessage, decryptionFlags);
-
                             // Save processed message data to Outlook
                             if (processedMessage != null)
                             {
@@ -1871,85 +1870,6 @@
          *************************************************************/
 
         /// <summary>
-        /// Checks if the key sync wizard is open or the message is a sync message.
-        /// If this is true, the message will get processed further, either raising
-        /// the respective event or opening the wizard.
-        /// </summary>
-        /// <param name="message">The message to check.</param>
-        /// <param name="flags">The decrypt flags.</param>
-        private void CheckForSyncMessage(PEPMessage message, pEpDecryptFlags flags)
-        {
-            try
-            {
-                /* To determine whether the processed message is a sync message:
-                 * 1. Is incoming (do not process sent messages)
-                 * 2. Has the KeyImport header (in case of pEp sync) and the header is not
-                 *    the own fingerprint.
-                 * - or -
-                 * 3. a. The WizardType is PGP
-                 *    b. The message has one To recipient that is also the From recipient
-                 *    c. The From recipient is an own identity (seems actually unnecessary)
-                 */
-                if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
-                    (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
-                {
-                    if ((message.To.Count == 1) &&
-                        (message.To[0].EqualsByAddress(message.From)) &&
-                        (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
-                    {
-                        Log.Verbose("CheckForSyncMessage: Sync message found.");
-
-                        if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
-                            (KeySyncWizard.Wizard?.IsVisible == false) &&
-                            (message.Rating < pEpRating.pEpRatingTrusted))
-                        {
-                            Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
-
-                            // Get own identity
-                            PEPIdentity myself = null;
-                            try
-                            {
-                                pEpIdentity _myself = message.To[0].ToCOMType();
-                                myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
-                            }
-                            catch (Exception ex)
-                            {
-                                myself = null;
-                                Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
-                            }
-
-                            // Only open if not sent to myself. Check again if not open
-                            if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
-                                (KeySyncWizard.Wizard?.IsVisible == false))
-                            {
-                                // Marshall to main thread and create new wizard
-                                KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
-                                {
-                                    KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
-                                    KeySyncWizard.Wizard.Show();
-                                    Log.Verbose("CheckForSyncMessage: Wizard opened.");
-                                }));
-                            }
-                        }
-                        else
-                        {
-                            Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
-                            CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
-                        }
-                    }
-                    else
-                    {
-                        Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
-            }
-        }
-
-        /// <summary>
         /// Releases all resources and disconnects internal events.
         /// The internal mail item will NOT be released -- this is managed externally.
         /// </summary>
@@ -2200,27 +2120,6 @@
         }
 
         /// <summary>
-        /// Class used to store the arguments in the SyncMessageReceived event.
-        /// </summary>
-        internal class SyncMessageEventArgs : EventArgs
-        {
-            public PEPMessage Message = null;
-            public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
-
-            /// <summary>
-            /// Constructs a new SyncMessageEventArgs with the given arguments.
-            /// </summary>
-            /// <param name="message">The message that has been received.</param>
-            /// <param name="flags">The decryption flags of the received message.</param>
-            public SyncMessageEventArgs(PEPMessage message,
-                                        pEpDecryptFlags flags)
-            {
-                this.Message = message;
-                this.Flags = flags;
-            }
-        }
-
-        /// <summary>
         /// Class used to store an entry in the encrypted conversation cache.
         /// This will identify the original parent encrypted mail item.
         /// </summary>
--- a/MsgProcessor.cs	Thu May 10 12:38:22 2018 +0200
+++ b/MsgProcessor.cs	Thu May 17 11:26:23 2018 +0200
@@ -13,6 +13,12 @@
     /// </summary>
     internal class MsgProcessor
     {
+        /// <summary>
+        /// Event handler for when a sync message is being detected during decryption.
+        /// </summary>
+        public delegate void SyncMessageReceivedHandler(object sender, MsgProcessor.SyncMessageEventArgs e);
+        public static event SyncMessageReceivedHandler SyncMessageReceived;
+
         /**************************************************************
          * 
          * Constructors/Destructors
@@ -33,6 +39,93 @@
          *************************************************************/
 
         /// <summary>
+        /// Checks if the key sync wizard is open or the message is a sync message.
+        /// If this is true, the message will get processed further, either raising
+        /// the respective event or opening the wizard.
+        /// </summary>
+        /// <param name="message">The message to check.</param>
+        /// <param name="flags">The decrypt flags.</param>
+        private void CheckForSyncMessage(PEPMessage message, ref pEpDecryptFlags flags)
+        {
+            try
+            {
+                /* To determine whether the processed message is a sync message:
+                 * 1. Is incoming (do not process sent messages)
+                 * 2. Has the KeyImport header (in case of pEp sync) and the header is not
+                 *    the own fingerprint.
+                 * - or -
+                 * 3. a. The WizardType is PGP
+                 *    b. The message has one To recipient that is also the From recipient
+                 *    c. The From recipient is an own identity (seems actually unnecessary)
+                 */
+                if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
+                    (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
+                {
+                    if ((message.To.Count == 1) &&
+                        (message.To[0].EqualsByAddress(message.From)) &&
+                        (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
+                    {
+                        Log.Verbose("CheckForSyncMessage: Sync message found.");
+
+                        if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
+                            (KeySyncWizard.Wizard?.IsVisible == false) &&
+                            (message.Rating < pEpRating.pEpRatingTrusted))
+                        {
+                            Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
+
+                            // Get own identity
+                            PEPIdentity myself = null;
+                            try
+                            {
+                                pEpIdentity _myself = message.To[0].ToCOMType();
+                                myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
+                            }
+                            catch (Exception ex)
+                            {
+                                myself = null;
+                                Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
+                            }
+
+                            // Only open if not sent to myself. Check again if not open
+                            if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
+                                (KeySyncWizard.Wizard?.IsVisible == false))
+                            {
+                                // Marshall to main thread and create new wizard
+                                KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
+                                {
+                                    KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
+                                    KeySyncWizard.Wizard.Show();
+                                    Log.Verbose("CheckForSyncMessage: Wizard opened.");
+                                })); 
+                            }
+                        }
+                        else
+                        {
+                            Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
+                            MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
+                        }
+
+                        // Delete message if necessary
+                        if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.pEp) &&
+                            (string.IsNullOrEmpty(message?.KeyImport) == false) &&
+                            (KeySyncWizard.Wizard?.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))
+                        {
+                            flags = (flags | pEpDecryptFlags.pEpDecryptFlagConsume);
+                        }
+                    }
+                    else
+                    {
+                        Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
+            }
+        }
+
+        /// <summary>
         /// Processes the given message including any decryption where necessary.
         /// This will then return the latest pEp rating for the message.
         /// If rating is ever undefined: it can be assumed an error occured.
@@ -393,14 +486,6 @@
 
             Log.Verbose("ProcessSentMessage: Started");
 
-            // Check if we have an extra key for sync messages and add it
-            if (string.IsNullOrEmpty(KeySyncWizard.Wizard?.Partner?.Fingerprint) == false)
-            {
-                List<string> eKeys = extraKeys?.ToList<string>() ?? new List<string>();
-                eKeys.Add(KeySyncWizard.Wizard.Partner.Fingerprint);
-                extraKeys = eKeys.ToArray<string>();
-            }
-
             // Force the working message to outgoing direction.
             // This protects mostly for outgoing rating calculation which requires it.
             // However, if the message is ever incoming direction here, a failure occured elsewhere.
@@ -767,6 +852,19 @@
 
         /// <summary>
         /// Decrypts the given pEp message.
+        /// This is a wrapper for special cases where we don't need the actual result.
+        /// </summary>
+        /// <param name="sourceMessage">The message to decrypt.</param>
+        /// <returns>True if decryption was considered successful, otherwise false.</returns>
+        public bool Decrypt(PEPMessage sourceMessage)
+        {
+            PEPMessage outMessage;
+
+            return this.Decrypt(sourceMessage, out outMessage);
+        }
+
+        /// <summary>
+        /// Decrypts the given pEp message.
         /// This is a wrapper for special cases where we don't need to take care of
         /// rating, key list or flags.
         /// </summary>
@@ -882,7 +980,10 @@
             {
                 destMessage = null;
                 keyList = new string[0];
-            }            
+            }
+
+            // Check for sync message
+            this.CheckForSyncMessage((rating == pEpRating.pEpRatingUnencrypted) ? sourceMessage : destMessage, ref flags);
 
             Log.SensitiveData("Decrypt: Complete. " + sourceMessage?.Id);
 
@@ -1159,5 +1260,26 @@
                 this.ProcessedStatus = Globals.ReturnStatus.Success;
             }
         }
+
+        /// <summary>
+        /// Class used to store the arguments in the SyncMessageReceived event.
+        /// </summary>
+        internal class SyncMessageEventArgs : EventArgs
+        {
+            public PEPMessage Message = null;
+            public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
+
+            /// <summary>
+            /// Constructs a new SyncMessageEventArgs with the given arguments.
+            /// </summary>
+            /// <param name="message">The message that has been received.</param>
+            /// <param name="flags">The decryption flags of the received message.</param>
+            public SyncMessageEventArgs(PEPMessage message,
+                                        pEpDecryptFlags flags)
+            {
+                this.Message = message;
+                this.Flags = flags;
+            }
+        }
     }
 }
--- a/PEPSettings.cs	Thu May 10 12:38:22 2018 +0200
+++ b/PEPSettings.cs	Thu May 17 11:26:23 2018 +0200
@@ -1846,7 +1846,6 @@
             protected bool          _IsSyncEnabled;
             protected string        _SentFolderEntryId;
             protected string        _SmtpAddress;
-            protected string        _StoreId;
             protected string        _Type;
             protected string        _UserName;
 
--- a/Properties/Resources.Designer.cs	Thu May 10 12:38:22 2018 +0200
+++ b/Properties/Resources.Designer.cs	Thu May 17 11:26:23 2018 +0200
@@ -701,6 +701,24 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Back.
+        /// </summary>
+        public static string KeySyncWizard_BackButtonText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_BackButtonText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
+        /// </summary>
+        public static string KeySyncWizard_ErrorExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_ErrorExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Error.
         /// </summary>
         public static string KeySyncWizard_ErrorText {
@@ -710,6 +728,15 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Export my private key to the other device.
+        /// </summary>
+        public static string KeySyncWizard_ExportOwnPrivateKey {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_ExportOwnPrivateKey", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Finish.
         /// </summary>
         public static string KeySyncWizard_Finish {
@@ -728,6 +755,89 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep1ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep1ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to If you initiated a key import for the following account, please click Start.
+        ///
+        ///If this was not you, please cancel..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep1NonInitiatorExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep1NonInitiatorExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep2ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep2ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Importing key....
+        /// </summary>
+        public static string KeySyncWizard_PEPStep3ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep3ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key import successful!.
+        /// </summary>
+        public static string KeySyncWizard_PEPStep4ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep4ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key successfully exported!.
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessExport {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessExport", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key successfully imported!.
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessImport {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessImport", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The key from your other device will now also be used to decrypt messages..
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessOtherKeyUsed {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:  
         ///
         ///1. has your public PGP key attached and
@@ -749,98 +859,56 @@
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+        ///   Looks up a localized string similar to A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain..
         /// </summary>
-        public static string KeySyncWizard_Step1PEPExplanationText {
+        public static string KeySyncWizard_PGPStep1ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep1ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Please import your public p≡p key on your PGP device and reply with a message that:  
-        ///
-        ///1. has your public PGP key attached and
-        ///2. is encrypted with the p≡p key you just imported.
+        ///   Looks up a localized string similar to In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key..
         /// </summary>
-        public static string KeySyncWizard_Step1PGPExplanationText {
+        public static string KeySyncWizard_PGPStep2ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PGPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep2ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to A message with your public key has been sent to yourself..
+        ///   Looks up a localized string similar to Encrypt the answer message with the public p≡p key you just imported and send it..
         /// </summary>
-        public static string KeySyncWizard_Step1PGPSubtitleText {
+        public static string KeySyncWizard_PGPStep3ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PGPSubtitleText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
-        /// </summary>
-        public static string KeySyncWizard_Step2PEPExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step2PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep3ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
         ///   Looks up a localized string similar to Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match..
         /// </summary>
-        public static string KeySyncWizard_Step2PGPExplanationText {
+        public static string KeySyncWizard_PGPStep5ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step2PGPExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Importing key....
-        /// </summary>
-        public static string KeySyncWizard_Step3PEPExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step3PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep5ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Please send now another reply message that:  
-        ///
-        ///1. has your private PGP key attached and
-        ///2. is encrypted with the p≡p key you just imported.
+        ///   Looks up a localized string similar to In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key..
         /// </summary>
-        public static string KeySyncWizard_Step3PGPExplanationText {
+        public static string KeySyncWizard_PGPStep6ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step3PGPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep6ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
-        /// </summary>
-        public static string KeySyncWizard_Step4ErrorExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step4ErrorExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
+        ///   Looks up a localized string similar to Encrypt the answer message again with the public p≡p key and send it..
         /// </summary>
-        public static string KeySyncWizard_Step4PEPSuccessInitiatorExplanationText {
+        public static string KeySyncWizard_PGPStep7ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessInitiatorExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The key from the other device can now be used to decrypt messages..
-        /// </summary>
-        public static string KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep7ExplanationText", resourceCulture);
             }
         }
         
@@ -849,9 +917,27 @@
         ///
         ///Your private PGP key has been successfully imported and will now be used as default p≡p key..
         /// </summary>
-        public static string KeySyncWizard_Step4SuccessExplanationText {
+        public static string KeySyncWizard_PGPSuccessExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PGPSuccessExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Use the imported key as default key.
+        /// </summary>
+        public static string KeySyncWizard_SetImportedKeyAsDefault {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step4SuccessExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_SetImportedKeyAsDefault", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Start.
+        /// </summary>
+        public static string KeySyncWizard_Start {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_Start", resourceCulture);
             }
         }
         
--- a/Properties/Resources.de.resx	Thu May 10 12:38:22 2018 +0200
+++ b/Properties/Resources.de.resx	Thu May 17 11:26:23 2018 +0200
@@ -651,7 +651,7 @@
     <value>Die Mailgröße überschreitet die zulässige Größenbeschränkung für die Verschlüsselung.</value>
   </data>
   <data name="Handshake_WrongFingerprint" xml:space="preserve">
-    <value>Falscher Fingerprint</value>
+    <value>Falscher Fingerabdruck</value>
   </data>
   <data name="Handshake_TrustwordsExpanderTooltipFull" xml:space="preserve">
     <value>Vollversion der Trustwords anzeigen</value>
@@ -722,22 +722,16 @@
   <data name="KeySyncWizard_Finish" xml:space="preserve">
     <value>Fertig stellen</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
-    <value>Bitte importieren Sie Ihren öffentlichen p≡p-Schlüssel auf Ihrem PGP-Gerät und senden Sie eine Antwortnachricht:  
-
-1. an die Sie Ihren öffentlichen PGP-Schlüssel anhängen und
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln</value>
+  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+    <value>Eine Nachricht mit Ihrem öffentlichen p≡p-Schlüssel wurde an Sie selbst versendet. Bitte öffnen Sie die Nachricht auf Ihrem PGP-Gerät und importieren Sie den Schlüssel in Ihren PGP-Schlüsselring.</value>
   </data>
-  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
-    <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+    <value>Erstellen Sie auf Ihrem PGP-Gerät eine Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben und hängen Sie Ihren öffentlichen PGP-Schlüssel an.</value>
   </data>
-  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
-    <value>Senden Sie nun bitte eine weitere Antwortnachricht:  
-
-1. an die Sie Ihren privaten PGP-Schlüssel anhängen und 
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln </value>
+  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+    <value>Verschlüsseln Sie die Antwortnachricht mit dem öffentlichen p≡p-Schlüssel, den Sie gerade importiert haben und versenden Sie sie.</value>
   </data>
-  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
     <value>Schlüsselimport erfolgreich
 
 Ihr privater PGP-Schlüssel wurde erfolgreich importiert und wird nun standardmäßig auch als p≡p-Schlüssel verwendet.</value>
@@ -745,23 +739,23 @@
   <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
     <value>Schlüsselimport</value>
   </data>
-  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
     <value>Der Schlüsselimportprozess wurde gestartet. Bitte stellen Sie sicher, dass Ihr anderes Gerät, von dem Sie Ihren Schlüssel importieren möchten, eingeschaltet ist.</value>
   </data>
-  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
     <value>Bitte vergleichen Sie die folgenden Trustwords mit denjenigen auf Ihrem anderen Gerät und bestätigen Sie sie, wenn sie übereinstimmen.</value>
   </data>
   <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
     <value>Es wird auf eine Antwort vom anderen Gerät gewartet...</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
-    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+    <value>Schlüsselimport erfolgreich!</value>
   </data>
-  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
     <value>Es ist ein Fehler aufgetreten. Ihr Schlüssel konnte nicht importiert werden. Bitte versuchen Sie es erneut.</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
-    <value>Der Schlüssel des anderen Geräts kann nun zum Entschlüsseln von Nachrichten verwendet werden.</value>
+  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+    <value>Schlüsselexport erfolgreich!</value>
   </data>
   <data name="KeySyncWizard_SuccessText" xml:space="preserve">
     <value>Schlüsselimport erfolgreich!</value>
@@ -769,7 +763,7 @@
   <data name="KeySyncWizard_ErrorText" xml:space="preserve">
     <value>Fehler</value>
   </data>
-  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
     <value>Schlüssel wird importiert...</value>
   </data>
   <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -781,9 +775,6 @@
   <data name="StoreContextMenu_KeyImportText" xml:space="preserve">
     <value>Schlüsselimport</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
-    <value>Eine Nachricht mit Ihrem öffentlichen Schlüssel wurde an Sie selbst versendet.</value>
-  </data>
   <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
     <value>Um mit dem Schlüsselimport fortzufahren, importieren Sie bitte den angehängten öffentlichen p≡p-Schlüssel und senden Sie eine Antwortnachricht:  
 
@@ -793,4 +784,39 @@
   <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
     <value>p≡p-Schlüsselimport</value>
   </data>
+  <data name="KeySyncWizard_Start" xml:space="preserve">
+    <value>Start</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+    <value>Wenn Sie einen Schlüsselimport von einem anderen Gerät gestartet haben, klicken Sie bitte auf Start.
+
+Andernfalls klicken Sie bitte auf Abbrechen.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+    <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+    <value>Erstellen Sie auf Ihrem PGP-Gerät eine neue Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben. Hängen Sie nun bitte Ihren privaten PGP-Schlüssel an.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+    <value>Verschlüsseln Sie die Antwortnachricht nun wieder mit dem öffentlichen p≡p-Schlüssel und versenden Sie sie.</value>
+  </data>
+  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+    <value>Zurück</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+    <value>Schlüsselimport erfolgreich!</value>
+  </data>
+  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+    <value>Meinen privaten Schlüssel auf das andere Gerät exportieren</value>
+  </data>
+  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+    <value>Den importierten Schlüssel standardmäßig verwenden</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+    <value>Der Schlüssel von Ihrem anderen Gerät kann nun ebenfalls zum Entschlüsseln verwendet werden.</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+  </data>
 </root>
\ No newline at end of file
--- a/Properties/Resources.resx	Thu May 10 12:38:22 2018 +0200
+++ b/Properties/Resources.resx	Thu May 17 11:26:23 2018 +0200
@@ -804,22 +804,16 @@
   <data name="KeySyncWizard_Finish" xml:space="preserve">
     <value>Finish</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
-    <value>Please import your public p≡p key on your PGP device and reply with a message that:  
-
-1. has your public PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+    <value>A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain.</value>
   </data>
-  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
-    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+    <value>In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key.</value>
   </data>
-  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
-    <value>Please send now another reply message that:  
-
-1. has your private PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+    <value>Encrypt the answer message with the public p≡p key you just imported and send it.</value>
   </data>
-  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
     <value>Key successfully imported
 
 Your private PGP key has been successfully imported and will now be used as default p≡p key.</value>
@@ -827,10 +821,10 @@
   <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
     <value>Key Import</value>
   </data>
-  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
     <value>The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key.</value>
   </data>
-  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
     <value>Please compare the following Trustwords with the ones on your other device and confirm if they match.</value>
   </data>
   <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
@@ -839,14 +833,14 @@
   <data name="KeySyncWizard_Next" xml:space="preserve">
     <value>Next</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
-    <value>The key from your other device will now be used as your default private key.</value>
+  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+    <value>Key successfully imported!</value>
   </data>
-  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
     <value>An error occured. Your key could not be imported correctly. Please try again.</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
-    <value>The key from the other device can now be used to decrypt messages.</value>
+  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+    <value>Key successfully exported!</value>
   </data>
   <data name="KeySyncWizard_SuccessText" xml:space="preserve">
     <value>Key import successful!</value>
@@ -854,7 +848,7 @@
   <data name="KeySyncWizard_ErrorText" xml:space="preserve">
     <value>Error</value>
   </data>
-  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
     <value>Importing key...</value>
   </data>
   <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -869,9 +863,6 @@
   <data name="ImageLogoIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\resources\imagelogoicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
-    <value>A message with your public key has been sent to yourself.</value>
-  </data>
   <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
     <value>To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:  
 
@@ -881,4 +872,39 @@
   <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
     <value>p≡p Key Import</value>
   </data>
+  <data name="KeySyncWizard_Start" xml:space="preserve">
+    <value>Start</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+    <value>If you initiated a key import for the following account, please click Start.
+
+If this was not you, please cancel.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+    <value>In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+    <value>Encrypt the answer message again with the public p≡p key and send it.</value>
+  </data>
+  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+    <value>Back</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+    <value>Key import successful!</value>
+  </data>
+  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+    <value>Export my private key to the other device</value>
+  </data>
+  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+    <value>Use the imported key as default key</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+    <value>The key from your other device will now be used as your default private key.</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+    <value>The key from your other device will now also be used to decrypt messages.</value>
+  </data>
 </root>
\ No newline at end of file
--- a/ThisAddIn.cs	Thu May 10 12:38:22 2018 +0200
+++ b/ThisAddIn.cs	Thu May 17 11:26:23 2018 +0200
@@ -685,10 +685,12 @@
         /// <param name="validateSendingAccount">Validates that the SendingAccount matches the From identity of the given message.
         /// This can catch situations (and throw exceptions) where the default account would be used instead.</param>
         /// <param name="processMessage">Whether or not to process this message through the pEp engine.</param>
+        /// <param name="setKeyImportHeader">Whether or not to process this message through the pEp engine.</param>
         internal void CreateAndSendMessage(PEPMessage message,
                                            bool deleteAfterSend,
                                            bool validateSendingAccount,
-                                           bool processMessage = false)
+                                           bool processMessage = false,
+                                           bool setKeyImportHeader = false)
         {
             Outlook.MailItem newItem;
             Globals.ReturnStatus sts;
@@ -721,10 +723,31 @@
                     MapiHelper.SetProperty(newItem, MapiProperty.PidLidUseTnef, false);
 
                     // If ForceUnencrypted property is set, add it to mail item
+                    bool save = false;
                     if (message.ForceUnencrypted)
                     {
                         newItem.SetPEPProperty(MailItemExtensions.PEPProperty.ForceUnencrypted, true);
-                        newItem.Save();
+                        save = true;
+                    }
+
+                    // Set KeyImport header if necessary
+                    if (setKeyImportHeader)
+                    {
+                        newItem.SetPEPProperty(MailItemExtensions.PEPProperty.KeyImport, message.KeyImport);
+                        save = true;
+                    }
+
+                    // Save if necessary
+                    if (save)
+                    {
+                        try
+                        {
+                            newItem.Save();
+                        }
+                        catch (Exception ex)
+                        {
+                            Log.Error("CreateAndSendMessage: Error saving new item. " + ex.ToString());
+                        }
                     }
 
                     /* Send
--- a/UI/HandshakeDialog.xaml.cs	Thu May 10 12:38:22 2018 +0200
+++ b/UI/HandshakeDialog.xaml.cs	Thu May 17 11:26:23 2018 +0200
@@ -4,7 +4,6 @@
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Linq;
-using System.Runtime.InteropServices;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
--- a/UI/HandshakeItemsControl.xaml	Thu May 10 12:38:22 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml	Thu May 17 11:26:23 2018 +0200
@@ -201,7 +201,8 @@
                                   SelectedValuePath="Key"
                                   SelectedValue="{Binding Path=TrustwordsCulture, Mode=TwoWay}"
                                   IsEnabled="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Trustwords}"
-                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}" />
+                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}"
+                                  Visibility="{Binding Path=Mode, Converter={StaticResource IsNotSyncModeToVisibility}}" />
                     </StackPanel>
 
                     <!-- Trustwords -->
--- a/UI/HandshakeItemsControl.xaml.cs	Thu May 10 12:38:22 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml.cs	Thu May 17 11:26:23 2018 +0200
@@ -127,5 +127,15 @@
                 handshakeItem.AreTrustwordsExpanded = ((sender as Expander)?.IsExpanded == true);
             }
         }
+
+        /// <summary>
+        /// Raises the property changed event, if possible, with the given arguments.
+        /// </summary>
+        /// <param name="propertyName">The name of the property that changed.</param>
+        private void RaisePropertyChangedEvent(string propertyName)
+        {
+            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+            return;
+        }
     }
 }
--- a/UI/KeySyncWizard.xaml	Thu May 10 12:38:22 2018 +0200
+++ b/UI/KeySyncWizard.xaml	Thu May 17 11:26:23 2018 +0200
@@ -23,94 +23,92 @@
         <ResourceDictionary>
             <!-- Converters -->
             <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
-            <local:InvertBoolConverter x:Key="InvertBool" />
-            <local:ValueConverterGroup x:Key="IsWizardStateToVisibility">
-                <local:IsWizardStateConverter />
-                <BooleanToVisibilityConverter />
-            </local:ValueConverterGroup>
-            <local:ValueConverterGroup x:Key="IsNotWizardStateToVisibility">
-                <local:IsWizardStateConverter />
+            <local:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibility" />
+            <local:ValueConverterGroup x:Key="IsStringNotNullOrEmptyToVisibility">
+                <local:IsStringEmptyConverter />
                 <local:InvertBoolConverter />
                 <BooleanToVisibilityConverter />
             </local:ValueConverterGroup>
-            <local:ValueConverterGroup x:Key="IsNotWizardStateToBool">
-                <local:IsWizardStateConverter />
-                <local:InvertBoolConverter />
-            </local:ValueConverterGroup>
+            <local:IsWizardTypeConverter x:Key="IsWizardType" />
+
+            <!--Dictionary-->
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="pack://application:,,,/pEp;component/Resources/Dictionary.xaml" />
+            </ResourceDictionary.MergedDictionaries>
         </ResourceDictionary>
     </Window.Resources>
 
-    <!--The window content-->
-    <StackPanel Width="470">
-
-        <!--Title section-->
-        <Grid Background="White"
-              Margin="0">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*" />
-                <ColumnDefinition Width="Auto" />
-            </Grid.ColumnDefinitions>
-            <StackPanel Grid.Column="0">
-                <TextBlock Margin="20,10,10,10"
-                       Text="{Binding Path=TitleText}"
-                       FontWeight="Bold" 
-                       VerticalAlignment="Center"/>
-                <TextBlock Margin="20,10,10,10"
-                           Text="{Binding Path=SubtitleText}"
-                           TextWrapping="Wrap"
-                           VerticalAlignment="Center" />
-            </StackPanel>
-            <Image Grid.Column="1"
-                   Stretch="Uniform"
-                   Height="40"
-                   VerticalAlignment="Center"
-                   HorizontalAlignment="Right"
-                   Margin="20,10"
-                   Source="pack://application:,,,/pEp;component/Resources/ImageLogoMedium.png">
-            </Image>
-        </Grid>
-
-        <Separator Margin="0,0,0,20"
-                   Background="LightGray" />
+    <StackPanel Margin="10"
+                Width="470">
 
         <!--Information section-->
-        <TextBlock Text="{Binding Path=ExplanationText}"
+        <TextBlock Text="{Binding Path=CurrentState.TitleText}"
                    TextWrapping="Wrap"
-                   Margin="20,10" />
+                   Margin="5,5,5,15" />
+
+        <!--User name section-->
+        <TextBlock Text="{Binding Path=CurrentState.UserText}"
+                   Padding="10"
+                   MinHeight="80"
+                   Background="White"
+                   FontWeight="DemiBold"
+                   Visibility="{Binding Path=CurrentState.IsUserTextVisible, Converter={StaticResource BoolToVisibility}}" />
 
         <!--Identities section-->
-        <local:HandshakeItemsControl Margin="10,0"
-                                     ItemsSource="{Binding Path=Items}"
-                                     Visibility="{Binding Path=State, Converter={StaticResource IsWizardStateToVisibility}, ConverterParameter=Step2}" />
+        <StackPanel Visibility="{Binding Path=CurrentState.AreTrustwordsVisible, Converter={StaticResource BoolToVisibility}}">
+            <local:HandshakeItemsControl ItemsSource="{Binding Path=Items}" />
+            <StackPanel Orientation="Horizontal"
+                        Margin="5,10,5,0"
+                        Visibility="{Binding Path=IsInitiator, Converter={StaticResource BoolToVisibility}}">
+                <CheckBox VerticalAlignment="Center"
+                          IsChecked="{Binding Path=SetImportedKeyAsDefault}" />
+                <Label Content="{x:Static p:Resources.KeySyncWizard_SetImportedKeyAsDefault}"
+                       MouseUp="LabelSetImportedKeyAsDefault_MouseUp"/>
+            </StackPanel>
+            <StackPanel Orientation="Horizontal"
+                        Margin="5,0,5,5">
+                <StackPanel.Visibility>
+                    <MultiBinding Converter="{StaticResource MultiBooleanToVisibility}">
+                        <Binding Path="IsInitiator" />
+                        <Binding Path="Type" Converter="{StaticResource IsWizardType}" ConverterParameter="pEp" />
+                    </MultiBinding>
+                </StackPanel.Visibility>
+                <CheckBox VerticalAlignment="Center"
+                          IsChecked="{Binding Path=ExportPrivateKey}" />
+                <Label Content="{x:Static p:Resources.KeySyncWizard_ExportOwnPrivateKey}" 
+                       MouseUp="LabelExportPrivateKey_MouseUp"/>
+            </StackPanel>
+        </StackPanel>
 
-        <Separator Margin="10,20,10,0" 
-                   Background="LightGray"/>
+        <!--Subtitle section-->
+        <TextBlock Text="{Binding Path=CurrentState.SubtitleText}"
+                   TextWrapping="Wrap"
+                   Margin="5,15"
+                   Visibility="{Binding Path=CurrentState.SubtitleText, Converter={StaticResource IsStringNotNullOrEmptyToVisibility}}" />
 
         <!--Buttons section-->
-        <Grid>
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*" />
-                <ColumnDefinition Width="Auto" />
-            </Grid.ColumnDefinitions>
-            <StackPanel Grid.Column="1"
-                        Margin="10"
-                        Orientation="Horizontal">
-                <Button x:Name="OKNextButton"
-                        Margin="5"
-                        Padding="5,2"
-                        MinWidth="70"
-                        IsEnabled="{Binding Path=State, Converter={StaticResource IsNotWizardStateToBool}, ConverterParameter=Step1|Step3}"
-                        Click="OKNextButton_Click"
-                        Content="{Binding Path=NextButtonText}" />
-                <Button x:Name="CancelButton"
-                        Margin="5"
-                        Padding="5,2"
-                        MinWidth="70"
-                        Click="CancelButton_Click"
-                        Visibility="{Binding Path=State, Converter={StaticResource IsNotWizardStateToVisibility}, ConverterParameter=Step4}"
-                        Content="{x:Static p:Resources.Options_CancelText}" />
-            </StackPanel>
-        </Grid>
+        <StackPanel Margin="0,10"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Right">
+            <Button x:Name="BackButton"
+                    Style="{StaticResource StyleCancelButton}"
+                    Margin="0,5,5,5"
+                    Click="BackButton_Click"
+                    Content="{x:Static p:Resources.KeySyncWizard_BackButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsBackButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+            <Button x:Name="AcceptButton"
+                    Style="{StaticResource StyleConfirmButton}"
+                    Margin="5"
+                    Click="AcceptButton_Click"
+                    Content="{Binding Path=CurrentState.AcceptButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsAcceptButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+            <Button x:Name="CancelButton"
+                    Margin="5,5,0,5"
+                    Style="{StaticResource StyleWrongButton}"
+                    Click="CancelButton_Click"
+                    Content="{Binding Path=CurrentState.CancelButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsCancelButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+        </StackPanel>
     </StackPanel>
 </Window>
 
--- a/UI/KeySyncWizard.xaml.cs	Thu May 10 12:38:22 2018 +0200
+++ b/UI/KeySyncWizard.xaml.cs	Thu May 17 11:26:23 2018 +0200
@@ -3,7 +3,10 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
+using System.Threading.Tasks;
 using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
 using Outlook = Microsoft.Office.Interop.Outlook;
 
 namespace pEp.UI
@@ -15,8 +18,23 @@
                                            INotifyPropertyChanged,
                                            Interfaces.IReset
     {
-        public const string PEP_PGP_SYNC_MESSAGE_SUBJECT    = "p≡p Key Import";
-        public const string PEP_PGP_SYNC_MESSAGE_BODY       = "";
+        /// <summary>
+        /// Defines the step this wizard is currently in.
+        /// </summary>
+        public enum Steps
+        {
+            Undefined,
+            Success,
+            Error,
+            Step1,
+            Step2,
+            Step3,
+            Step4,
+            Step5,
+            Step6,
+            Step7,
+            Step8
+        }
 
         /// <summary>
         /// The message types for sync messages.
@@ -40,66 +58,33 @@
         }
 
         /// <summary>
-        /// Defines the state (step) this wizard is currently in.
-        /// </summary>
-        public enum WizardState
-        {
-            /// <summary>
-            /// Undefined state. Should never occur.
-            /// </summary>
-            Undefined,
-
-            /// <summary>
-            /// First state on the side of the device that initiated
-            /// the process. Will send a first message and wait for
-            /// an answer message from the other device.
-            /// </summary>
-            Step1,
-
-            /// <summary>
-            /// Showing the Trustwords dialog, waiting for user input.
-            /// </summary>
-            Step2,
-
-            /// <summary>
-            /// Trustwords are accepted, the private key is being sent.
-            /// Waiting for key from other device.
-            /// </summary>
-            Step3,
-
-            /// <summary>
-            /// Process has finished (successfully or not).
-            /// </summary>
-            Step4
-        }
-
-        /// <summary>
         /// Event raised when a property is changed on a component.
         /// </summary>
         public event PropertyChangedEventHandler PropertyChanged;
 
-        private string                                  _ExplanationText;
+        private WizardState                             _CurrentState;
+        private bool                                    _ExportPrivateKey;
+        private bool                                    _IsInitiator;
         private ObservableCollection<HandshakeItem>     _Items;
         private PEPIdentity                             _Myself;
-        private string                                  _NextButtonText;
         private PEPIdentity                             _Partner;
-        private WizardState                             _State;
-        private string                                  _SubtitleText;
-        private bool                                    _Success;
-        private string                                  _TitleText;
+        private Steps                                   _Step;
+        private bool                                    _SetImportedKeyAsDefault;
         private WizardType                              _Type;
 
-        public static KeySyncWizard                     Wizard = null;
+        private bool                                    privateKeyImported = false;
+        private List<MessageTypes>                      sentMessages                = new List<MessageTypes>();
+        private List<PEPMessage>                        receivedSyncMessages        = new List<PEPMessage>();
+        private List<WizardState>                       states = new List<WizardState>();
+        private object                                  mutexReceivedSyncMessages   = new object();
 
-        private bool                                    isInitiator         = false;
-        private List<MessageTypes>                      sentMessages = new List<MessageTypes>();
+        public static KeySyncWizard                     Wizard = null;
 
         /// <summary>
         /// Default constructor
         /// </summary>
         public KeySyncWizard()
-        {
-        }
+        { }
 
         /// <summary>
         /// Constructor to create a new key sync wizard.
@@ -118,57 +103,25 @@
                 KeySyncWizard.Wizard.Close();
             }
 
+            // Reset all values
+            this.Reset();
+
             // Initialize the window
             InitializeComponent();
 
             // Set current wizard
             KeySyncWizard.Wizard = this;
 
-            // Reset all values
-            this.Reset();
-
             // Initialize the wizard
-            this.InitializeWizard(type, myself, partnerFpr);
-
-            // Set if wizard is the one that has started the sync process
-            this.isInitiator = isInitiator;
+            this.InitializeWizard(isInitiator, type, myself, partnerFpr);
 
             // Attach event handler for new sync messages
-            CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
-
-            // Either send initial or answer message
-            if (isInitiator)
-            {
-                // Send initial message
-                this.SendSyncMessage(MessageTypes.InitialMessage);
-            }
-            else
-            {
-                try
-                {
-                    // Update own identity
-                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
+            MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
 
-                    // Create handshake item
-                    if (this.CreateHandshakeItem())
-                    {
-                        // Send answer message with pub key
-                        this.SendSyncMessage(MessageTypes.PublicKeyMessage);
-
-                        // Go to next step
-                        this.GoToNextStep();
-                    }
-                    else
-                    {
-                        Log.Error("KeySyncWizard: Error creating handshake item.");
-                        this.GoToLastStep(false);
-                    }
-                }
-                catch (Exception ex)
-                {
-                    Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
-                    this.GoToLastStep(false);
-                }
+            // Send initial message if necessary
+            if (this.IsInitiator)
+            {
+                this.SendSyncMessage(MessageTypes.InitialMessage);
             }
         }
 
@@ -180,15 +133,42 @@
          *************************************************************/
 
         /// <summary>
-        /// Gets or sets the explanatory text in the wizard.
+        /// Gets or sets the Items collection.
         /// </summary>
-        public string ExplanationText
+        public WizardState CurrentState
         {
-            get { return this._ExplanationText; }
+            get { return this._CurrentState; }
             set
             {
-                this._ExplanationText = value;
-                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
+                this._CurrentState = value;
+                this.RaisePropertyChangedEvent(nameof(this.CurrentState));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to export the private key.
+        /// </summary>
+        public bool ExportPrivateKey
+        {
+            get { return this._ExportPrivateKey; }
+            set
+            {
+                this._ExportPrivateKey = value;
+                this.RaisePropertyChangedEvent(nameof(this.ExportPrivateKey));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether this wizard is the one that
+        /// initiated the Key Import process.
+        /// </summary>
+        public bool IsInitiator
+        {
+            get { return this._IsInitiator; }
+            set
+            {
+                this._IsInitiator = value;
+                this.RaisePropertyChangedEvent(nameof(this.IsInitiator));
             }
         }
 
@@ -219,19 +199,6 @@
         }
 
         /// <summary>
-        /// Gets or sets the Next/Finish button's text.
-        /// </summary>
-        public string NextButtonText
-        {
-            get { return this._NextButtonText; }
-            set
-            {
-                this._NextButtonText = value;
-                this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
-            }
-        }
-
-        /// <summary>
         /// Gets or sets the sync partner.
         /// </summary>
         public PEPIdentity Partner
@@ -245,56 +212,35 @@
         }
 
         /// <summary>
-        /// Gets or sets the wizard state.
+        /// Gets or sets the current wizard step.
         /// </summary>
-        public WizardState State
+        public Steps Step
         {
-            get { return this._State; }
+            get { return this._Step; }
             set
             {
-                this._State = value;
-                this.RaisePropertyChangedEvent(nameof(this.State));
+                this._Step = value;
+                this.RaisePropertyChangedEvent(nameof(this.Step));
             }
         }
 
         /// <summary>
-        /// Gets or sets the subtitle text in the wizard.
+        /// Gets or sets whether to use the imported key as default key.
         /// </summary>
-        public string SubtitleText
+        public bool SetImportedKeyAsDefault
         {
-            get { return this._SubtitleText; }
+            get { return this._SetImportedKeyAsDefault; }
             set
             {
-                this._SubtitleText = value;
-                this.RaisePropertyChangedEvent(nameof(this.SubtitleText));
+                this._SetImportedKeyAsDefault = value;
+                this.RaisePropertyChangedEvent(nameof(this.SetImportedKeyAsDefault));
             }
         }
 
         /// <summary>
         /// Gets or sets the success state.
         /// </summary>
-        public bool Success
-        {
-            get { return this._Success; }
-            set
-            {
-                this._Success = value;
-                this.RaisePropertyChangedEvent(nameof(this.Success));
-            }
-        }
 
-        /// <summary>
-        /// Gets or sets the title text in the wizard.
-        /// </summary>
-        public string TitleText
-        {
-            get { return this._TitleText; }
-            set
-            {
-                this._TitleText = value;
-                this.RaisePropertyChangedEvent(nameof(this.TitleText));
-            }
-        }
 
         /// <summary>
         /// Gets or sets the wizard type.
@@ -309,6 +255,35 @@
             }
         }
 
+        /// <summary>
+        /// Gets the user name to display in the dialog.
+        /// </summary>
+        public string UserName
+        {
+            get
+            {
+                string userName = string.Empty;
+
+                // Try to get user name in format "name (address)"
+                if (string.IsNullOrEmpty(this.Myself?.UserName) == false)
+                {
+                    userName = this.Myself.UserName;
+
+                    if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+                    {
+                        userName += " (" + this.Myself.Address + ")";
+                    }
+                }
+                // If we have no user name, just display address
+                else if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+                {
+                    userName = this.Myself.Address;
+                }
+
+                return userName;
+            }
+        }
+
         #endregion
 
         #region Event handlers
@@ -318,39 +293,195 @@
          * 
          *************************************************************/
 
+        /// <summary>
+        /// Event handler for when the OK/Next button is clicked.
+        /// </summary>
+        private void AcceptButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.CurrentState.AcceptButtonClick();
+        }
+
+        /// <summary>
+        /// Event handler for when the Back button is clicked.
+        /// </summary>
+        private void BackButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.CurrentState.BackButtonClick();
+        }
+
+        /// <summary>
+        /// Event handler for when the Cancel button is clicked.
+        /// </summary>
         private void CancelButton_Click(object sender, RoutedEventArgs e)
         {
-            this.Close();
+            this.CurrentState.CancelButtonClick();
         }
 
-        private void OKNextButton_Click(object sender, RoutedEventArgs e)
+        /// <summary>
+        /// Event handler for when a sync message arrives while the wizard is open and in progress.
+        /// </summary>
+        private void KeySyncWizard_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
         {
-            // Navigation logic
-            switch (this.State)
+            // Ignore outgoing messages
+            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
             {
-                case WizardState.Step2:
+                try
+                {
+                    // Waiting for message with public key from other device
+                    if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step1)) ||
+                        ((this.Type == WizardType.PGP) && (this.Step == Steps.Step4)))
                     {
-                        // User accepts the fingerprint. Make channel green.
-                        this.TrustKey();
+                        string partnerFpr = null;
+
+                        // Make sure the channel is not already trusted (either attack or re-processing)
+                        if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
+                        {
+                            Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
+                            return;
+                        }
+
+                        // In case of pEp sync, use header
+                        if (this.Type == WizardType.pEp)
+                        {
+                            // Public key message received. Show trustwords.
+                            partnerFpr = e.Message?.KeyImport;
+
+                            Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
+
+                            // Doublecheck that it's not the own key
+                            if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
+                            {
+                                partnerFpr = null;
+                            }
+                        }
+                        else if (this.Type == WizardType.PGP)
+                        {
+                            // In case of PGP import, use key list
+                            string[] keys = e.Message?.KeyList?.Split(',');
+                            for (int i = 0; i < keys?.Length; i++)
+                            {
+                                if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
+                                {
+                                    partnerFpr = keys[i];
+                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
+                                    break;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
+                        }
+
+                        // If we have a valid fingerprint, show Trustwords
+                        if ((this.IsInitiator) &&
+                            (string.IsNullOrEmpty(partnerFpr) == false))
+                        {
+                            // Set the partner's fingerprint
+                            this.Partner.Fingerprint = partnerFpr;
+
+                            // Marshall to main thread
+                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+                            {
+                                // Create the handshake item 
+                                if (this.CreateHandshakeItem())
+                                {
+                                    this.GoToNextStep();
+                                }
+                                else
+                                {
+                                    Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
+                                    this.GoToLastStep(false);
+                                }
+                            }));
+                        }
+                        else
+                        {
+                            Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
+                        }
                     }
-                    break;
-                /* 'Step 1' and 'Step 3' are not clickable. 
-                 * 'Step 4' finishes the process. 
-                 * 'Undefined' means an error occured.
-                 */
-                case WizardState.Step1:
-                case WizardState.Step3:
-                case WizardState.Step4:
-                case WizardState.Undefined:
-                default:
+                    // Waiting for private key message
+                    else if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step3)) ||
+                             ((this.Type == WizardType.PGP) && (this.Step == Steps.Step8)))
                     {
-                        this.Close();
+                        /* Finish the process under the following conditions:
+                         *  1. PGP key import + own private key flag
+                         *  2. pEp key import +
+                         *      a. initiator wizard + own private key flag + partner fpr in key import header
+                         *      b. not initiator wizard + trusted message + partner fpr in key import header
+                         */
+                        bool hasDecryptFlagOwnPrivateKey = e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey);
+                        if (((this.Type == WizardType.PGP) && (hasDecryptFlagOwnPrivateKey)) ||
+                            ((this.IsInitiator) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (hasDecryptFlagOwnPrivateKey)) ||
+                            ((this.IsInitiator == false) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (e.Message.Rating >= pEpRating.pEpRatingTrusted)))
+                        {
+                            // Set flag
+                            this.privateKeyImported = hasDecryptFlagOwnPrivateKey;
+
+                            // Marshall to main thread
+                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+                            {
+                                // Set private key as default if needed
+                                bool success = false;
+                                if ((this.IsInitiator) &&
+                                    (this.SetImportedKeyAsDefault))
+                                {
+                                    try
+                                    {
+                                        pEpIdentity partner = this.Partner.ToCOMType();
+                                        ThisAddIn.PEPEngine.SetOwnKey(partner, partner.fpr);
+                                        success = true;
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        success = false;
+                                        Log.Error("AcceptButtonClick: Error setting own key. " + ex.ToString());
+                                    }
+                                }
+                                else
+                                {
+                                    success = true;
+                                }
+
+                                this.GoToLastStep(success);
+
+                            }));
+                        }
+                        else
+                        {
+                            Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. Steps: Step 3. Own private key flag is " +
+                                        e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
+                                        Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
+                                        e.Message?.KeyImport ?? "null");
+                        }
                     }
-                    break;
+                }
+                catch (Exception ex)
+                {
+                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+                }
             }
         }
 
         /// <summary>
+        /// Event handler for when the label next to the Export Private Key checkbox
+        /// is clicked.
+        /// </summary>
+        private void LabelExportPrivateKey_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            this.ExportPrivateKey = (this.ExportPrivateKey == false);
+        }
+
+        /// <summary>
+        /// Event handler for when the label next to the Set Imported Key As Default checkbox
+        /// is clicked.
+        /// </summary>
+        private void LabelSetImportedKeyAsDefault_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            this.SetImportedKeyAsDefault = (this.SetImportedKeyAsDefault == false);
+        }
+
+        /// <summary>
         /// Raises the property changed event, if possible, with the given arguments.
         /// </summary>
         /// <param name="propertyName">The name of the property that changed.</param>
@@ -361,127 +492,40 @@
         }
 
         /// <summary>
-        /// Event handler for when a sync message arrives while the wizard is open and in progress.
+        /// Shows the handshake window
         /// </summary>
-        private void KeySyncWizard_SyncMessageReceived(object sender, CryptableMailItem.SyncMessageEventArgs e)
+        private bool ShowHandshake()
         {
-            // Ignore outgoing messages
-            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
-            {
-                try
-                {
-                    switch (this.State)
-                    {
-                        // Step 1: get partner fingerprint and show Trustwords
-                        case WizardState.Step1:
-                            {
-                                string partnerFpr = null;
-
-                                // Make sure the channel is not already trusted (either attack or re-processing)
-                                if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
-                                {
-                                    Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
-                                    return;
-                                }
-
-                                // In case of pEp sync, use header
-                                if (this.Type == WizardType.pEp)
-                                {
-                                    // Public key message received. Show trustwords.
-                                    partnerFpr = e.Message?.KeyImport;
-
-                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
-
-                                    // Doublecheck that it's not the own key
-                                    if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
-                                    {
-                                        partnerFpr = null;
-                                    }
-                                }
-                                else if (this.Type == WizardType.PGP)
-                                {
-                                    // In case of PGP import, use key list
-                                    string[] keys = e.Message?.KeyList?.Split(',');
-                                    for (int i = 0; i < keys?.Length; i++)
-                                    {
-                                        if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
-                                        {
-                                            partnerFpr = keys[i];
-                                            Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
-                                            break;
-                                        }
-                                    }
-                                }
-                                else
-                                {
-                                    Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
-                                }
+            bool success = false;
 
-                                // If we have a valid fingerprint, show Trustwords
-                                if (string.IsNullOrEmpty(partnerFpr) == false)
-                                {
-                                    // Set the partner's fingerprint
-                                    this.Partner.Fingerprint = partnerFpr;
+            try
+            {
+                // Update own identity if necessary
+                if (string.IsNullOrEmpty(this.Myself?.Fingerprint))
+                {
+                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
+                }
 
-                                    // Marshall to main thread
-                                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
-                                    {
-                                        // Create the handshake item 
-                                        if (this.CreateHandshakeItem())
-                                        {
-                                            this.GoToNextStep();
-                                        }
-                                        else
-                                        {
-                                            Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
-                                            this.GoToLastStep(false);
-                                        }
-                                    }));
-                                }
-                                else
-                                {
-                                    Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
-                                }
-                            }
-                            break;
-                        case WizardState.Step2:
-                            {
-                                Log.Verbose("KeySyncWizard_SyncMessageReceived: Nothing done. WizardState is Step 2.");
-                            }
-                            break;
-                        case WizardState.Step3:
-                            {
-                                /* Finish the process if a private key has been imported and the message
-                                 * is at least trusted.
-                                 * For pEp key import, check also that we don't import our own key.
-                                 */ 
-                                if ((e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)) &&
-                                    (e.Message.Rating >= pEpRating.pEpRatingTrusted) &&
-                                    ((e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) ||
-                                     (this.Type == WizardType.PGP)))
-                                {
-                                    this.CompleteWizard();
-                                }
-                                else
-                                {
-                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. WizardState: Step 3. Own private key flag is " +
-                                                e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
-                                                Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
-                                                e.Message?.KeyImport ?? "null");
-                                }
-                            }
-                            break;
-                        case WizardState.Step4:
-                        case WizardState.Undefined:
-                        default:
-                            break;
-                    }
+                // Create handshake item
+                if (this.CreateHandshakeItem())
+                {
+                    // Set success flag
+                    success = true;
+
+                    // Send answer message with pub key
+                    this.SendSyncMessage(MessageTypes.PublicKeyMessage);
                 }
-                catch (Exception ex)
+                else
                 {
-                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+                    Log.Error("KeySyncWizard: Error creating handshake item.");
                 }
             }
+            catch (Exception ex)
+            {
+                Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
+            }
+
+            return success;
         }
 
         /// <summary>
@@ -490,7 +534,7 @@
         private void Window_Closed(object sender, EventArgs e)
         {
             // Remove event handler
-            CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
+            MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
 
             // Reset static references
             KeySyncWizard.Wizard = new KeySyncWizard();
@@ -506,18 +550,69 @@
          *************************************************************/
 
         /// <summary>
+        /// Adds the given PEPMessage to the list of received sync messages.
+        /// </summary>
+        /// <param name="message">The PEPMessage to add to the list.</param>
+        public void AddToReceivedSyncMessages(PEPMessage message)
+        {
+            /* Add message to list if:
+             *  1.  a. WizardType is PGP and message is secure
+             *      b. WizardType is pEp, the current step is Step 2 and the
+             *         message hasn't been sent from myself
+             *  2. Message is not in the list yet
+             */
+            lock (mutexReceivedSyncMessages)
+            {
+                if (((this.Type == WizardType.PGP) &&
+                     (message.IsSecure) ||
+                     ((this.Type == WizardType.pEp) &&
+                      (this.Step == Steps.Step2) &&
+                      (this.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))) &&
+                    (this.receivedSyncMessages?.Find(a => (a.Id?.Equals(message.Id) == true)) == null))
+                {
+                    this.receivedSyncMessages?.Add(message);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Closes the wizard and resets the partner identity in the management.db.
+        /// </summary>
+        private void CancelWizard()
+        {
+            try
+            {
+                pEpIdentity partner = this.Partner.Copy().ToCOMType();
+
+                if (string.IsNullOrEmpty(partner.fpr) == false)
+                {
+                    Task.Factory.StartNew(new Action(() =>
+                    {
+                        ThisAddIn.PEPEngine.KeyResetTrust(partner);
+                    }), TaskCreationOptions.LongRunning);
+                }
+            }
+            catch (Exception ex)
+            {
+                Log.Error("CancelWizard: Error resetting identity. " + ex.ToString());
+            }
+
+            this.Close();
+        }
+
+        /// <summary>
         /// Completes the process and moves wizard to last step.
         /// Sets the imported private key as own key, if needed.
         /// </summary>
         private void CompleteWizard()
         {
             // Marshall to main thread
-            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
+            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
             {
                 bool success = false;
 
                 // Private key message received. Set key as default if needed.
-                if (this.isInitiator)
+                if (this.IsInitiator)
                 {
                     try
                     {
@@ -553,9 +648,10 @@
             HandshakeItem item;
             if (HandshakeItem.Create(this.Myself, this.Partner, false, out item) == Globals.ReturnStatus.Success)
             {
-                item.AreTabControlsVisible = (this.Type == WizardType.PGP);
+                item.AreTabControlsVisible = false;
                 item.ActiveTab = (this.Type == WizardType.pEp) ? HandshakeItem.Tabs.Trustwords : HandshakeItem.Tabs.Fingerprint;
                 item.AreHandshakeButtonsVisible = false;
+                item.Mode = HandshakeItem.HandshakeMode.Sync;
                 this.Items.Add(item);
 
                 success = true;
@@ -566,17 +662,658 @@
         }
 
         /// <summary>
+        /// Creates a list of wizard states that serve as model for the wizard.
+        /// The pEp Key Import process consists of the following steps:
+        ///     Step 1:
+        ///         a. Is initiator(user opened wizard): Info message that sync message has been sent.
+        ///            Waiting for answer message from other device.
+        ///         b. Is not initiator (wizard opened through sync message): Info message that key import has been started.
+        ///            Waiting for user decision to continue or abort.
+        ///     Step 2:
+        ///         - Show trustwords. User interaction: confirm or cancel.
+        ///     Step 3: 
+        ///         - Private keys have been sent. Waiting for answer message from other device.
+        ///     Step 4: 
+        ///         - Only on initiator side: Ask user if they want to set imported key as default. Next or Cancel.
+        ///     Success:
+        ///         - Key Import successfully finished.
+        ///     Error:
+        ///         - An error occured during the Key Import process.
+        /// </summary>
+        /// <returns>The list of wizard states.</returns>
+        private List<WizardState> CreatePEPWizardStates()
+        {
+            List<WizardState> states = new List<WizardState>();
+
+            try
+            {
+                // Step 1
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step1,
+
+                    // Title text
+                    TitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_PEPStep1ExplanationText : Properties.Resources.KeySyncWizard_PEPStep1NonInitiatorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Start,
+                    IsAcceptButtonVisible = (this.IsInitiator == false),
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        if (this.ShowHandshake())
+                        {
+                            this.GoToNextStep();
+                        }
+                        else
+                        {
+                            this.GoToLastStep(false);
+                        }
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_WaitingForResponseText : null
+                });
+
+                // Step 2
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step2,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PEPStep2ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = true,
+                    IsUserTextVisible = false,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.Handshake_ConfirmTrustwords,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.TrustKey();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Handshake_WrongTrustwords,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 3
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step3,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PEPStep3ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText
+                });
+
+                // Success
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Success,
+
+                    // Title text
+                    TitleText = null,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.Close();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Error
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Error,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+            }
+            catch (Exception ex)
+            {
+                states = null;
+                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+            }
+
+            return states;
+        }
+
+        /// <summary>
+        /// Creates a list of wizard states that serve as model for the wizard.
+        /// The PGP Key Import process consists of the following steps:
+        ///     Steps 1-3:
+        ///         - Instructions on how to prepare the answer message with pub key.
+        ///     Step 4: 
+        ///         - Waiting for answer message from other device.
+        ///     Step 5: 
+        ///         - Show fingerprints. Confirm or deny them.        
+        ///     Step 6 - 7: 
+        ///         - Instructions on how to prepare the answer message with private key.
+        ///     Success:
+        ///         - Key Import successfully finished.
+        ///     Error:
+        ///         - An error occured during the Key Import process.
+        /// </summary>
+        /// <returns>The list of wizard states.</returns>
+        private List<WizardState> CreatePGPWizardStates()
+        {
+            List<WizardState> states = new List<WizardState>();
+
+            try
+            {
+                // Step 1
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step1,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep1ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 2
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step2,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep2ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 3
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step3,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep3ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.ProcessReceivedSyncMessages();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 4
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step4,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 5
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step5,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep5ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = true,
+                    IsUserTextVisible = false,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.Handshake_ConfirmFingerprint,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.TrustKey();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Handshake_WrongFingerprint,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 6
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step6,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep6ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 7
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step7,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep7ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.ProcessReceivedSyncMessages();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 8
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step8,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Success
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Success,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPSuccessExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.Close();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Error
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Error,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+            }
+            catch (Exception ex)
+            {
+                states = null;
+                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+            }
+
+            return states;
+        }
+
+        /// <summary>
         /// Navigates to the last step of the wizard.
         /// </summary>
         /// <param name="success">Whether or not the wizard has been completed successfully.</param>
         private void GoToLastStep(bool success)
         {
             // Go to last step
-            this.State = WizardState.Step4;
-            this.Success = success;
+            this.Step = success ? Steps.Success : Steps.Error;
 
-            // Update content
-            this.UpdateContent();
+            // Update wording and state
+            var lastState = this.states.Find(a => a.Step == this.Step);
+            if (this.IsInitiator)
+            {
+                if (this.SetImportedKeyAsDefault)
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault;
+                }
+                else
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+                }
+            }
+            else
+            {
+                if (this.privateKeyImported)
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+                }
+                else
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport;
+                }
+            }
+
+            // Apply state
+            this.CurrentState = lastState;
 
             Log.Verbose("GoToLastStep: Process finished. Success is " + success.ToString());
         }
@@ -587,26 +1324,42 @@
         private void GoToNextStep()
         {
             // Go to next step
-            this.State++;
+            this.Step++;
+
+            // Set current state
+            this.CurrentState = states.Find(a => a.Step == this.Step);
+
+            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
+        }
 
-            // Update content
-            this.UpdateContent();
+        /// <summary>
+        /// Navigates to the previous state of the wizard.
+        /// </summary>
+        private void GoToPreviousStep()
+        {
+            // Go to next step
+            this.Step--;
 
-            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(WizardState), this.State));
+            // Set current state
+            this.CurrentState = states.Find(a => a.Step == this.Step);
+
+            Log.Verbose("GoToPreviousStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
         }
 
         /// <summary>
         /// Initializes the wizard.
         /// </summary>
-        private void InitializeWizard(WizardType type,
+        private void InitializeWizard(bool isInitiator,
+                                      WizardType type,
                                       PEPIdentity myself,
                                       string partnerFpr)
         {
             // Set initial state
             this.DataContext = this;
             this.Myself = myself;
-            this.State = WizardState.Step1;
+            this.Step = Steps.Step1;
             this.Type = type;
+            this.IsInitiator = isInitiator;
 
             // If own identity is null, get default account
             if (this.Myself == null)
@@ -699,8 +1452,39 @@
                 this.Partner.Fingerprint = partnerFpr;
             }
 
-            // Update dialog content
-            this.UpdateContent();
+            // Define states
+            this.states = (this.Type == WizardType.pEp) ? this.CreatePEPWizardStates() : this.CreatePGPWizardStates();
+
+            // Set current state
+            this.CurrentState = states?.Find(a => a.Step == Steps.Step1);
+        }
+
+        /// <summary>
+        /// Runs through all received sync messages.
+        /// </summary>
+        private void ProcessReceivedSyncMessages()
+        {
+            lock (mutexReceivedSyncMessages)
+            {
+                if (this.receivedSyncMessages != null)
+                {
+                    foreach (var message in this.receivedSyncMessages)
+                    {
+                        try
+                        {
+                            Task.Factory.StartNew(new Action(() =>
+                            {
+                                MsgProcessor msgProcessor = new MsgProcessor();
+                                msgProcessor.Decrypt(message);
+                            }));
+                        }
+                        catch (Exception ex)
+                        {
+                            Log.Error("ProcessReceivedSyncMessages: Error processing sync message. " + ex.ToString());
+                        }
+                    }
+                }
+            }
         }
 
         /// <summary>
@@ -714,93 +1498,117 @@
             {
                 try
                 {
-                    // If we have no partner at this point, use a copy of myself
-                    if (this.Partner == null)
-                    {
-                        this.Partner = this.Myself.Copy();
-                        Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
-                    }
-
-                    // Create basic message
-                    bool processMessage = true;
-                    PEPMessage message = new PEPMessage
+                    // Start sending in background
+                    Task.Factory.StartNew(new Action(() =>
                     {
-                        From = this.Myself,
-                        ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
-                        LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
-                        AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
-                        Direction = pEpMsgDirection.pEpDirOutgoing,
-                        ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
-                        KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
-                    };
-                    message.To.Add(this.Partner);
+                        // If we have no partner at this point, use a copy of myself
+                        if (this.Partner == null)
+                        {
+                            this.Partner = this.Myself.Copy();
+                            this.Partner.Fingerprint = null;
+                            Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
+                        }
+
+                        // Create basic message
+                        bool processMessage = true;
+                        PEPMessage message = new PEPMessage
+                        {
+                            From = this.Myself,
+                            ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
+                            LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
+                            AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
+                            Direction = pEpMsgDirection.pEpDirOutgoing,
+                            ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
+                            KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
+                        };
+                        message.To.Add(this.Partner);
+
+                        Log.Verbose("SendSyncMessage: Basic message successfully created.");
 
-                    Log.Verbose("SendSyncMessage: Basic message successfully created.");
+                        // If message type isn't InitialMessage, encrypt it accordingly
+                        PEPMessage msg;
+                        MsgProcessor msgProcessor = new MsgProcessor();
+                        if ((messageType == MessageTypes.PrivateKeyMessage) &&
+                            (this.ExportPrivateKey))
+                        {
+                            // Encrypt and add private key
+                            if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+                            {
+                                Log.Verbose("SendSyncMessage: Private key message successfully created.");
+                                message = msg;
+                                processMessage = false;
+                            }
+                            else
+                            {
+                                Log.Error("SendSyncMessage: Error encrypting private key message.");
+                                message = null;
+                            }
+                        }
+                        else if (((messageType == MessageTypes.PrivateKeyMessage) &&
+                                  (this.ExportPrivateKey == false)) ||
+                                 (messageType == MessageTypes.PublicKeyMessage))
+                        {
+                            // Encrypt using partner fpr as extra key
+                            if (msgProcessor.Encrypt(message, new string[] { this.Partner.Fingerprint }, out msg))
+                            {
+                                Log.Verbose("SendSyncMessage: Public key message successfully created.");
+                                message = msg;
+                                processMessage = false;
+                            }
+                            else
+                            {
+                                Log.Error("SendSyncMessage: Error encrypting public key message.");
+                                message = null;
+                            }
+                        }
 
-                    // If the message is the private key transport message, add own private key
-                    PEPMessage msg;
-                    if (messageType == MessageTypes.PrivateKeyMessage)
-                    {
-                        MsgProcessor msgProcessor = new MsgProcessor();
-                        if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+                        // If we have a message, send it
+                        if (message != null)
                         {
-                            Log.Verbose("SendSyncMessage: Private key message successfully created.");
-                            message = msg;
-                            processMessage = false;
+                            Log.Verbose("SendSyncMessage: Sending message...");
+
+                            // Disable passive mode if needed
+                            bool reenablePassiveMode = false;
+                            if ((messageType == MessageTypes.InitialMessage) &&
+                                (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
+                            {
+                                try
+                                {
+                                    ThisAddIn.PEPEngine.PassiveMode(false);
+                                    reenablePassiveMode = true;
+                                    Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
+                                }
+                                catch (Exception ex)
+                                {
+                                    Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
+                                }
+                            }
+
+                            // Send message
+                            Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
+
+                            // Log that message has been sent
+                            this.sentMessages?.Add(messageType);
+
+                            // Reenable passive mode if needed
+                            if (reenablePassiveMode)
+                            {
+                                try
+                                {
+                                    ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
+                                    Log.Verbose("SendSyncMessage: Passive mode reenabled.");
+                                }
+                                catch (Exception ex)
+                                {
+                                    Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
+                                }
+                            }
                         }
                         else
                         {
-                            Log.Error("SendSyncMessage: Error encrypting private key message.");
-                            message = null;
-                        }
-                    }
-
-                    // If we have a message, send it
-                    if (message != null)
-                    {
-                        Log.Verbose("SendSyncMessage: Sending message...");
-
-                        // Disable passive mode if needed
-                        bool reenablePassiveMode = false;
-                        if ((messageType == MessageTypes.InitialMessage) &&
-                            (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
-                        {
-                            try
-                            {
-                                ThisAddIn.PEPEngine.PassiveMode(false);
-                                reenablePassiveMode = true;
-                                Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
-                            }
-                            catch (Exception ex)
-                            {
-                                Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
-                            }
+                            Log.Error("SendSyncMessage: Myself identity is null.");
                         }
-
-                        // Send message
-                        Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage);
-
-                        // Log that message has been sent
-                        this.sentMessages?.Add(messageType);
-
-                        // Reenable passive mode if needed
-                        if (reenablePassiveMode)
-                        {
-                            try
-                            {
-                                ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
-                                Log.Verbose("SendSyncMessage: Passive mode reenabled.");
-                            }
-                            catch (Exception ex)
-                            {
-                                Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
-                            }
-                        }
-                    }
-                    else
-                    {
-                        Log.Error("SendSyncMessage: Myself identity is null.");
-                    }
+                    }), TaskCreationOptions.LongRunning);
                 }
                 catch (Exception ex)
                 {
@@ -810,7 +1618,7 @@
         }
 
         /// <summary>
-        /// Trusts the communication partner key (makes the channel green)
+        /// Trusts the communication partner key (makes the channel green).
         /// </summary>
         private void TrustKey()
         {
@@ -818,31 +1626,28 @@
             {
                 try
                 {
-                    Log.Verbose("TrustKey: Trusting partner key...");
-
-                    this._Partner = this.Items[0].Partner;
-                    pEpIdentity partner = this._Partner.ToCOMType();
-                    ThisAddIn.PEPEngine.TrustPersonalKey(partner);
-
-                    // If Trustwords are being accepted after having received
-                    // the private key, finish process.
-                    if (this.State == WizardState.Step3)
+                    // Run in background
+                    Task.Factory.StartNew(new Action(() =>
                     {
-                        Log.Verbose("TrustKey: Private key already received. Completing wizard.");
-                        this.CompleteWizard();
-                    }
-                    else
+                        Log.Verbose("TrustKey: Trusting partner key...");
+
+                        // Trust the partner's key
+                        this._Partner = this.Items[0].Partner;
+                        pEpIdentity partner = this._Partner.ToCOMType();
+                        ThisAddIn.PEPEngine.TrustPersonalKey(partner);
+
+                        // Process messages that might have been received
+                        this.ProcessReceivedSyncMessages();
+
+                    }), TaskCreationOptions.LongRunning).ContinueWith(new Action<Task>((result) =>
                     {
-                        Log.Verbose("TrustKey: No private key received yet. Going to next step.");
-                        this.GoToNextStep();
-                    }
-
-                    // In pEp sync mode, send private key to partner
-                    if (this.Type == WizardType.pEp)
-                    {
-                        Log.Verbose("TrustKey: Sending private key to partner.");
-                        this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
-                    }
+                        // In pEp sync mode, send private key message to partner
+                        if (this.Type == WizardType.pEp)
+                        {
+                            Log.Verbose("TrustKey: Sending private key to partner.");
+                            this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
+                        }
+                    }));
                 }
                 catch (Exception ex)
                 {
@@ -858,108 +1663,42 @@
         }
 
         /// <summary>
-        /// Updates the dialog content according to its current state.
-        /// </summary>
-        private void UpdateContent()
-        {
-            // Set title
-            if (string.IsNullOrEmpty(this._TitleText))
-            {
-                this.TitleText = this.TitleText = this.Myself?.Address;
-            }
-
-            // Set content according to state
-            switch (this.State)
-            {
-                case WizardState.Step1:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step1PEPExplanationText : Properties.Resources.KeySyncWizard_Step1PGPExplanationText;
-                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_WaitingForResponseText : Properties.Resources.KeySyncWizard_Step1PGPSubtitleText;
-                    }
-                    break;
-                case WizardState.Step2:
-                    {
-                        this.NextButtonText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step2PEPExplanationText : Properties.Resources.KeySyncWizard_Step2PGPExplanationText;
-                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
-                    }
-                    break;
-                case WizardState.Step3:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step3PEPExplanationText : Properties.Resources.KeySyncWizard_Step3PGPExplanationText;
-                        this.SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText;
-                    }
-                    break;
-                case WizardState.Step4:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
-
-                        if (this.Success)
-                        {
-                            this.SubtitleText = Properties.Resources.KeySyncWizard_SuccessText;
-
-                            switch (this.Type)
-                            {
-                                case WizardType.PGP:
-                                    {
-                                        this.ExplanationText = Properties.Resources.KeySyncWizard_Step4SuccessExplanationText;
-                                    }
-                                    break;
-                                case WizardType.pEp:
-                                    {
-                                        if (this.isInitiator)
-                                        {
-                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessInitiatorExplanationText;
-                                        }
-                                        else
-                                        {
-                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText;
-                                        }
-                                    }
-                                    break;
-                                case WizardType.Undefined:
-                                default:
-                                    {
-                                        this.ExplanationText = string.Empty;
-                                    }
-                                    break;
-                            }
-                        }
-                        else
-                        {
-                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4ErrorExplanationText;
-                            this.SubtitleText = Properties.Resources.KeySyncWizard_ErrorText;
-                        }
-                    }
-                    break;
-                case WizardState.Undefined:
-                default:
-                    this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
-                    this.ExplanationText = string.Empty;
-                    this.SubtitleText = string.Empty;
-                    break;
-            }
-        }
-
-        /// <summary>
         /// Resets the object to its defaults.
         /// </summary>
         public void Reset()
         {
-            this._ExplanationText = null;
+            this._CurrentState = new WizardState();
+            this._ExportPrivateKey = true;
+            this._IsInitiator = false;
             this._Items = new ObservableCollection<HandshakeItem>();
             this._Myself = null;
-            this._NextButtonText = null;
             this._Partner = null;
-            this._State = WizardState.Undefined;
-            this._SubtitleText = null;
-            this._Success = false;
+            this._Step = Steps.Undefined;
+            this._SetImportedKeyAsDefault = true;
             this._Type = WizardType.Undefined;
-            this._TitleText = null;
         }
 
         #endregion
+
+        /// <summary>
+        /// Container to define a wizard state.
+        /// </summary>
+        public class WizardState
+        {
+            public Action                   AcceptButtonClick           { get; set; }   =   null;
+            public string                   AcceptButtonText            { get; set; }   =   null;
+            public bool                     AreTrustwordsVisible        { get; set; }   =   false;
+            public Action                   BackButtonClick             { get; set; }   =   null;
+            public Action                   CancelButtonClick           { get; set; }   =   null;
+            public string                   CancelButtonText            { get; set; }   =   null;
+            public bool                     IsAcceptButtonVisible       { get; set; }   =   true;
+            public bool                     IsBackButtonVisible         { get; set; }   =   false;
+            public bool                     IsCancelButtonVisible       { get; set; }   =   true;
+            public bool                     IsUserTextVisible           { get; set; }   =   true;
+            public KeySyncWizard.Steps      Step                        { get; set; }   =   Steps.Undefined;
+            public string                   SubtitleText                { get; set; }   =   null;
+            public string                   TitleText                   { get; set; }   =   null;
+            public string                   UserText                    { get; set; }   =   null;
+        }
     }
 }
--- a/UI/ValueConverters.cs	Thu May 10 12:38:22 2018 +0200
+++ b/UI/ValueConverters.cs	Thu May 17 11:26:23 2018 +0200
@@ -276,61 +276,6 @@
     }
 
     /// <summary>
-    /// Returns a bool value indicating if the wizard state matches any of the given parameter.
-    /// </summary>
-    public class IsWizardStateConverter : IValueConverter
-    {
-        public object Convert(object value,
-                              Type targetType,
-                              object parameter,
-                              CultureInfo culture)
-        {
-            bool success;
-            KeySyncWizard.WizardState param;
-
-            if ((value is KeySyncWizard.WizardState) &&
-                (parameter is string))
-            {
-                string[] parameters = (parameter as string).Split('|');
-
-                if (parameters?.Length > 0)
-                {
-                    foreach (var p in parameters)
-                    {
-                        success = Enum.TryParse(p, out param);
-
-                        if (success)
-                        {
-                            if (((KeySyncWizard.WizardState)value) == param)
-                            {
-                                return true;
-                            }
-                        }
-                        else
-                        {
-                            throw new ArgumentException();
-                        }
-                    }
-                }
-
-                return false;
-            }
-            else
-            {
-                throw new ArgumentException();
-            }
-        }
-
-        public object ConvertBack(object value,
-                                  Type targetType,
-                                  object parameter,
-                                  CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
-    }
-
-    /// <summary>
     /// Converter to check if a list is empty.
     /// </summary>
     public class IsListEmptyConverter : IValueConverter
@@ -530,6 +475,38 @@
     }
 
     /// <summary>
+    /// Returns true if the Wizard is in the given state.
+    /// </summary>
+    public class IsWizardTypeConverter : IValueConverter
+    {
+        public object Convert(object value,
+                              Type targetType,
+                              object parameter,
+                              CultureInfo culture)
+        {
+            string val = null;
+            string param = parameter as string;
+
+            try
+            {
+                val = Enum.GetName(typeof(KeySyncWizard.WizardType), value);
+            }
+            catch
+            {
+                val = null;
+            }
+
+            return (param?.Equals(val) == true);
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+
+    /// <summary>
     /// Converter to AND several bool values and convert to Visibility.
     /// </summary>
     public class MultiBooleanToVisibilityConverter : IMultiValueConverter