Merge with OUT-428
authorThomas
Thu, 17 May 2018 11:21:56 +0200
changeset 21995c8c43f38243
parent 2185 a3f839db149f
parent 2198 fdda622085c6
child 2200 c578f001cfe5
child 2201 5c9f9d4ec13f
Merge with OUT-428
     1.1 --- a/CryptableMailItem.cs	Thu May 10 15:04:25 2018 +0200
     1.2 +++ b/CryptableMailItem.cs	Thu May 17 11:21:56 2018 +0200
     1.3 @@ -97,12 +97,6 @@
     1.4          public delegate void OriginallyEncryptedStatusUpdateHandler(object sender, EventArgs e);
     1.5          public event OriginallyEncryptedStatusUpdateHandler OriginallyEncryptedStatusUpdated;
     1.6  
     1.7 -        /// <summary>
     1.8 -        /// Event handler for when a sync message is being detected during decryption.
     1.9 -        /// </summary>
    1.10 -        public delegate void SyncMessageReceivedHandler(object sender, CryptableMailItem.SyncMessageEventArgs e);
    1.11 -        public static event SyncMessageReceivedHandler SyncMessageReceived;
    1.12 -
    1.13          private pEpRating            _LastProcessedRating;
    1.14          private Globals.ReturnStatus _LastProcessedStatus;
    1.15  
    1.16 @@ -1227,9 +1221,18 @@
    1.17                          // Wait for the other thread to finish
    1.18                          if (isAlreadyBeingDecrypted)
    1.19                          {
    1.20 -                            Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
    1.21 -                            Thread.Sleep(sleepTime);
    1.22 -                            curWaitTime += sleepTime;
    1.23 +                            // Do not process multiple times if it is an automatic message
    1.24 +                            if (this.internalMailItem.GetIsAutoConsume())
    1.25 +                            {
    1.26 +                                curWaitTime = maxWaitTime + 1;
    1.27 +                                Log.Verbose("ProcessAndGetRating: Setting timeout for AutoConsume message.");
    1.28 +                            }
    1.29 +                            else
    1.30 +                            {
    1.31 +                                Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
    1.32 +                                Thread.Sleep(sleepTime);
    1.33 +                                curWaitTime += sleepTime;
    1.34 +                            }
    1.35                          }
    1.36                      }
    1.37                      while ((isAlreadyBeingDecrypted) && (curWaitTime < maxWaitTime));
    1.38 @@ -1443,14 +1446,13 @@
    1.39                      // Process mail item
    1.40                      sts1 = PEPMessage.Create(this.internalMailItem, out message);
    1.41  
    1.42 -                    // Block while KeySyncWizard is open and Trustwords haven't been accepted
    1.43 -                    while ((KeySyncWizard.Wizard?.State == KeySyncWizard.WizardState.Step2) &&
    1.44 -                            (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
    1.45 -                            (message.To?.Count == 1) &&
    1.46 -                            (message.From?.EqualsByAddress(message.To[0]) == true))
    1.47 +                    // If Key Import Wizard is open, add mail to list to process later
    1.48 +                    if ((KeySyncWizard.Wizard?.IsVisible == true) &&
    1.49 +                        (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
    1.50 +                        (message.To?.Count == 1) &&
    1.51 +                        (message.From?.EqualsByAddress(message.To[0]) == true))
    1.52                      {
    1.53 -                        Log.Verbose("ProcessAndGetRating: KeySyncWizard in Step 2. Blocking decryption.");
    1.54 -                        Thread.Sleep(100);
    1.55 +                        KeySyncWizard.Wizard?.AddToReceivedSyncMessages(message);
    1.56                      }
    1.57  
    1.58                      // Process
    1.59 @@ -1491,9 +1493,6 @@
    1.60                          }
    1.61                          else
    1.62                          {
    1.63 -                            // Check for sync message
    1.64 -                            this.CheckForSyncMessage((processedRating == pEpRating.pEpRatingUnencrypted) ? message : processedMessage, decryptionFlags);
    1.65 -
    1.66                              // Save processed message data to Outlook
    1.67                              if (processedMessage != null)
    1.68                              {
    1.69 @@ -1839,85 +1838,6 @@
    1.70           *************************************************************/
    1.71  
    1.72          /// <summary>
    1.73 -        /// Checks if the key sync wizard is open or the message is a sync message.
    1.74 -        /// If this is true, the message will get processed further, either raising
    1.75 -        /// the respective event or opening the wizard.
    1.76 -        /// </summary>
    1.77 -        /// <param name="message">The message to check.</param>
    1.78 -        /// <param name="flags">The decrypt flags.</param>
    1.79 -        private void CheckForSyncMessage(PEPMessage message, pEpDecryptFlags flags)
    1.80 -        {
    1.81 -            try
    1.82 -            {
    1.83 -                /* To determine whether the processed message is a sync message:
    1.84 -                 * 1. Is incoming (do not process sent messages)
    1.85 -                 * 2. Has the KeyImport header (in case of pEp sync) and the header is not
    1.86 -                 *    the own fingerprint.
    1.87 -                 * - or -
    1.88 -                 * 3. a. The WizardType is PGP
    1.89 -                 *    b. The message has one To recipient that is also the From recipient
    1.90 -                 *    c. The From recipient is an own identity (seems actually unnecessary)
    1.91 -                 */
    1.92 -                if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
    1.93 -                    (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
    1.94 -                {
    1.95 -                    if ((message.To.Count == 1) &&
    1.96 -                        (message.To[0].EqualsByAddress(message.From)) &&
    1.97 -                        (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
    1.98 -                    {
    1.99 -                        Log.Verbose("CheckForSyncMessage: Sync message found.");
   1.100 -
   1.101 -                        if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
   1.102 -                            (KeySyncWizard.Wizard?.IsVisible == false) &&
   1.103 -                            (message.Rating < pEpRating.pEpRatingTrusted))
   1.104 -                        {
   1.105 -                            Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
   1.106 -
   1.107 -                            // Get own identity
   1.108 -                            PEPIdentity myself = null;
   1.109 -                            try
   1.110 -                            {
   1.111 -                                pEpIdentity _myself = message.To[0].ToCOMType();
   1.112 -                                myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
   1.113 -                            }
   1.114 -                            catch (Exception ex)
   1.115 -                            {
   1.116 -                                myself = null;
   1.117 -                                Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
   1.118 -                            }
   1.119 -
   1.120 -                            // Only open if not sent to myself. Check again if not open
   1.121 -                            if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
   1.122 -                                (KeySyncWizard.Wizard?.IsVisible == false))
   1.123 -                            {
   1.124 -                                // Marshall to main thread and create new wizard
   1.125 -                                KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
   1.126 -                                {
   1.127 -                                    KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
   1.128 -                                    KeySyncWizard.Wizard.Show();
   1.129 -                                    Log.Verbose("CheckForSyncMessage: Wizard opened.");
   1.130 -                                }));
   1.131 -                            }
   1.132 -                        }
   1.133 -                        else
   1.134 -                        {
   1.135 -                            Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
   1.136 -                            CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
   1.137 -                        }
   1.138 -                    }
   1.139 -                    else
   1.140 -                    {
   1.141 -                        Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
   1.142 -                    }
   1.143 -                }
   1.144 -            }
   1.145 -            catch (Exception ex)
   1.146 -            {
   1.147 -                Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
   1.148 -            }
   1.149 -        }
   1.150 -
   1.151 -        /// <summary>
   1.152          /// Releases all resources and disconnects internal events.
   1.153          /// The internal mail item will NOT be released -- this is managed externally.
   1.154          /// </summary>
   1.155 @@ -2168,27 +2088,6 @@
   1.156          }
   1.157  
   1.158          /// <summary>
   1.159 -        /// Class used to store the arguments in the SyncMessageReceived event.
   1.160 -        /// </summary>
   1.161 -        internal class SyncMessageEventArgs : EventArgs
   1.162 -        {
   1.163 -            public PEPMessage Message = null;
   1.164 -            public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
   1.165 -
   1.166 -            /// <summary>
   1.167 -            /// Constructs a new SyncMessageEventArgs with the given arguments.
   1.168 -            /// </summary>
   1.169 -            /// <param name="message">The message that has been received.</param>
   1.170 -            /// <param name="flags">The decryption flags of the received message.</param>
   1.171 -            public SyncMessageEventArgs(PEPMessage message,
   1.172 -                                        pEpDecryptFlags flags)
   1.173 -            {
   1.174 -                this.Message = message;
   1.175 -                this.Flags = flags;
   1.176 -            }
   1.177 -        }
   1.178 -
   1.179 -        /// <summary>
   1.180          /// Class used to store an entry in the encrypted conversation cache.
   1.181          /// This will identify the original parent encrypted mail item.
   1.182          /// </summary>
     2.1 --- a/MsgProcessor.cs	Thu May 10 15:04:25 2018 +0200
     2.2 +++ b/MsgProcessor.cs	Thu May 17 11:21:56 2018 +0200
     2.3 @@ -13,6 +13,12 @@
     2.4      /// </summary>
     2.5      internal class MsgProcessor : IDisposable
     2.6      {
     2.7 +        /// <summary>
     2.8 +        /// Event handler for when a sync message is being detected during decryption.
     2.9 +        /// </summary>
    2.10 +        public delegate void SyncMessageReceivedHandler(object sender, MsgProcessor.SyncMessageEventArgs e);
    2.11 +        public static event SyncMessageReceivedHandler SyncMessageReceived;
    2.12 +
    2.13          public delegate void ProcessingCompletedHandler(object sender, ProcessingCompletedEventArgs e);
    2.14  
    2.15          /// <summary>
    2.16 @@ -114,6 +120,93 @@
    2.17           *************************************************************/
    2.18  
    2.19          /// <summary>
    2.20 +        /// Checks if the key sync wizard is open or the message is a sync message.
    2.21 +        /// If this is true, the message will get processed further, either raising
    2.22 +        /// the respective event or opening the wizard.
    2.23 +        /// </summary>
    2.24 +        /// <param name="message">The message to check.</param>
    2.25 +        /// <param name="flags">The decrypt flags.</param>
    2.26 +        private void CheckForSyncMessage(PEPMessage message, ref pEpDecryptFlags flags)
    2.27 +        {
    2.28 +            try
    2.29 +            {
    2.30 +                /* To determine whether the processed message is a sync message:
    2.31 +                 * 1. Is incoming (do not process sent messages)
    2.32 +                 * 2. Has the KeyImport header (in case of pEp sync) and the header is not
    2.33 +                 *    the own fingerprint.
    2.34 +                 * - or -
    2.35 +                 * 3. a. The WizardType is PGP
    2.36 +                 *    b. The message has one To recipient that is also the From recipient
    2.37 +                 *    c. The From recipient is an own identity (seems actually unnecessary)
    2.38 +                 */
    2.39 +                if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
    2.40 +                    (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
    2.41 +                {
    2.42 +                    if ((message.To.Count == 1) &&
    2.43 +                        (message.To[0].EqualsByAddress(message.From)) &&
    2.44 +                        (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
    2.45 +                    {
    2.46 +                        Log.Verbose("CheckForSyncMessage: Sync message found.");
    2.47 +
    2.48 +                        if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
    2.49 +                            (KeySyncWizard.Wizard?.IsVisible == false) &&
    2.50 +                            (message.Rating < pEpRating.pEpRatingTrusted))
    2.51 +                        {
    2.52 +                            Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
    2.53 +
    2.54 +                            // Get own identity
    2.55 +                            PEPIdentity myself = null;
    2.56 +                            try
    2.57 +                            {
    2.58 +                                pEpIdentity _myself = message.To[0].ToCOMType();
    2.59 +                                myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
    2.60 +                            }
    2.61 +                            catch (Exception ex)
    2.62 +                            {
    2.63 +                                myself = null;
    2.64 +                                Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
    2.65 +                            }
    2.66 +
    2.67 +                            // Only open if not sent to myself. Check again if not open
    2.68 +                            if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
    2.69 +                                (KeySyncWizard.Wizard?.IsVisible == false))
    2.70 +                            {
    2.71 +                                // Marshall to main thread and create new wizard
    2.72 +                                KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
    2.73 +                                {
    2.74 +                                    KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
    2.75 +                                    KeySyncWizard.Wizard.Show();
    2.76 +                                    Log.Verbose("CheckForSyncMessage: Wizard opened.");
    2.77 +                                })); 
    2.78 +                            }
    2.79 +                        }
    2.80 +                        else
    2.81 +                        {
    2.82 +                            Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
    2.83 +                            MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
    2.84 +                        }
    2.85 +
    2.86 +                        // Delete message if necessary
    2.87 +                        if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.pEp) &&
    2.88 +                            (string.IsNullOrEmpty(message?.KeyImport) == false) &&
    2.89 +                            (KeySyncWizard.Wizard?.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))
    2.90 +                        {
    2.91 +                            flags = (flags | pEpDecryptFlags.pEpDecryptFlagConsume);
    2.92 +                        }
    2.93 +                    }
    2.94 +                    else
    2.95 +                    {
    2.96 +                        Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
    2.97 +                    }
    2.98 +                }
    2.99 +            }
   2.100 +            catch (Exception ex)
   2.101 +            {
   2.102 +                Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
   2.103 +            }
   2.104 +        }
   2.105 +
   2.106 +        /// <summary>
   2.107          /// Starts the processing of the mail item which can result in decryption or encryption of the message.
   2.108          /// This will also return the latest message rating.
   2.109          /// </summary>
   2.110 @@ -493,14 +586,6 @@
   2.111  
   2.112              Log.Verbose("ProcessSentMessage: Started");
   2.113  
   2.114 -            // Check if we have an extra key for sync messages and add it
   2.115 -            if (string.IsNullOrEmpty(KeySyncWizard.Wizard?.Partner?.Fingerprint) == false)
   2.116 -            {
   2.117 -                List<string> eKeys = extraKeys?.ToList<string>() ?? new List<string>();
   2.118 -                eKeys.Add(KeySyncWizard.Wizard.Partner.Fingerprint);
   2.119 -                extraKeys = eKeys.ToArray<string>();
   2.120 -            }
   2.121 -
   2.122              // Force the working message to outgoing direction.
   2.123              // This protects mostly for outgoing rating calculation which requires it.
   2.124              // However, if the message is ever incoming direction here, a failure occured elsewhere.
   2.125 @@ -867,6 +952,19 @@
   2.126  
   2.127          /// <summary>
   2.128          /// Decrypts the given pEp message.
   2.129 +        /// This is a wrapper for special cases where we don't need the actual result.
   2.130 +        /// </summary>
   2.131 +        /// <param name="sourceMessage">The message to decrypt.</param>
   2.132 +        /// <returns>True if decryption was considered successful, otherwise false.</returns>
   2.133 +        public bool Decrypt(PEPMessage sourceMessage)
   2.134 +        {
   2.135 +            PEPMessage outMessage;
   2.136 +
   2.137 +            return this.Decrypt(sourceMessage, out outMessage);
   2.138 +        }
   2.139 +
   2.140 +        /// <summary>
   2.141 +        /// Decrypts the given pEp message.
   2.142          /// This is a wrapper for special cases where we don't need to take care of
   2.143          /// rating, key list or flags.
   2.144          /// </summary>
   2.145 @@ -974,7 +1072,10 @@
   2.146              {
   2.147                  destMessage = null;
   2.148                  keyList = new string[0];
   2.149 -            }            
   2.150 +            }
   2.151 +
   2.152 +            // Check for sync message
   2.153 +            this.CheckForSyncMessage((rating == pEpRating.pEpRatingUnencrypted) ? sourceMessage : destMessage, ref flags);
   2.154  
   2.155              Log.SensitiveData("Decrypt: Complete. " + sourceMessage?.Id);
   2.156  
   2.157 @@ -1251,5 +1352,26 @@
   2.158                  this.ProcessedStatus = Globals.ReturnStatus.Success;
   2.159              }
   2.160          }
   2.161 +
   2.162 +        /// <summary>
   2.163 +        /// Class used to store the arguments in the SyncMessageReceived event.
   2.164 +        /// </summary>
   2.165 +        internal class SyncMessageEventArgs : EventArgs
   2.166 +        {
   2.167 +            public PEPMessage Message = null;
   2.168 +            public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
   2.169 +
   2.170 +            /// <summary>
   2.171 +            /// Constructs a new SyncMessageEventArgs with the given arguments.
   2.172 +            /// </summary>
   2.173 +            /// <param name="message">The message that has been received.</param>
   2.174 +            /// <param name="flags">The decryption flags of the received message.</param>
   2.175 +            public SyncMessageEventArgs(PEPMessage message,
   2.176 +                                        pEpDecryptFlags flags)
   2.177 +            {
   2.178 +                this.Message = message;
   2.179 +                this.Flags = flags;
   2.180 +            }
   2.181 +        }
   2.182      }
   2.183  }
     3.1 --- a/PEPSettings.cs	Thu May 10 15:04:25 2018 +0200
     3.2 +++ b/PEPSettings.cs	Thu May 17 11:21:56 2018 +0200
     3.3 @@ -1846,7 +1846,6 @@
     3.4              protected bool          _IsSyncEnabled;
     3.5              protected string        _SentFolderEntryId;
     3.6              protected string        _SmtpAddress;
     3.7 -            protected string        _StoreId;
     3.8              protected string        _Type;
     3.9              protected string        _UserName;
    3.10  
     4.1 --- a/Properties/Resources.Designer.cs	Thu May 10 15:04:25 2018 +0200
     4.2 +++ b/Properties/Resources.Designer.cs	Thu May 17 11:21:56 2018 +0200
     4.3 @@ -701,6 +701,24 @@
     4.4          }
     4.5          
     4.6          /// <summary>
     4.7 +        ///   Looks up a localized string similar to Back.
     4.8 +        /// </summary>
     4.9 +        public static string KeySyncWizard_BackButtonText {
    4.10 +            get {
    4.11 +                return ResourceManager.GetString("KeySyncWizard_BackButtonText", resourceCulture);
    4.12 +            }
    4.13 +        }
    4.14 +        
    4.15 +        /// <summary>
    4.16 +        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
    4.17 +        /// </summary>
    4.18 +        public static string KeySyncWizard_ErrorExplanationText {
    4.19 +            get {
    4.20 +                return ResourceManager.GetString("KeySyncWizard_ErrorExplanationText", resourceCulture);
    4.21 +            }
    4.22 +        }
    4.23 +        
    4.24 +        /// <summary>
    4.25          ///   Looks up a localized string similar to Error.
    4.26          /// </summary>
    4.27          public static string KeySyncWizard_ErrorText {
    4.28 @@ -710,6 +728,15 @@
    4.29          }
    4.30          
    4.31          /// <summary>
    4.32 +        ///   Looks up a localized string similar to Export my private key to the other device.
    4.33 +        /// </summary>
    4.34 +        public static string KeySyncWizard_ExportOwnPrivateKey {
    4.35 +            get {
    4.36 +                return ResourceManager.GetString("KeySyncWizard_ExportOwnPrivateKey", resourceCulture);
    4.37 +            }
    4.38 +        }
    4.39 +        
    4.40 +        /// <summary>
    4.41          ///   Looks up a localized string similar to Finish.
    4.42          /// </summary>
    4.43          public static string KeySyncWizard_Finish {
    4.44 @@ -728,6 +755,89 @@
    4.45          }
    4.46          
    4.47          /// <summary>
    4.48 +        ///   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..
    4.49 +        /// </summary>
    4.50 +        public static string KeySyncWizard_PEPStep1ExplanationText {
    4.51 +            get {
    4.52 +                return ResourceManager.GetString("KeySyncWizard_PEPStep1ExplanationText", resourceCulture);
    4.53 +            }
    4.54 +        }
    4.55 +        
    4.56 +        /// <summary>
    4.57 +        ///   Looks up a localized string similar to If you initiated a key import for the following account, please click Start.
    4.58 +        ///
    4.59 +        ///If this was not you, please cancel..
    4.60 +        /// </summary>
    4.61 +        public static string KeySyncWizard_PEPStep1NonInitiatorExplanationText {
    4.62 +            get {
    4.63 +                return ResourceManager.GetString("KeySyncWizard_PEPStep1NonInitiatorExplanationText", resourceCulture);
    4.64 +            }
    4.65 +        }
    4.66 +        
    4.67 +        /// <summary>
    4.68 +        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
    4.69 +        /// </summary>
    4.70 +        public static string KeySyncWizard_PEPStep2ExplanationText {
    4.71 +            get {
    4.72 +                return ResourceManager.GetString("KeySyncWizard_PEPStep2ExplanationText", resourceCulture);
    4.73 +            }
    4.74 +        }
    4.75 +        
    4.76 +        /// <summary>
    4.77 +        ///   Looks up a localized string similar to Importing key....
    4.78 +        /// </summary>
    4.79 +        public static string KeySyncWizard_PEPStep3ExplanationText {
    4.80 +            get {
    4.81 +                return ResourceManager.GetString("KeySyncWizard_PEPStep3ExplanationText", resourceCulture);
    4.82 +            }
    4.83 +        }
    4.84 +        
    4.85 +        /// <summary>
    4.86 +        ///   Looks up a localized string similar to Key import successful!.
    4.87 +        /// </summary>
    4.88 +        public static string KeySyncWizard_PEPStep4ExplanationText {
    4.89 +            get {
    4.90 +                return ResourceManager.GetString("KeySyncWizard_PEPStep4ExplanationText", resourceCulture);
    4.91 +            }
    4.92 +        }
    4.93 +        
    4.94 +        /// <summary>
    4.95 +        ///   Looks up a localized string similar to Key successfully exported!.
    4.96 +        /// </summary>
    4.97 +        public static string KeySyncWizard_PEPSuccessExport {
    4.98 +            get {
    4.99 +                return ResourceManager.GetString("KeySyncWizard_PEPSuccessExport", resourceCulture);
   4.100 +            }
   4.101 +        }
   4.102 +        
   4.103 +        /// <summary>
   4.104 +        ///   Looks up a localized string similar to Key successfully imported!.
   4.105 +        /// </summary>
   4.106 +        public static string KeySyncWizard_PEPSuccessImport {
   4.107 +            get {
   4.108 +                return ResourceManager.GetString("KeySyncWizard_PEPSuccessImport", resourceCulture);
   4.109 +            }
   4.110 +        }
   4.111 +        
   4.112 +        /// <summary>
   4.113 +        ///   Looks up a localized string similar to The key from your other device will now also be used to decrypt messages..
   4.114 +        /// </summary>
   4.115 +        public static string KeySyncWizard_PEPSuccessOtherKeyUsed {
   4.116 +            get {
   4.117 +                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsed", resourceCulture);
   4.118 +            }
   4.119 +        }
   4.120 +        
   4.121 +        /// <summary>
   4.122 +        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
   4.123 +        /// </summary>
   4.124 +        public static string KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault {
   4.125 +            get {
   4.126 +                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault", resourceCulture);
   4.127 +            }
   4.128 +        }
   4.129 +        
   4.130 +        /// <summary>
   4.131          ///   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:  
   4.132          ///
   4.133          ///1. has your public PGP key attached and
   4.134 @@ -749,98 +859,56 @@
   4.135          }
   4.136          
   4.137          /// <summary>
   4.138 -        ///   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..
   4.139 +        ///   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..
   4.140          /// </summary>
   4.141 -        public static string KeySyncWizard_Step1PEPExplanationText {
   4.142 +        public static string KeySyncWizard_PGPStep1ExplanationText {
   4.143              get {
   4.144 -                return ResourceManager.GetString("KeySyncWizard_Step1PEPExplanationText", resourceCulture);
   4.145 +                return ResourceManager.GetString("KeySyncWizard_PGPStep1ExplanationText", resourceCulture);
   4.146              }
   4.147          }
   4.148          
   4.149          /// <summary>
   4.150 -        ///   Looks up a localized string similar to Please import your public p≡p key on your PGP device and reply with a message that:  
   4.151 -        ///
   4.152 -        ///1. has your public PGP key attached and
   4.153 -        ///2. is encrypted with the p≡p key you just imported.
   4.154 +        ///   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..
   4.155          /// </summary>
   4.156 -        public static string KeySyncWizard_Step1PGPExplanationText {
   4.157 +        public static string KeySyncWizard_PGPStep2ExplanationText {
   4.158              get {
   4.159 -                return ResourceManager.GetString("KeySyncWizard_Step1PGPExplanationText", resourceCulture);
   4.160 +                return ResourceManager.GetString("KeySyncWizard_PGPStep2ExplanationText", resourceCulture);
   4.161              }
   4.162          }
   4.163          
   4.164          /// <summary>
   4.165 -        ///   Looks up a localized string similar to A message with your public key has been sent to yourself..
   4.166 +        ///   Looks up a localized string similar to Encrypt the answer message with the public p≡p key you just imported and send it..
   4.167          /// </summary>
   4.168 -        public static string KeySyncWizard_Step1PGPSubtitleText {
   4.169 +        public static string KeySyncWizard_PGPStep3ExplanationText {
   4.170              get {
   4.171 -                return ResourceManager.GetString("KeySyncWizard_Step1PGPSubtitleText", resourceCulture);
   4.172 -            }
   4.173 -        }
   4.174 -        
   4.175 -        /// <summary>
   4.176 -        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
   4.177 -        /// </summary>
   4.178 -        public static string KeySyncWizard_Step2PEPExplanationText {
   4.179 -            get {
   4.180 -                return ResourceManager.GetString("KeySyncWizard_Step2PEPExplanationText", resourceCulture);
   4.181 +                return ResourceManager.GetString("KeySyncWizard_PGPStep3ExplanationText", resourceCulture);
   4.182              }
   4.183          }
   4.184          
   4.185          /// <summary>
   4.186          ///   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..
   4.187          /// </summary>
   4.188 -        public static string KeySyncWizard_Step2PGPExplanationText {
   4.189 +        public static string KeySyncWizard_PGPStep5ExplanationText {
   4.190              get {
   4.191 -                return ResourceManager.GetString("KeySyncWizard_Step2PGPExplanationText", resourceCulture);
   4.192 +                return ResourceManager.GetString("KeySyncWizard_PGPStep5ExplanationText", resourceCulture);
   4.193              }
   4.194          }
   4.195          
   4.196          /// <summary>
   4.197 -        ///   Looks up a localized string similar to Importing key....
   4.198 +        ///   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..
   4.199          /// </summary>
   4.200 -        public static string KeySyncWizard_Step3PEPExplanationText {
   4.201 +        public static string KeySyncWizard_PGPStep6ExplanationText {
   4.202              get {
   4.203 -                return ResourceManager.GetString("KeySyncWizard_Step3PEPExplanationText", resourceCulture);
   4.204 +                return ResourceManager.GetString("KeySyncWizard_PGPStep6ExplanationText", resourceCulture);
   4.205              }
   4.206          }
   4.207          
   4.208          /// <summary>
   4.209 -        ///   Looks up a localized string similar to Please send now another reply message that:  
   4.210 -        ///
   4.211 -        ///1. has your private PGP key attached and
   4.212 -        ///2. is encrypted with the p≡p key you just imported.
   4.213 +        ///   Looks up a localized string similar to Encrypt the answer message again with the public p≡p key and send it..
   4.214          /// </summary>
   4.215 -        public static string KeySyncWizard_Step3PGPExplanationText {
   4.216 +        public static string KeySyncWizard_PGPStep7ExplanationText {
   4.217              get {
   4.218 -                return ResourceManager.GetString("KeySyncWizard_Step3PGPExplanationText", resourceCulture);
   4.219 -            }
   4.220 -        }
   4.221 -        
   4.222 -        /// <summary>
   4.223 -        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
   4.224 -        /// </summary>
   4.225 -        public static string KeySyncWizard_Step4ErrorExplanationText {
   4.226 -            get {
   4.227 -                return ResourceManager.GetString("KeySyncWizard_Step4ErrorExplanationText", resourceCulture);
   4.228 -            }
   4.229 -        }
   4.230 -        
   4.231 -        /// <summary>
   4.232 -        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
   4.233 -        /// </summary>
   4.234 -        public static string KeySyncWizard_Step4PEPSuccessInitiatorExplanationText {
   4.235 -            get {
   4.236 -                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessInitiatorExplanationText", resourceCulture);
   4.237 -            }
   4.238 -        }
   4.239 -        
   4.240 -        /// <summary>
   4.241 -        ///   Looks up a localized string similar to The key from the other device can now be used to decrypt messages..
   4.242 -        /// </summary>
   4.243 -        public static string KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText {
   4.244 -            get {
   4.245 -                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText", resourceCulture);
   4.246 +                return ResourceManager.GetString("KeySyncWizard_PGPStep7ExplanationText", resourceCulture);
   4.247              }
   4.248          }
   4.249          
   4.250 @@ -849,9 +917,27 @@
   4.251          ///
   4.252          ///Your private PGP key has been successfully imported and will now be used as default p≡p key..
   4.253          /// </summary>
   4.254 -        public static string KeySyncWizard_Step4SuccessExplanationText {
   4.255 +        public static string KeySyncWizard_PGPSuccessExplanationText {
   4.256              get {
   4.257 -                return ResourceManager.GetString("KeySyncWizard_Step4SuccessExplanationText", resourceCulture);
   4.258 +                return ResourceManager.GetString("KeySyncWizard_PGPSuccessExplanationText", resourceCulture);
   4.259 +            }
   4.260 +        }
   4.261 +        
   4.262 +        /// <summary>
   4.263 +        ///   Looks up a localized string similar to Use the imported key as default key.
   4.264 +        /// </summary>
   4.265 +        public static string KeySyncWizard_SetImportedKeyAsDefault {
   4.266 +            get {
   4.267 +                return ResourceManager.GetString("KeySyncWizard_SetImportedKeyAsDefault", resourceCulture);
   4.268 +            }
   4.269 +        }
   4.270 +        
   4.271 +        /// <summary>
   4.272 +        ///   Looks up a localized string similar to Start.
   4.273 +        /// </summary>
   4.274 +        public static string KeySyncWizard_Start {
   4.275 +            get {
   4.276 +                return ResourceManager.GetString("KeySyncWizard_Start", resourceCulture);
   4.277              }
   4.278          }
   4.279          
     5.1 --- a/Properties/Resources.de.resx	Thu May 10 15:04:25 2018 +0200
     5.2 +++ b/Properties/Resources.de.resx	Thu May 17 11:21:56 2018 +0200
     5.3 @@ -651,7 +651,7 @@
     5.4      <value>Die Mailgröße überschreitet die zulässige Größenbeschränkung für die Verschlüsselung.</value>
     5.5    </data>
     5.6    <data name="Handshake_WrongFingerprint" xml:space="preserve">
     5.7 -    <value>Falscher Fingerprint</value>
     5.8 +    <value>Falscher Fingerabdruck</value>
     5.9    </data>
    5.10    <data name="Handshake_TrustwordsExpanderTooltipFull" xml:space="preserve">
    5.11      <value>Vollversion der Trustwords anzeigen</value>
    5.12 @@ -722,22 +722,16 @@
    5.13    <data name="KeySyncWizard_Finish" xml:space="preserve">
    5.14      <value>Fertig stellen</value>
    5.15    </data>
    5.16 -  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
    5.17 -    <value>Bitte importieren Sie Ihren öffentlichen p≡p-Schlüssel auf Ihrem PGP-Gerät und senden Sie eine Antwortnachricht:  
    5.18 -
    5.19 -1. an die Sie Ihren öffentlichen PGP-Schlüssel anhängen und
    5.20 -2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln</value>
    5.21 +  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
    5.22 +    <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>
    5.23    </data>
    5.24 -  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
    5.25 -    <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>
    5.26 +  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
    5.27 +    <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>
    5.28    </data>
    5.29 -  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
    5.30 -    <value>Senden Sie nun bitte eine weitere Antwortnachricht:  
    5.31 -
    5.32 -1. an die Sie Ihren privaten PGP-Schlüssel anhängen und 
    5.33 -2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln </value>
    5.34 +  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
    5.35 +    <value>Verschlüsseln Sie die Antwortnachricht mit dem öffentlichen p≡p-Schlüssel, den Sie gerade importiert haben und versenden Sie sie.</value>
    5.36    </data>
    5.37 -  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
    5.38 +  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
    5.39      <value>Schlüsselimport erfolgreich
    5.40  
    5.41  Ihr privater PGP-Schlüssel wurde erfolgreich importiert und wird nun standardmäßig auch als p≡p-Schlüssel verwendet.</value>
    5.42 @@ -745,23 +739,23 @@
    5.43    <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
    5.44      <value>Schlüsselimport</value>
    5.45    </data>
    5.46 -  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
    5.47 +  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
    5.48      <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>
    5.49    </data>
    5.50 -  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
    5.51 +  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
    5.52      <value>Bitte vergleichen Sie die folgenden Trustwords mit denjenigen auf Ihrem anderen Gerät und bestätigen Sie sie, wenn sie übereinstimmen.</value>
    5.53    </data>
    5.54    <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
    5.55      <value>Es wird auf eine Antwort vom anderen Gerät gewartet...</value>
    5.56    </data>
    5.57 -  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
    5.58 -    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
    5.59 +  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
    5.60 +    <value>Schlüsselimport erfolgreich!</value>
    5.61    </data>
    5.62 -  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
    5.63 +  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
    5.64      <value>Es ist ein Fehler aufgetreten. Ihr Schlüssel konnte nicht importiert werden. Bitte versuchen Sie es erneut.</value>
    5.65    </data>
    5.66 -  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
    5.67 -    <value>Der Schlüssel des anderen Geräts kann nun zum Entschlüsseln von Nachrichten verwendet werden.</value>
    5.68 +  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
    5.69 +    <value>Schlüsselexport erfolgreich!</value>
    5.70    </data>
    5.71    <data name="KeySyncWizard_SuccessText" xml:space="preserve">
    5.72      <value>Schlüsselimport erfolgreich!</value>
    5.73 @@ -769,7 +763,7 @@
    5.74    <data name="KeySyncWizard_ErrorText" xml:space="preserve">
    5.75      <value>Fehler</value>
    5.76    </data>
    5.77 -  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
    5.78 +  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
    5.79      <value>Schlüssel wird importiert...</value>
    5.80    </data>
    5.81    <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
    5.82 @@ -781,9 +775,6 @@
    5.83    <data name="StoreContextMenu_KeyImportText" xml:space="preserve">
    5.84      <value>Schlüsselimport</value>
    5.85    </data>
    5.86 -  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
    5.87 -    <value>Eine Nachricht mit Ihrem öffentlichen Schlüssel wurde an Sie selbst versendet.</value>
    5.88 -  </data>
    5.89    <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
    5.90      <value>Um mit dem Schlüsselimport fortzufahren, importieren Sie bitte den angehängten öffentlichen p≡p-Schlüssel und senden Sie eine Antwortnachricht:  
    5.91  
    5.92 @@ -793,4 +784,39 @@
    5.93    <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
    5.94      <value>p≡p-Schlüsselimport</value>
    5.95    </data>
    5.96 +  <data name="KeySyncWizard_Start" xml:space="preserve">
    5.97 +    <value>Start</value>
    5.98 +  </data>
    5.99 +  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
   5.100 +    <value>Wenn Sie einen Schlüsselimport von einem anderen Gerät gestartet haben, klicken Sie bitte auf Start.
   5.101 +
   5.102 +Andernfalls klicken Sie bitte auf Abbrechen.</value>
   5.103 +  </data>
   5.104 +  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
   5.105 +    <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>
   5.106 +  </data>
   5.107 +  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
   5.108 +    <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>
   5.109 +  </data>
   5.110 +  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
   5.111 +    <value>Verschlüsseln Sie die Antwortnachricht nun wieder mit dem öffentlichen p≡p-Schlüssel und versenden Sie sie.</value>
   5.112 +  </data>
   5.113 +  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
   5.114 +    <value>Zurück</value>
   5.115 +  </data>
   5.116 +  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
   5.117 +    <value>Schlüsselimport erfolgreich!</value>
   5.118 +  </data>
   5.119 +  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
   5.120 +    <value>Meinen privaten Schlüssel auf das andere Gerät exportieren</value>
   5.121 +  </data>
   5.122 +  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
   5.123 +    <value>Den importierten Schlüssel standardmäßig verwenden</value>
   5.124 +  </data>
   5.125 +  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
   5.126 +    <value>Der Schlüssel von Ihrem anderen Gerät kann nun ebenfalls zum Entschlüsseln verwendet werden.</value>
   5.127 +  </data>
   5.128 +  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
   5.129 +    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
   5.130 +  </data>
   5.131  </root>
   5.132 \ No newline at end of file
     6.1 --- a/Properties/Resources.resx	Thu May 10 15:04:25 2018 +0200
     6.2 +++ b/Properties/Resources.resx	Thu May 17 11:21:56 2018 +0200
     6.3 @@ -804,22 +804,16 @@
     6.4    <data name="KeySyncWizard_Finish" xml:space="preserve">
     6.5      <value>Finish</value>
     6.6    </data>
     6.7 -  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
     6.8 -    <value>Please import your public p≡p key on your PGP device and reply with a message that:  
     6.9 -
    6.10 -1. has your public PGP key attached and
    6.11 -2. is encrypted with the p≡p key you just imported</value>
    6.12 +  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
    6.13 +    <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>
    6.14    </data>
    6.15 -  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
    6.16 -    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
    6.17 +  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
    6.18 +    <value>In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key.</value>
    6.19    </data>
    6.20 -  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
    6.21 -    <value>Please send now another reply message that:  
    6.22 -
    6.23 -1. has your private PGP key attached and
    6.24 -2. is encrypted with the p≡p key you just imported</value>
    6.25 +  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
    6.26 +    <value>Encrypt the answer message with the public p≡p key you just imported and send it.</value>
    6.27    </data>
    6.28 -  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
    6.29 +  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
    6.30      <value>Key successfully imported
    6.31  
    6.32  Your private PGP key has been successfully imported and will now be used as default p≡p key.</value>
    6.33 @@ -827,10 +821,10 @@
    6.34    <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
    6.35      <value>Key Import</value>
    6.36    </data>
    6.37 -  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
    6.38 +  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
    6.39      <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>
    6.40    </data>
    6.41 -  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
    6.42 +  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
    6.43      <value>Please compare the following Trustwords with the ones on your other device and confirm if they match.</value>
    6.44    </data>
    6.45    <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
    6.46 @@ -839,14 +833,14 @@
    6.47    <data name="KeySyncWizard_Next" xml:space="preserve">
    6.48      <value>Next</value>
    6.49    </data>
    6.50 -  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
    6.51 -    <value>The key from your other device will now be used as your default private key.</value>
    6.52 +  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
    6.53 +    <value>Key successfully imported!</value>
    6.54    </data>
    6.55 -  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
    6.56 +  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
    6.57      <value>An error occured. Your key could not be imported correctly. Please try again.</value>
    6.58    </data>
    6.59 -  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
    6.60 -    <value>The key from the other device can now be used to decrypt messages.</value>
    6.61 +  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
    6.62 +    <value>Key successfully exported!</value>
    6.63    </data>
    6.64    <data name="KeySyncWizard_SuccessText" xml:space="preserve">
    6.65      <value>Key import successful!</value>
    6.66 @@ -854,7 +848,7 @@
    6.67    <data name="KeySyncWizard_ErrorText" xml:space="preserve">
    6.68      <value>Error</value>
    6.69    </data>
    6.70 -  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
    6.71 +  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
    6.72      <value>Importing key...</value>
    6.73    </data>
    6.74    <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
    6.75 @@ -869,9 +863,6 @@
    6.76    <data name="ImageLogoIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
    6.77      <value>..\resources\imagelogoicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
    6.78    </data>
    6.79 -  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
    6.80 -    <value>A message with your public key has been sent to yourself.</value>
    6.81 -  </data>
    6.82    <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
    6.83      <value>To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:  
    6.84  
    6.85 @@ -881,4 +872,39 @@
    6.86    <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
    6.87      <value>p≡p Key Import</value>
    6.88    </data>
    6.89 +  <data name="KeySyncWizard_Start" xml:space="preserve">
    6.90 +    <value>Start</value>
    6.91 +  </data>
    6.92 +  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
    6.93 +    <value>If you initiated a key import for the following account, please click Start.
    6.94 +
    6.95 +If this was not you, please cancel.</value>
    6.96 +  </data>
    6.97 +  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
    6.98 +    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
    6.99 +  </data>
   6.100 +  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
   6.101 +    <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>
   6.102 +  </data>
   6.103 +  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
   6.104 +    <value>Encrypt the answer message again with the public p≡p key and send it.</value>
   6.105 +  </data>
   6.106 +  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
   6.107 +    <value>Back</value>
   6.108 +  </data>
   6.109 +  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
   6.110 +    <value>Key import successful!</value>
   6.111 +  </data>
   6.112 +  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
   6.113 +    <value>Export my private key to the other device</value>
   6.114 +  </data>
   6.115 +  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
   6.116 +    <value>Use the imported key as default key</value>
   6.117 +  </data>
   6.118 +  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
   6.119 +    <value>The key from your other device will now be used as your default private key.</value>
   6.120 +  </data>
   6.121 +  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
   6.122 +    <value>The key from your other device will now also be used to decrypt messages.</value>
   6.123 +  </data>
   6.124  </root>
   6.125 \ No newline at end of file
     7.1 --- a/UI/HandshakeDialog.xaml.cs	Thu May 10 15:04:25 2018 +0200
     7.2 +++ b/UI/HandshakeDialog.xaml.cs	Thu May 17 11:21:56 2018 +0200
     7.3 @@ -4,7 +4,6 @@
     7.4  using System.Collections.ObjectModel;
     7.5  using System.ComponentModel;
     7.6  using System.Linq;
     7.7 -using System.Runtime.InteropServices;
     7.8  using System.Windows;
     7.9  using System.Windows.Controls;
    7.10  using System.Windows.Input;
     8.1 --- a/UI/HandshakeItemsControl.xaml	Thu May 10 15:04:25 2018 +0200
     8.2 +++ b/UI/HandshakeItemsControl.xaml	Thu May 17 11:21:56 2018 +0200
     8.3 @@ -201,7 +201,8 @@
     8.4                                    SelectedValuePath="Key"
     8.5                                    SelectedValue="{Binding Path=TrustwordsCulture, Mode=TwoWay}"
     8.6                                    IsEnabled="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Trustwords}"
     8.7 -                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}" />
     8.8 +                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}"
     8.9 +                                  Visibility="{Binding Path=Mode, Converter={StaticResource IsNotSyncModeToVisibility}}" />
    8.10                      </StackPanel>
    8.11  
    8.12                      <!-- Trustwords -->
     9.1 --- a/UI/HandshakeItemsControl.xaml.cs	Thu May 10 15:04:25 2018 +0200
     9.2 +++ b/UI/HandshakeItemsControl.xaml.cs	Thu May 17 11:21:56 2018 +0200
     9.3 @@ -127,5 +127,15 @@
     9.4                  handshakeItem.AreTrustwordsExpanded = ((sender as Expander)?.IsExpanded == true);
     9.5              }
     9.6          }
     9.7 +
     9.8 +        /// <summary>
     9.9 +        /// Raises the property changed event, if possible, with the given arguments.
    9.10 +        /// </summary>
    9.11 +        /// <param name="propertyName">The name of the property that changed.</param>
    9.12 +        private void RaisePropertyChangedEvent(string propertyName)
    9.13 +        {
    9.14 +            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    9.15 +            return;
    9.16 +        }
    9.17      }
    9.18  }
    10.1 --- a/UI/KeySyncWizard.xaml	Thu May 10 15:04:25 2018 +0200
    10.2 +++ b/UI/KeySyncWizard.xaml	Thu May 17 11:21:56 2018 +0200
    10.3 @@ -23,94 +23,92 @@
    10.4          <ResourceDictionary>
    10.5              <!-- Converters -->
    10.6              <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
    10.7 -            <local:InvertBoolConverter x:Key="InvertBool" />
    10.8 -            <local:ValueConverterGroup x:Key="IsWizardStateToVisibility">
    10.9 -                <local:IsWizardStateConverter />
   10.10 -                <BooleanToVisibilityConverter />
   10.11 -            </local:ValueConverterGroup>
   10.12 -            <local:ValueConverterGroup x:Key="IsNotWizardStateToVisibility">
   10.13 -                <local:IsWizardStateConverter />
   10.14 +            <local:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibility" />
   10.15 +            <local:ValueConverterGroup x:Key="IsStringNotNullOrEmptyToVisibility">
   10.16 +                <local:IsStringEmptyConverter />
   10.17                  <local:InvertBoolConverter />
   10.18                  <BooleanToVisibilityConverter />
   10.19              </local:ValueConverterGroup>
   10.20 -            <local:ValueConverterGroup x:Key="IsNotWizardStateToBool">
   10.21 -                <local:IsWizardStateConverter />
   10.22 -                <local:InvertBoolConverter />
   10.23 -            </local:ValueConverterGroup>
   10.24 +            <local:IsWizardTypeConverter x:Key="IsWizardType" />
   10.25 +
   10.26 +            <!--Dictionary-->
   10.27 +            <ResourceDictionary.MergedDictionaries>
   10.28 +                <ResourceDictionary Source="pack://application:,,,/pEp;component/Resources/Dictionary.xaml" />
   10.29 +            </ResourceDictionary.MergedDictionaries>
   10.30          </ResourceDictionary>
   10.31      </Window.Resources>
   10.32  
   10.33 -    <!--The window content-->
   10.34 -    <StackPanel Width="470">
   10.35 -
   10.36 -        <!--Title section-->
   10.37 -        <Grid Background="White"
   10.38 -              Margin="0">
   10.39 -            <Grid.ColumnDefinitions>
   10.40 -                <ColumnDefinition Width="*" />
   10.41 -                <ColumnDefinition Width="Auto" />
   10.42 -            </Grid.ColumnDefinitions>
   10.43 -            <StackPanel Grid.Column="0">
   10.44 -                <TextBlock Margin="20,10,10,10"
   10.45 -                       Text="{Binding Path=TitleText}"
   10.46 -                       FontWeight="Bold" 
   10.47 -                       VerticalAlignment="Center"/>
   10.48 -                <TextBlock Margin="20,10,10,10"
   10.49 -                           Text="{Binding Path=SubtitleText}"
   10.50 -                           TextWrapping="Wrap"
   10.51 -                           VerticalAlignment="Center" />
   10.52 -            </StackPanel>
   10.53 -            <Image Grid.Column="1"
   10.54 -                   Stretch="Uniform"
   10.55 -                   Height="40"
   10.56 -                   VerticalAlignment="Center"
   10.57 -                   HorizontalAlignment="Right"
   10.58 -                   Margin="20,10"
   10.59 -                   Source="pack://application:,,,/pEp;component/Resources/ImageLogoMedium.png">
   10.60 -            </Image>
   10.61 -        </Grid>
   10.62 -
   10.63 -        <Separator Margin="0,0,0,20"
   10.64 -                   Background="LightGray" />
   10.65 +    <StackPanel Margin="10"
   10.66 +                Width="470">
   10.67  
   10.68          <!--Information section-->
   10.69 -        <TextBlock Text="{Binding Path=ExplanationText}"
   10.70 +        <TextBlock Text="{Binding Path=CurrentState.TitleText}"
   10.71                     TextWrapping="Wrap"
   10.72 -                   Margin="20,10" />
   10.73 +                   Margin="5,5,5,15" />
   10.74 +
   10.75 +        <!--User name section-->
   10.76 +        <TextBlock Text="{Binding Path=CurrentState.UserText}"
   10.77 +                   Padding="10"
   10.78 +                   MinHeight="80"
   10.79 +                   Background="White"
   10.80 +                   FontWeight="DemiBold"
   10.81 +                   Visibility="{Binding Path=CurrentState.IsUserTextVisible, Converter={StaticResource BoolToVisibility}}" />
   10.82  
   10.83          <!--Identities section-->
   10.84 -        <local:HandshakeItemsControl Margin="10,0"
   10.85 -                                     ItemsSource="{Binding Path=Items}"
   10.86 -                                     Visibility="{Binding Path=State, Converter={StaticResource IsWizardStateToVisibility}, ConverterParameter=Step2}" />
   10.87 +        <StackPanel Visibility="{Binding Path=CurrentState.AreTrustwordsVisible, Converter={StaticResource BoolToVisibility}}">
   10.88 +            <local:HandshakeItemsControl ItemsSource="{Binding Path=Items}" />
   10.89 +            <StackPanel Orientation="Horizontal"
   10.90 +                        Margin="5,10,5,0"
   10.91 +                        Visibility="{Binding Path=IsInitiator, Converter={StaticResource BoolToVisibility}}">
   10.92 +                <CheckBox VerticalAlignment="Center"
   10.93 +                          IsChecked="{Binding Path=SetImportedKeyAsDefault}" />
   10.94 +                <Label Content="{x:Static p:Resources.KeySyncWizard_SetImportedKeyAsDefault}"
   10.95 +                       MouseUp="LabelSetImportedKeyAsDefault_MouseUp"/>
   10.96 +            </StackPanel>
   10.97 +            <StackPanel Orientation="Horizontal"
   10.98 +                        Margin="5,0,5,5">
   10.99 +                <StackPanel.Visibility>
  10.100 +                    <MultiBinding Converter="{StaticResource MultiBooleanToVisibility}">
  10.101 +                        <Binding Path="IsInitiator" />
  10.102 +                        <Binding Path="Type" Converter="{StaticResource IsWizardType}" ConverterParameter="pEp" />
  10.103 +                    </MultiBinding>
  10.104 +                </StackPanel.Visibility>
  10.105 +                <CheckBox VerticalAlignment="Center"
  10.106 +                          IsChecked="{Binding Path=ExportPrivateKey}" />
  10.107 +                <Label Content="{x:Static p:Resources.KeySyncWizard_ExportOwnPrivateKey}" 
  10.108 +                       MouseUp="LabelExportPrivateKey_MouseUp"/>
  10.109 +            </StackPanel>
  10.110 +        </StackPanel>
  10.111  
  10.112 -        <Separator Margin="10,20,10,0" 
  10.113 -                   Background="LightGray"/>
  10.114 +        <!--Subtitle section-->
  10.115 +        <TextBlock Text="{Binding Path=CurrentState.SubtitleText}"
  10.116 +                   TextWrapping="Wrap"
  10.117 +                   Margin="5,15"
  10.118 +                   Visibility="{Binding Path=CurrentState.SubtitleText, Converter={StaticResource IsStringNotNullOrEmptyToVisibility}}" />
  10.119  
  10.120          <!--Buttons section-->
  10.121 -        <Grid>
  10.122 -            <Grid.ColumnDefinitions>
  10.123 -                <ColumnDefinition Width="*" />
  10.124 -                <ColumnDefinition Width="Auto" />
  10.125 -            </Grid.ColumnDefinitions>
  10.126 -            <StackPanel Grid.Column="1"
  10.127 -                        Margin="10"
  10.128 -                        Orientation="Horizontal">
  10.129 -                <Button x:Name="OKNextButton"
  10.130 -                        Margin="5"
  10.131 -                        Padding="5,2"
  10.132 -                        MinWidth="70"
  10.133 -                        IsEnabled="{Binding Path=State, Converter={StaticResource IsNotWizardStateToBool}, ConverterParameter=Step1|Step3}"
  10.134 -                        Click="OKNextButton_Click"
  10.135 -                        Content="{Binding Path=NextButtonText}" />
  10.136 -                <Button x:Name="CancelButton"
  10.137 -                        Margin="5"
  10.138 -                        Padding="5,2"
  10.139 -                        MinWidth="70"
  10.140 -                        Click="CancelButton_Click"
  10.141 -                        Visibility="{Binding Path=State, Converter={StaticResource IsNotWizardStateToVisibility}, ConverterParameter=Step4}"
  10.142 -                        Content="{x:Static p:Resources.Options_CancelText}" />
  10.143 -            </StackPanel>
  10.144 -        </Grid>
  10.145 +        <StackPanel Margin="0,10"
  10.146 +                    Orientation="Horizontal"
  10.147 +                    HorizontalAlignment="Right">
  10.148 +            <Button x:Name="BackButton"
  10.149 +                    Style="{StaticResource StyleCancelButton}"
  10.150 +                    Margin="0,5,5,5"
  10.151 +                    Click="BackButton_Click"
  10.152 +                    Content="{x:Static p:Resources.KeySyncWizard_BackButtonText}"
  10.153 +                    Visibility="{Binding Path=CurrentState.IsBackButtonVisible, Converter={StaticResource BoolToVisibility}}" />
  10.154 +            <Button x:Name="AcceptButton"
  10.155 +                    Style="{StaticResource StyleConfirmButton}"
  10.156 +                    Margin="5"
  10.157 +                    Click="AcceptButton_Click"
  10.158 +                    Content="{Binding Path=CurrentState.AcceptButtonText}"
  10.159 +                    Visibility="{Binding Path=CurrentState.IsAcceptButtonVisible, Converter={StaticResource BoolToVisibility}}" />
  10.160 +            <Button x:Name="CancelButton"
  10.161 +                    Margin="5,5,0,5"
  10.162 +                    Style="{StaticResource StyleWrongButton}"
  10.163 +                    Click="CancelButton_Click"
  10.164 +                    Content="{Binding Path=CurrentState.CancelButtonText}"
  10.165 +                    Visibility="{Binding Path=CurrentState.IsCancelButtonVisible, Converter={StaticResource BoolToVisibility}}" />
  10.166 +        </StackPanel>
  10.167      </StackPanel>
  10.168  </Window>
  10.169  
    11.1 --- a/UI/KeySyncWizard.xaml.cs	Thu May 10 15:04:25 2018 +0200
    11.2 +++ b/UI/KeySyncWizard.xaml.cs	Thu May 17 11:21:56 2018 +0200
    11.3 @@ -3,7 +3,10 @@
    11.4  using System.Collections.Generic;
    11.5  using System.Collections.ObjectModel;
    11.6  using System.ComponentModel;
    11.7 +using System.Threading.Tasks;
    11.8  using System.Windows;
    11.9 +using System.Windows.Input;
   11.10 +using System.Windows.Threading;
   11.11  using Outlook = Microsoft.Office.Interop.Outlook;
   11.12  
   11.13  namespace pEp.UI
   11.14 @@ -16,6 +19,24 @@
   11.15                                             Interfaces.IReset
   11.16      {
   11.17          /// <summary>
   11.18 +        /// Defines the step this wizard is currently in.
   11.19 +        /// </summary>
   11.20 +        public enum Steps
   11.21 +        {
   11.22 +            Undefined,
   11.23 +            Success,
   11.24 +            Error,
   11.25 +            Step1,
   11.26 +            Step2,
   11.27 +            Step3,
   11.28 +            Step4,
   11.29 +            Step5,
   11.30 +            Step6,
   11.31 +            Step7,
   11.32 +            Step8
   11.33 +        }
   11.34 +
   11.35 +        /// <summary>
   11.36          /// The message types for sync messages.
   11.37          /// </summary>
   11.38          public enum MessageTypes
   11.39 @@ -37,66 +58,33 @@
   11.40          }
   11.41  
   11.42          /// <summary>
   11.43 -        /// Defines the state (step) this wizard is currently in.
   11.44 -        /// </summary>
   11.45 -        public enum WizardState
   11.46 -        {
   11.47 -            /// <summary>
   11.48 -            /// Undefined state. Should never occur.
   11.49 -            /// </summary>
   11.50 -            Undefined,
   11.51 -
   11.52 -            /// <summary>
   11.53 -            /// First state on the side of the device that initiated
   11.54 -            /// the process. Will send a first message and wait for
   11.55 -            /// an answer message from the other device.
   11.56 -            /// </summary>
   11.57 -            Step1,
   11.58 -
   11.59 -            /// <summary>
   11.60 -            /// Showing the Trustwords dialog, waiting for user input.
   11.61 -            /// </summary>
   11.62 -            Step2,
   11.63 -
   11.64 -            /// <summary>
   11.65 -            /// Trustwords are accepted, the private key is being sent.
   11.66 -            /// Waiting for key from other device.
   11.67 -            /// </summary>
   11.68 -            Step3,
   11.69 -
   11.70 -            /// <summary>
   11.71 -            /// Process has finished (successfully or not).
   11.72 -            /// </summary>
   11.73 -            Step4
   11.74 -        }
   11.75 -
   11.76 -        /// <summary>
   11.77          /// Event raised when a property is changed on a component.
   11.78          /// </summary>
   11.79          public event PropertyChangedEventHandler PropertyChanged;
   11.80  
   11.81 -        private string                                  _ExplanationText;
   11.82 +        private WizardState                             _CurrentState;
   11.83 +        private bool                                    _ExportPrivateKey;
   11.84 +        private bool                                    _IsInitiator;
   11.85          private ObservableCollection<HandshakeItem>     _Items;
   11.86          private PEPIdentity                             _Myself;
   11.87 -        private string                                  _NextButtonText;
   11.88          private PEPIdentity                             _Partner;
   11.89 -        private WizardState                             _State;
   11.90 -        private string                                  _SubtitleText;
   11.91 -        private bool                                    _Success;
   11.92 -        private string                                  _TitleText;
   11.93 +        private Steps                                   _Step;
   11.94 +        private bool                                    _SetImportedKeyAsDefault;
   11.95          private WizardType                              _Type;
   11.96  
   11.97 +        private bool                                    privateKeyImported = false;
   11.98 +        private List<MessageTypes>                      sentMessages                = new List<MessageTypes>();
   11.99 +        private List<PEPMessage>                        receivedSyncMessages        = new List<PEPMessage>();
  11.100 +        private List<WizardState>                       states = new List<WizardState>();
  11.101 +        private object                                  mutexReceivedSyncMessages   = new object();
  11.102 +
  11.103          public static KeySyncWizard                     Wizard = null;
  11.104  
  11.105 -        private bool                                    isInitiator         = false;
  11.106 -        private List<MessageTypes>                      sentMessages = new List<MessageTypes>();
  11.107 -
  11.108          /// <summary>
  11.109          /// Default constructor
  11.110          /// </summary>
  11.111          public KeySyncWizard()
  11.112 -        {
  11.113 -        }
  11.114 +        { }
  11.115  
  11.116          /// <summary>
  11.117          /// Constructor to create a new key sync wizard.
  11.118 @@ -115,58 +103,26 @@
  11.119                  KeySyncWizard.Wizard.Close();
  11.120              }
  11.121  
  11.122 +            // Reset all values
  11.123 +            this.Reset();
  11.124 +
  11.125              // Initialize the window
  11.126              InitializeComponent();
  11.127  
  11.128              // Set current wizard
  11.129              KeySyncWizard.Wizard = this;
  11.130  
  11.131 -            // Reset all values
  11.132 -            this.Reset();
  11.133 -
  11.134              // Initialize the wizard
  11.135 -            this.InitializeWizard(type, myself, partnerFpr);
  11.136 -
  11.137 -            // Set if wizard is the one that has started the sync process
  11.138 -            this.isInitiator = isInitiator;
  11.139 +            this.InitializeWizard(isInitiator, type, myself, partnerFpr);
  11.140  
  11.141              // Attach event handler for new sync messages
  11.142 -            CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
  11.143 +            MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
  11.144  
  11.145 -            // Either send initial or answer message
  11.146 -            if (isInitiator)
  11.147 +            // Send initial message if necessary
  11.148 +            if (this.IsInitiator)
  11.149              {
  11.150 -                // Send initial message
  11.151                  this.SendSyncMessage(MessageTypes.InitialMessage);
  11.152              }
  11.153 -            else
  11.154 -            {
  11.155 -                try
  11.156 -                {
  11.157 -                    // Update own identity
  11.158 -                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
  11.159 -
  11.160 -                    // Create handshake item
  11.161 -                    if (this.CreateHandshakeItem())
  11.162 -                    {
  11.163 -                        // Send answer message with pub key
  11.164 -                        this.SendSyncMessage(MessageTypes.PublicKeyMessage);
  11.165 -
  11.166 -                        // Go to next step
  11.167 -                        this.GoToNextStep();
  11.168 -                    }
  11.169 -                    else
  11.170 -                    {
  11.171 -                        Log.Error("KeySyncWizard: Error creating handshake item.");
  11.172 -                        this.GoToLastStep(false);
  11.173 -                    }
  11.174 -                }
  11.175 -                catch (Exception ex)
  11.176 -                {
  11.177 -                    Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
  11.178 -                    this.GoToLastStep(false);
  11.179 -                }
  11.180 -            }
  11.181          }
  11.182  
  11.183          #region Property Accessors
  11.184 @@ -177,15 +133,42 @@
  11.185           *************************************************************/
  11.186  
  11.187          /// <summary>
  11.188 -        /// Gets or sets the explanatory text in the wizard.
  11.189 +        /// Gets or sets the Items collection.
  11.190          /// </summary>
  11.191 -        public string ExplanationText
  11.192 +        public WizardState CurrentState
  11.193          {
  11.194 -            get { return this._ExplanationText; }
  11.195 +            get { return this._CurrentState; }
  11.196              set
  11.197              {
  11.198 -                this._ExplanationText = value;
  11.199 -                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
  11.200 +                this._CurrentState = value;
  11.201 +                this.RaisePropertyChangedEvent(nameof(this.CurrentState));
  11.202 +            }
  11.203 +        }
  11.204 +
  11.205 +        /// <summary>
  11.206 +        /// Gets or sets whether to export the private key.
  11.207 +        /// </summary>
  11.208 +        public bool ExportPrivateKey
  11.209 +        {
  11.210 +            get { return this._ExportPrivateKey; }
  11.211 +            set
  11.212 +            {
  11.213 +                this._ExportPrivateKey = value;
  11.214 +                this.RaisePropertyChangedEvent(nameof(this.ExportPrivateKey));
  11.215 +            }
  11.216 +        }
  11.217 +
  11.218 +        /// <summary>
  11.219 +        /// Gets or sets whether this wizard is the one that
  11.220 +        /// initiated the Key Import process.
  11.221 +        /// </summary>
  11.222 +        public bool IsInitiator
  11.223 +        {
  11.224 +            get { return this._IsInitiator; }
  11.225 +            set
  11.226 +            {
  11.227 +                this._IsInitiator = value;
  11.228 +                this.RaisePropertyChangedEvent(nameof(this.IsInitiator));
  11.229              }
  11.230          }
  11.231  
  11.232 @@ -216,19 +199,6 @@
  11.233          }
  11.234  
  11.235          /// <summary>
  11.236 -        /// Gets or sets the Next/Finish button's text.
  11.237 -        /// </summary>
  11.238 -        public string NextButtonText
  11.239 -        {
  11.240 -            get { return this._NextButtonText; }
  11.241 -            set
  11.242 -            {
  11.243 -                this._NextButtonText = value;
  11.244 -                this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
  11.245 -            }
  11.246 -        }
  11.247 -
  11.248 -        /// <summary>
  11.249          /// Gets or sets the sync partner.
  11.250          /// </summary>
  11.251          public PEPIdentity Partner
  11.252 @@ -242,56 +212,35 @@
  11.253          }
  11.254  
  11.255          /// <summary>
  11.256 -        /// Gets or sets the wizard state.
  11.257 +        /// Gets or sets the current wizard step.
  11.258          /// </summary>
  11.259 -        public WizardState State
  11.260 +        public Steps Step
  11.261          {
  11.262 -            get { return this._State; }
  11.263 +            get { return this._Step; }
  11.264              set
  11.265              {
  11.266 -                this._State = value;
  11.267 -                this.RaisePropertyChangedEvent(nameof(this.State));
  11.268 +                this._Step = value;
  11.269 +                this.RaisePropertyChangedEvent(nameof(this.Step));
  11.270              }
  11.271          }
  11.272  
  11.273          /// <summary>
  11.274 -        /// Gets or sets the subtitle text in the wizard.
  11.275 +        /// Gets or sets whether to use the imported key as default key.
  11.276          /// </summary>
  11.277 -        public string SubtitleText
  11.278 +        public bool SetImportedKeyAsDefault
  11.279          {
  11.280 -            get { return this._SubtitleText; }
  11.281 +            get { return this._SetImportedKeyAsDefault; }
  11.282              set
  11.283              {
  11.284 -                this._SubtitleText = value;
  11.285 -                this.RaisePropertyChangedEvent(nameof(this.SubtitleText));
  11.286 +                this._SetImportedKeyAsDefault = value;
  11.287 +                this.RaisePropertyChangedEvent(nameof(this.SetImportedKeyAsDefault));
  11.288              }
  11.289          }
  11.290  
  11.291          /// <summary>
  11.292          /// Gets or sets the success state.
  11.293          /// </summary>
  11.294 -        public bool Success
  11.295 -        {
  11.296 -            get { return this._Success; }
  11.297 -            set
  11.298 -            {
  11.299 -                this._Success = value;
  11.300 -                this.RaisePropertyChangedEvent(nameof(this.Success));
  11.301 -            }
  11.302 -        }
  11.303  
  11.304 -        /// <summary>
  11.305 -        /// Gets or sets the title text in the wizard.
  11.306 -        /// </summary>
  11.307 -        public string TitleText
  11.308 -        {
  11.309 -            get { return this._TitleText; }
  11.310 -            set
  11.311 -            {
  11.312 -                this._TitleText = value;
  11.313 -                this.RaisePropertyChangedEvent(nameof(this.TitleText));
  11.314 -            }
  11.315 -        }
  11.316  
  11.317          /// <summary>
  11.318          /// Gets or sets the wizard type.
  11.319 @@ -306,6 +255,35 @@
  11.320              }
  11.321          }
  11.322  
  11.323 +        /// <summary>
  11.324 +        /// Gets the user name to display in the dialog.
  11.325 +        /// </summary>
  11.326 +        public string UserName
  11.327 +        {
  11.328 +            get
  11.329 +            {
  11.330 +                string userName = string.Empty;
  11.331 +
  11.332 +                // Try to get user name in format "name (address)"
  11.333 +                if (string.IsNullOrEmpty(this.Myself?.UserName) == false)
  11.334 +                {
  11.335 +                    userName = this.Myself.UserName;
  11.336 +
  11.337 +                    if (string.IsNullOrEmpty(this.Myself?.Address) == false)
  11.338 +                    {
  11.339 +                        userName += " (" + this.Myself.Address + ")";
  11.340 +                    }
  11.341 +                }
  11.342 +                // If we have no user name, just display address
  11.343 +                else if (string.IsNullOrEmpty(this.Myself?.Address) == false)
  11.344 +                {
  11.345 +                    userName = this.Myself.Address;
  11.346 +                }
  11.347 +
  11.348 +                return userName;
  11.349 +            }
  11.350 +        }
  11.351 +
  11.352          #endregion
  11.353  
  11.354          #region Event handlers
  11.355 @@ -315,39 +293,195 @@
  11.356           * 
  11.357           *************************************************************/
  11.358  
  11.359 +        /// <summary>
  11.360 +        /// Event handler for when the OK/Next button is clicked.
  11.361 +        /// </summary>
  11.362 +        private void AcceptButton_Click(object sender, RoutedEventArgs e)
  11.363 +        {
  11.364 +            this.CurrentState.AcceptButtonClick();
  11.365 +        }
  11.366 +
  11.367 +        /// <summary>
  11.368 +        /// Event handler for when the Back button is clicked.
  11.369 +        /// </summary>
  11.370 +        private void BackButton_Click(object sender, RoutedEventArgs e)
  11.371 +        {
  11.372 +            this.CurrentState.BackButtonClick();
  11.373 +        }
  11.374 +
  11.375 +        /// <summary>
  11.376 +        /// Event handler for when the Cancel button is clicked.
  11.377 +        /// </summary>
  11.378          private void CancelButton_Click(object sender, RoutedEventArgs e)
  11.379          {
  11.380 -            this.Close();
  11.381 +            this.CurrentState.CancelButtonClick();
  11.382          }
  11.383  
  11.384 -        private void OKNextButton_Click(object sender, RoutedEventArgs e)
  11.385 +        /// <summary>
  11.386 +        /// Event handler for when a sync message arrives while the wizard is open and in progress.
  11.387 +        /// </summary>
  11.388 +        private void KeySyncWizard_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
  11.389          {
  11.390 -            // Navigation logic
  11.391 -            switch (this.State)
  11.392 +            // Ignore outgoing messages
  11.393 +            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
  11.394              {
  11.395 -                case WizardState.Step2:
  11.396 +                try
  11.397 +                {
  11.398 +                    // Waiting for message with public key from other device
  11.399 +                    if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step1)) ||
  11.400 +                        ((this.Type == WizardType.PGP) && (this.Step == Steps.Step4)))
  11.401                      {
  11.402 -                        // User accepts the fingerprint. Make channel green.
  11.403 -                        this.TrustKey();
  11.404 +                        string partnerFpr = null;
  11.405 +
  11.406 +                        // Make sure the channel is not already trusted (either attack or re-processing)
  11.407 +                        if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
  11.408 +                        {
  11.409 +                            Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
  11.410 +                            return;
  11.411 +                        }
  11.412 +
  11.413 +                        // In case of pEp sync, use header
  11.414 +                        if (this.Type == WizardType.pEp)
  11.415 +                        {
  11.416 +                            // Public key message received. Show trustwords.
  11.417 +                            partnerFpr = e.Message?.KeyImport;
  11.418 +
  11.419 +                            Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
  11.420 +
  11.421 +                            // Doublecheck that it's not the own key
  11.422 +                            if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
  11.423 +                            {
  11.424 +                                partnerFpr = null;
  11.425 +                            }
  11.426 +                        }
  11.427 +                        else if (this.Type == WizardType.PGP)
  11.428 +                        {
  11.429 +                            // In case of PGP import, use key list
  11.430 +                            string[] keys = e.Message?.KeyList?.Split(',');
  11.431 +                            for (int i = 0; i < keys?.Length; i++)
  11.432 +                            {
  11.433 +                                if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
  11.434 +                                {
  11.435 +                                    partnerFpr = keys[i];
  11.436 +                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
  11.437 +                                    break;
  11.438 +                                }
  11.439 +                            }
  11.440 +                        }
  11.441 +                        else
  11.442 +                        {
  11.443 +                            Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
  11.444 +                        }
  11.445 +
  11.446 +                        // If we have a valid fingerprint, show Trustwords
  11.447 +                        if ((this.IsInitiator) &&
  11.448 +                            (string.IsNullOrEmpty(partnerFpr) == false))
  11.449 +                        {
  11.450 +                            // Set the partner's fingerprint
  11.451 +                            this.Partner.Fingerprint = partnerFpr;
  11.452 +
  11.453 +                            // Marshall to main thread
  11.454 +                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  11.455 +                            {
  11.456 +                                // Create the handshake item 
  11.457 +                                if (this.CreateHandshakeItem())
  11.458 +                                {
  11.459 +                                    this.GoToNextStep();
  11.460 +                                }
  11.461 +                                else
  11.462 +                                {
  11.463 +                                    Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
  11.464 +                                    this.GoToLastStep(false);
  11.465 +                                }
  11.466 +                            }));
  11.467 +                        }
  11.468 +                        else
  11.469 +                        {
  11.470 +                            Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
  11.471 +                        }
  11.472                      }
  11.473 -                    break;
  11.474 -                /* 'Step 1' and 'Step 3' are not clickable. 
  11.475 -                 * 'Step 4' finishes the process. 
  11.476 -                 * 'Undefined' means an error occured.
  11.477 -                 */
  11.478 -                case WizardState.Step1:
  11.479 -                case WizardState.Step3:
  11.480 -                case WizardState.Step4:
  11.481 -                case WizardState.Undefined:
  11.482 -                default:
  11.483 +                    // Waiting for private key message
  11.484 +                    else if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step3)) ||
  11.485 +                             ((this.Type == WizardType.PGP) && (this.Step == Steps.Step8)))
  11.486                      {
  11.487 -                        this.Close();
  11.488 +                        /* Finish the process under the following conditions:
  11.489 +                         *  1. PGP key import + own private key flag
  11.490 +                         *  2. pEp key import +
  11.491 +                         *      a. initiator wizard + own private key flag + partner fpr in key import header
  11.492 +                         *      b. not initiator wizard + trusted message + partner fpr in key import header
  11.493 +                         */
  11.494 +                        bool hasDecryptFlagOwnPrivateKey = e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey);
  11.495 +                        if (((this.Type == WizardType.PGP) && (hasDecryptFlagOwnPrivateKey)) ||
  11.496 +                            ((this.IsInitiator) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (hasDecryptFlagOwnPrivateKey)) ||
  11.497 +                            ((this.IsInitiator == false) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (e.Message.Rating >= pEpRating.pEpRatingTrusted)))
  11.498 +                        {
  11.499 +                            // Set flag
  11.500 +                            this.privateKeyImported = hasDecryptFlagOwnPrivateKey;
  11.501 +
  11.502 +                            // Marshall to main thread
  11.503 +                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  11.504 +                            {
  11.505 +                                // Set private key as default if needed
  11.506 +                                bool success = false;
  11.507 +                                if ((this.IsInitiator) &&
  11.508 +                                    (this.SetImportedKeyAsDefault))
  11.509 +                                {
  11.510 +                                    try
  11.511 +                                    {
  11.512 +                                        pEpIdentity partner = this.Partner.ToCOMType();
  11.513 +                                        ThisAddIn.PEPEngine.SetOwnKey(partner, partner.fpr);
  11.514 +                                        success = true;
  11.515 +                                    }
  11.516 +                                    catch (Exception ex)
  11.517 +                                    {
  11.518 +                                        success = false;
  11.519 +                                        Log.Error("AcceptButtonClick: Error setting own key. " + ex.ToString());
  11.520 +                                    }
  11.521 +                                }
  11.522 +                                else
  11.523 +                                {
  11.524 +                                    success = true;
  11.525 +                                }
  11.526 +
  11.527 +                                this.GoToLastStep(success);
  11.528 +
  11.529 +                            }));
  11.530 +                        }
  11.531 +                        else
  11.532 +                        {
  11.533 +                            Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. Steps: Step 3. Own private key flag is " +
  11.534 +                                        e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
  11.535 +                                        Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
  11.536 +                                        e.Message?.KeyImport ?? "null");
  11.537 +                        }
  11.538                      }
  11.539 -                    break;
  11.540 +                }
  11.541 +                catch (Exception ex)
  11.542 +                {
  11.543 +                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
  11.544 +                }
  11.545              }
  11.546          }
  11.547  
  11.548          /// <summary>
  11.549 +        /// Event handler for when the label next to the Export Private Key checkbox
  11.550 +        /// is clicked.
  11.551 +        /// </summary>
  11.552 +        private void LabelExportPrivateKey_MouseUp(object sender, MouseButtonEventArgs e)
  11.553 +        {
  11.554 +            this.ExportPrivateKey = (this.ExportPrivateKey == false);
  11.555 +        }
  11.556 +
  11.557 +        /// <summary>
  11.558 +        /// Event handler for when the label next to the Set Imported Key As Default checkbox
  11.559 +        /// is clicked.
  11.560 +        /// </summary>
  11.561 +        private void LabelSetImportedKeyAsDefault_MouseUp(object sender, MouseButtonEventArgs e)
  11.562 +        {
  11.563 +            this.SetImportedKeyAsDefault = (this.SetImportedKeyAsDefault == false);
  11.564 +        }
  11.565 +
  11.566 +        /// <summary>
  11.567          /// Raises the property changed event, if possible, with the given arguments.
  11.568          /// </summary>
  11.569          /// <param name="propertyName">The name of the property that changed.</param>
  11.570 @@ -358,127 +492,40 @@
  11.571          }
  11.572  
  11.573          /// <summary>
  11.574 -        /// Event handler for when a sync message arrives while the wizard is open and in progress.
  11.575 +        /// Shows the handshake window
  11.576          /// </summary>
  11.577 -        private void KeySyncWizard_SyncMessageReceived(object sender, CryptableMailItem.SyncMessageEventArgs e)
  11.578 +        private bool ShowHandshake()
  11.579          {
  11.580 -            // Ignore outgoing messages
  11.581 -            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
  11.582 +            bool success = false;
  11.583 +
  11.584 +            try
  11.585              {
  11.586 -                try
  11.587 +                // Update own identity if necessary
  11.588 +                if (string.IsNullOrEmpty(this.Myself?.Fingerprint))
  11.589                  {
  11.590 -                    switch (this.State)
  11.591 -                    {
  11.592 -                        // Step 1: get partner fingerprint and show Trustwords
  11.593 -                        case WizardState.Step1:
  11.594 -                            {
  11.595 -                                string partnerFpr = null;
  11.596 +                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
  11.597 +                }
  11.598  
  11.599 -                                // Make sure the channel is not already trusted (either attack or re-processing)
  11.600 -                                if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
  11.601 -                                {
  11.602 -                                    Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
  11.603 -                                    return;
  11.604 -                                }
  11.605 +                // Create handshake item
  11.606 +                if (this.CreateHandshakeItem())
  11.607 +                {
  11.608 +                    // Set success flag
  11.609 +                    success = true;
  11.610  
  11.611 -                                // In case of pEp sync, use header
  11.612 -                                if (this.Type == WizardType.pEp)
  11.613 -                                {
  11.614 -                                    // Public key message received. Show trustwords.
  11.615 -                                    partnerFpr = e.Message?.KeyImport;
  11.616 -
  11.617 -                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
  11.618 -
  11.619 -                                    // Doublecheck that it's not the own key
  11.620 -                                    if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
  11.621 -                                    {
  11.622 -                                        partnerFpr = null;
  11.623 -                                    }
  11.624 -                                }
  11.625 -                                else if (this.Type == WizardType.PGP)
  11.626 -                                {
  11.627 -                                    // In case of PGP import, use key list
  11.628 -                                    string[] keys = e.Message?.KeyList?.Split(',');
  11.629 -                                    for (int i = 0; i < keys?.Length; i++)
  11.630 -                                    {
  11.631 -                                        if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
  11.632 -                                        {
  11.633 -                                            partnerFpr = keys[i];
  11.634 -                                            Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
  11.635 -                                            break;
  11.636 -                                        }
  11.637 -                                    }
  11.638 -                                }
  11.639 -                                else
  11.640 -                                {
  11.641 -                                    Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
  11.642 -                                }
  11.643 -
  11.644 -                                // If we have a valid fingerprint, show Trustwords
  11.645 -                                if (string.IsNullOrEmpty(partnerFpr) == false)
  11.646 -                                {
  11.647 -                                    // Set the partner's fingerprint
  11.648 -                                    this.Partner.Fingerprint = partnerFpr;
  11.649 -
  11.650 -                                    // Marshall to main thread
  11.651 -                                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
  11.652 -                                    {
  11.653 -                                        // Create the handshake item 
  11.654 -                                        if (this.CreateHandshakeItem())
  11.655 -                                        {
  11.656 -                                            this.GoToNextStep();
  11.657 -                                        }
  11.658 -                                        else
  11.659 -                                        {
  11.660 -                                            Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
  11.661 -                                            this.GoToLastStep(false);
  11.662 -                                        }
  11.663 -                                    }));
  11.664 -                                }
  11.665 -                                else
  11.666 -                                {
  11.667 -                                    Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
  11.668 -                                }
  11.669 -                            }
  11.670 -                            break;
  11.671 -                        case WizardState.Step2:
  11.672 -                            {
  11.673 -                                Log.Verbose("KeySyncWizard_SyncMessageReceived: Nothing done. WizardState is Step 2.");
  11.674 -                            }
  11.675 -                            break;
  11.676 -                        case WizardState.Step3:
  11.677 -                            {
  11.678 -                                /* Finish the process if a private key has been imported and the message
  11.679 -                                 * is at least trusted.
  11.680 -                                 * For pEp key import, check also that we don't import our own key.
  11.681 -                                 */ 
  11.682 -                                if ((e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)) &&
  11.683 -                                    (e.Message.Rating >= pEpRating.pEpRatingTrusted) &&
  11.684 -                                    ((e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) ||
  11.685 -                                     (this.Type == WizardType.PGP)))
  11.686 -                                {
  11.687 -                                    this.CompleteWizard();
  11.688 -                                }
  11.689 -                                else
  11.690 -                                {
  11.691 -                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. WizardState: Step 3. Own private key flag is " +
  11.692 -                                                e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
  11.693 -                                                Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
  11.694 -                                                e.Message?.KeyImport ?? "null");
  11.695 -                                }
  11.696 -                            }
  11.697 -                            break;
  11.698 -                        case WizardState.Step4:
  11.699 -                        case WizardState.Undefined:
  11.700 -                        default:
  11.701 -                            break;
  11.702 -                    }
  11.703 +                    // Send answer message with pub key
  11.704 +                    this.SendSyncMessage(MessageTypes.PublicKeyMessage);
  11.705                  }
  11.706 -                catch (Exception ex)
  11.707 +                else
  11.708                  {
  11.709 -                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
  11.710 +                    Log.Error("KeySyncWizard: Error creating handshake item.");
  11.711                  }
  11.712              }
  11.713 +            catch (Exception ex)
  11.714 +            {
  11.715 +                Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
  11.716 +            }
  11.717 +
  11.718 +            return success;
  11.719          }
  11.720  
  11.721          /// <summary>
  11.722 @@ -487,7 +534,7 @@
  11.723          private void Window_Closed(object sender, EventArgs e)
  11.724          {
  11.725              // Remove event handler
  11.726 -            CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
  11.727 +            MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
  11.728  
  11.729              // Reset static references
  11.730              KeySyncWizard.Wizard = new KeySyncWizard();
  11.731 @@ -503,18 +550,69 @@
  11.732           *************************************************************/
  11.733  
  11.734          /// <summary>
  11.735 +        /// Adds the given PEPMessage to the list of received sync messages.
  11.736 +        /// </summary>
  11.737 +        /// <param name="message">The PEPMessage to add to the list.</param>
  11.738 +        public void AddToReceivedSyncMessages(PEPMessage message)
  11.739 +        {
  11.740 +            /* Add message to list if:
  11.741 +             *  1.  a. WizardType is PGP and message is secure
  11.742 +             *      b. WizardType is pEp, the current step is Step 2 and the
  11.743 +             *         message hasn't been sent from myself
  11.744 +             *  2. Message is not in the list yet
  11.745 +             */
  11.746 +            lock (mutexReceivedSyncMessages)
  11.747 +            {
  11.748 +                if (((this.Type == WizardType.PGP) &&
  11.749 +                     (message.IsSecure) ||
  11.750 +                     ((this.Type == WizardType.pEp) &&
  11.751 +                      (this.Step == Steps.Step2) &&
  11.752 +                      (this.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))) &&
  11.753 +                    (this.receivedSyncMessages?.Find(a => (a.Id?.Equals(message.Id) == true)) == null))
  11.754 +                {
  11.755 +                    this.receivedSyncMessages?.Add(message);
  11.756 +                }
  11.757 +            }
  11.758 +        }
  11.759 +
  11.760 +        /// <summary>
  11.761 +        /// Closes the wizard and resets the partner identity in the management.db.
  11.762 +        /// </summary>
  11.763 +        private void CancelWizard()
  11.764 +        {
  11.765 +            try
  11.766 +            {
  11.767 +                pEpIdentity partner = this.Partner.Copy().ToCOMType();
  11.768 +
  11.769 +                if (string.IsNullOrEmpty(partner.fpr) == false)
  11.770 +                {
  11.771 +                    Task.Factory.StartNew(new Action(() =>
  11.772 +                    {
  11.773 +                        ThisAddIn.PEPEngine.KeyResetTrust(partner);
  11.774 +                    }), TaskCreationOptions.LongRunning);
  11.775 +                }
  11.776 +            }
  11.777 +            catch (Exception ex)
  11.778 +            {
  11.779 +                Log.Error("CancelWizard: Error resetting identity. " + ex.ToString());
  11.780 +            }
  11.781 +
  11.782 +            this.Close();
  11.783 +        }
  11.784 +
  11.785 +        /// <summary>
  11.786          /// Completes the process and moves wizard to last step.
  11.787          /// Sets the imported private key as own key, if needed.
  11.788          /// </summary>
  11.789          private void CompleteWizard()
  11.790          {
  11.791              // Marshall to main thread
  11.792 -            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
  11.793 +            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  11.794              {
  11.795                  bool success = false;
  11.796  
  11.797                  // Private key message received. Set key as default if needed.
  11.798 -                if (this.isInitiator)
  11.799 +                if (this.IsInitiator)
  11.800                  {
  11.801                      try
  11.802                      {
  11.803 @@ -550,9 +648,10 @@
  11.804              HandshakeItem item;
  11.805              if (HandshakeItem.Create(this.Myself, this.Partner, false, out item) == Globals.ReturnStatus.Success)
  11.806              {
  11.807 -                item.AreTabControlsVisible = (this.Type == WizardType.PGP);
  11.808 +                item.AreTabControlsVisible = false;
  11.809                  item.ActiveTab = (this.Type == WizardType.pEp) ? HandshakeItem.Tabs.Trustwords : HandshakeItem.Tabs.Fingerprint;
  11.810                  item.AreHandshakeButtonsVisible = false;
  11.811 +                item.Mode = HandshakeItem.HandshakeMode.Sync;
  11.812                  this.Items.Add(item);
  11.813  
  11.814                  success = true;
  11.815 @@ -563,17 +662,658 @@
  11.816          }
  11.817  
  11.818          /// <summary>
  11.819 +        /// Creates a list of wizard states that serve as model for the wizard.
  11.820 +        /// The pEp Key Import process consists of the following steps:
  11.821 +        ///     Step 1:
  11.822 +        ///         a. Is initiator(user opened wizard): Info message that sync message has been sent.
  11.823 +        ///            Waiting for answer message from other device.
  11.824 +        ///         b. Is not initiator (wizard opened through sync message): Info message that key import has been started.
  11.825 +        ///            Waiting for user decision to continue or abort.
  11.826 +        ///     Step 2:
  11.827 +        ///         - Show trustwords. User interaction: confirm or cancel.
  11.828 +        ///     Step 3: 
  11.829 +        ///         - Private keys have been sent. Waiting for answer message from other device.
  11.830 +        ///     Step 4: 
  11.831 +        ///         - Only on initiator side: Ask user if they want to set imported key as default. Next or Cancel.
  11.832 +        ///     Success:
  11.833 +        ///         - Key Import successfully finished.
  11.834 +        ///     Error:
  11.835 +        ///         - An error occured during the Key Import process.
  11.836 +        /// </summary>
  11.837 +        /// <returns>The list of wizard states.</returns>
  11.838 +        private List<WizardState> CreatePEPWizardStates()
  11.839 +        {
  11.840 +            List<WizardState> states = new List<WizardState>();
  11.841 +
  11.842 +            try
  11.843 +            {
  11.844 +                // Step 1
  11.845 +                states.Add(new WizardState
  11.846 +                {
  11.847 +                    // Step
  11.848 +                    Step = Steps.Step1,
  11.849 +
  11.850 +                    // Title text
  11.851 +                    TitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_PEPStep1ExplanationText : Properties.Resources.KeySyncWizard_PEPStep1NonInitiatorExplanationText,
  11.852 +
  11.853 +                    // Central area
  11.854 +                    AreTrustwordsVisible = false,
  11.855 +                    IsUserTextVisible = true,
  11.856 +                    UserText = this.UserName,
  11.857 +
  11.858 +                    // Back button
  11.859 +                    IsBackButtonVisible = false,
  11.860 +
  11.861 +                    // Accept button
  11.862 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Start,
  11.863 +                    IsAcceptButtonVisible = (this.IsInitiator == false),
  11.864 +                    AcceptButtonClick = new Action(() =>
  11.865 +                    {
  11.866 +                        if (this.ShowHandshake())
  11.867 +                        {
  11.868 +                            this.GoToNextStep();
  11.869 +                        }
  11.870 +                        else
  11.871 +                        {
  11.872 +                            this.GoToLastStep(false);
  11.873 +                        }
  11.874 +                    }),
  11.875 +
  11.876 +                    // Cancel button
  11.877 +                    CancelButtonText = Properties.Resources.Options_CancelText,
  11.878 +                    IsCancelButtonVisible = true,
  11.879 +                    CancelButtonClick = new Action(() =>
  11.880 +                    {
  11.881 +                        this.CancelWizard();
  11.882 +                    }),
  11.883 +
  11.884 +                    // Subtitle area
  11.885 +                    SubtitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_WaitingForResponseText : null
  11.886 +                });
  11.887 +
  11.888 +                // Step 2
  11.889 +                states.Add(new WizardState
  11.890 +                {
  11.891 +                    // Step
  11.892 +                    Step = Steps.Step2,
  11.893 +
  11.894 +                    // Title text
  11.895 +                    TitleText = Properties.Resources.KeySyncWizard_PEPStep2ExplanationText,
  11.896 +
  11.897 +                    // Central area
  11.898 +                    AreTrustwordsVisible = true,
  11.899 +                    IsUserTextVisible = false,
  11.900 +
  11.901 +                    // Back button
  11.902 +                    IsBackButtonVisible = false,
  11.903 +
  11.904 +                    // Accept button
  11.905 +                    AcceptButtonText = Properties.Resources.Handshake_ConfirmTrustwords,
  11.906 +                    IsAcceptButtonVisible = true,
  11.907 +                    AcceptButtonClick = new Action(() =>
  11.908 +                    {
  11.909 +                        this.GoToNextStep();
  11.910 +                        this.TrustKey();
  11.911 +                    }),
  11.912 +
  11.913 +                    // Cancel button
  11.914 +                    CancelButtonText = Properties.Resources.Handshake_WrongTrustwords,
  11.915 +                    IsCancelButtonVisible = true,
  11.916 +                    CancelButtonClick = new Action(() =>
  11.917 +                    {
  11.918 +                        this.CancelWizard();
  11.919 +                    }),
  11.920 +
  11.921 +                    // Subtitle area
  11.922 +                    SubtitleText = null
  11.923 +                });
  11.924 +
  11.925 +                // Step 3
  11.926 +                states.Add(new WizardState
  11.927 +                {
  11.928 +                    // Step
  11.929 +                    Step = Steps.Step3,
  11.930 +
  11.931 +                    // Title text
  11.932 +                    TitleText = Properties.Resources.KeySyncWizard_PEPStep3ExplanationText,
  11.933 +
  11.934 +                    // Central area
  11.935 +                    AreTrustwordsVisible = false,
  11.936 +                    IsUserTextVisible = true,
  11.937 +                    UserText = this.UserName,
  11.938 +
  11.939 +                    // Back button
  11.940 +                    IsBackButtonVisible = false,
  11.941 +
  11.942 +                    // Accept button
  11.943 +                    IsAcceptButtonVisible = false,
  11.944 +
  11.945 +                    // Cancel button
  11.946 +                    CancelButtonText = Properties.Resources.Options_CancelText,
  11.947 +                    IsCancelButtonVisible = true,
  11.948 +                    CancelButtonClick = new Action(() =>
  11.949 +                    {
  11.950 +                        this.CancelWizard();
  11.951 +                    }),
  11.952 +
  11.953 +                    // Subtitle area
  11.954 +                    SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText
  11.955 +                });
  11.956 +
  11.957 +                // Success
  11.958 +                states.Add(new WizardState
  11.959 +                {
  11.960 +                    // Step
  11.961 +                    Step = Steps.Success,
  11.962 +
  11.963 +                    // Title text
  11.964 +                    TitleText = null,
  11.965 +
  11.966 +                    // Central area
  11.967 +                    AreTrustwordsVisible = false,
  11.968 +                    IsUserTextVisible = true,
  11.969 +                    UserText = this.UserName,
  11.970 +
  11.971 +                    // Back button
  11.972 +                    IsBackButtonVisible = false,
  11.973 +
  11.974 +                    // Accept button
  11.975 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
  11.976 +                    IsAcceptButtonVisible = true,
  11.977 +                    AcceptButtonClick = new Action(() =>
  11.978 +                    {
  11.979 +                        this.Close();
  11.980 +                    }),
  11.981 +
  11.982 +                    // Cancel button
  11.983 +                    IsCancelButtonVisible = false,
  11.984 +
  11.985 +                    // Subtitle area
  11.986 +                    SubtitleText = null
  11.987 +                });
  11.988 +
  11.989 +                // Error
  11.990 +                states.Add(new WizardState
  11.991 +                {
  11.992 +                    // Step
  11.993 +                    Step = Steps.Error,
  11.994 +
  11.995 +                    // Title text
  11.996 +                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
  11.997 +
  11.998 +                    // Central area
  11.999 +                    AreTrustwordsVisible = false,
 11.1000 +                    IsUserTextVisible = true,
 11.1001 +                    UserText = this.UserName,
 11.1002 +
 11.1003 +                    // Back button
 11.1004 +                    IsBackButtonVisible = false,
 11.1005 +
 11.1006 +                    // Accept button
 11.1007 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
 11.1008 +                    IsAcceptButtonVisible = true,
 11.1009 +                    AcceptButtonClick = new Action(() =>
 11.1010 +                    {
 11.1011 +                        this.CancelWizard();
 11.1012 +                    }),
 11.1013 +
 11.1014 +                    // Cancel button
 11.1015 +                    IsCancelButtonVisible = false,
 11.1016 +
 11.1017 +                    // Subtitle area
 11.1018 +                    SubtitleText = null
 11.1019 +                });
 11.1020 +            }
 11.1021 +            catch (Exception ex)
 11.1022 +            {
 11.1023 +                states = null;
 11.1024 +                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
 11.1025 +            }
 11.1026 +
 11.1027 +            return states;
 11.1028 +        }
 11.1029 +
 11.1030 +        /// <summary>
 11.1031 +        /// Creates a list of wizard states that serve as model for the wizard.
 11.1032 +        /// The PGP Key Import process consists of the following steps:
 11.1033 +        ///     Steps 1-3:
 11.1034 +        ///         - Instructions on how to prepare the answer message with pub key.
 11.1035 +        ///     Step 4: 
 11.1036 +        ///         - Waiting for answer message from other device.
 11.1037 +        ///     Step 5: 
 11.1038 +        ///         - Show fingerprints. Confirm or deny them.        
 11.1039 +        ///     Step 6 - 7: 
 11.1040 +        ///         - Instructions on how to prepare the answer message with private key.
 11.1041 +        ///     Success:
 11.1042 +        ///         - Key Import successfully finished.
 11.1043 +        ///     Error:
 11.1044 +        ///         - An error occured during the Key Import process.
 11.1045 +        /// </summary>
 11.1046 +        /// <returns>The list of wizard states.</returns>
 11.1047 +        private List<WizardState> CreatePGPWizardStates()
 11.1048 +        {
 11.1049 +            List<WizardState> states = new List<WizardState>();
 11.1050 +
 11.1051 +            try
 11.1052 +            {
 11.1053 +                // Step 1
 11.1054 +                states.Add(new WizardState
 11.1055 +                {
 11.1056 +                    // Step
 11.1057 +                    Step = Steps.Step1,
 11.1058 +
 11.1059 +                    // Title text
 11.1060 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep1ExplanationText,
 11.1061 +
 11.1062 +                    // Central area
 11.1063 +                    AreTrustwordsVisible = false,
 11.1064 +                    IsUserTextVisible = true,
 11.1065 +                    UserText = this.UserName,
 11.1066 +
 11.1067 +                    // Back button
 11.1068 +                    IsBackButtonVisible = false,
 11.1069 +
 11.1070 +                    // Accept button
 11.1071 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
 11.1072 +                    IsAcceptButtonVisible = true,
 11.1073 +                    AcceptButtonClick = new Action(() =>
 11.1074 +                    {
 11.1075 +                        this.GoToNextStep();
 11.1076 +                    }),
 11.1077 +
 11.1078 +                    // Cancel button
 11.1079 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1080 +                    IsCancelButtonVisible = true,
 11.1081 +                    CancelButtonClick = new Action(() =>
 11.1082 +                    {
 11.1083 +                        this.CancelWizard();
 11.1084 +                    }),
 11.1085 +
 11.1086 +                    // Subtitle area
 11.1087 +                    SubtitleText = null
 11.1088 +                });
 11.1089 +
 11.1090 +                // Step 2
 11.1091 +                states.Add(new WizardState
 11.1092 +                {
 11.1093 +                    // Step
 11.1094 +                    Step = Steps.Step2,
 11.1095 +
 11.1096 +                    // Title text
 11.1097 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep2ExplanationText,
 11.1098 +
 11.1099 +                    // Central area
 11.1100 +                    AreTrustwordsVisible = false,
 11.1101 +                    IsUserTextVisible = true,
 11.1102 +                    UserText = this.UserName,
 11.1103 +
 11.1104 +                    // Back button
 11.1105 +                    IsBackButtonVisible = true,
 11.1106 +                    BackButtonClick = new Action(() =>
 11.1107 +                    {
 11.1108 +                        this.GoToPreviousStep();
 11.1109 +                    }),
 11.1110 +
 11.1111 +                    // Accept button
 11.1112 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
 11.1113 +                    IsAcceptButtonVisible = true,
 11.1114 +                    AcceptButtonClick = new Action(() =>
 11.1115 +                    {
 11.1116 +                        this.GoToNextStep();
 11.1117 +                    }),
 11.1118 +
 11.1119 +                    // Cancel button
 11.1120 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1121 +                    IsCancelButtonVisible = true,
 11.1122 +                    CancelButtonClick = new Action(() =>
 11.1123 +                    {
 11.1124 +                        this.CancelWizard();
 11.1125 +                    }),
 11.1126 +
 11.1127 +                    // Subtitle area
 11.1128 +                    SubtitleText = null
 11.1129 +                });
 11.1130 +
 11.1131 +                // Step 3
 11.1132 +                states.Add(new WizardState
 11.1133 +                {
 11.1134 +                    // Step
 11.1135 +                    Step = Steps.Step3,
 11.1136 +
 11.1137 +                    // Title text
 11.1138 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep3ExplanationText,
 11.1139 +
 11.1140 +                    // Central area
 11.1141 +                    AreTrustwordsVisible = false,
 11.1142 +                    IsUserTextVisible = true,
 11.1143 +                    UserText = this.UserName,
 11.1144 +
 11.1145 +                    // Back button
 11.1146 +                    IsBackButtonVisible = true,
 11.1147 +                    BackButtonClick = new Action(() =>
 11.1148 +                    {
 11.1149 +                        this.GoToPreviousStep();
 11.1150 +                    }),
 11.1151 +
 11.1152 +                    // Accept button
 11.1153 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
 11.1154 +                    IsAcceptButtonVisible = true,
 11.1155 +                    AcceptButtonClick = new Action(() =>
 11.1156 +                    {
 11.1157 +                        this.GoToNextStep();
 11.1158 +                        this.ProcessReceivedSyncMessages();
 11.1159 +                    }),
 11.1160 +
 11.1161 +                    // Cancel button
 11.1162 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1163 +                    IsCancelButtonVisible = true,
 11.1164 +                    CancelButtonClick = new Action(() =>
 11.1165 +                    {
 11.1166 +                        this.CancelWizard();
 11.1167 +                    }),
 11.1168 +
 11.1169 +                    // Subtitle area
 11.1170 +                    SubtitleText = null
 11.1171 +                });
 11.1172 +
 11.1173 +                // Step 4
 11.1174 +                states.Add(new WizardState
 11.1175 +                {
 11.1176 +                    // Step
 11.1177 +                    Step = Steps.Step4,
 11.1178 +
 11.1179 +                    // Title text
 11.1180 +                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
 11.1181 +
 11.1182 +                    // Central area
 11.1183 +                    AreTrustwordsVisible = false,
 11.1184 +                    IsUserTextVisible = true,
 11.1185 +                    UserText = this.UserName,
 11.1186 +
 11.1187 +                    // Back button
 11.1188 +                    // Back button
 11.1189 +                    IsBackButtonVisible = true,
 11.1190 +                    BackButtonClick = new Action(() =>
 11.1191 +                    {
 11.1192 +                        this.GoToPreviousStep();
 11.1193 +                    }),
 11.1194 +
 11.1195 +                    // Accept button
 11.1196 +                    IsAcceptButtonVisible = false,
 11.1197 +
 11.1198 +                    // Cancel button
 11.1199 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1200 +                    IsCancelButtonVisible = true,
 11.1201 +                    CancelButtonClick = new Action(() =>
 11.1202 +                    {
 11.1203 +                        this.CancelWizard();
 11.1204 +                    }),
 11.1205 +
 11.1206 +                    // Subtitle area
 11.1207 +                    SubtitleText = null
 11.1208 +                });
 11.1209 +
 11.1210 +                // Step 5
 11.1211 +                states.Add(new WizardState
 11.1212 +                {
 11.1213 +                    // Step
 11.1214 +                    Step = Steps.Step5,
 11.1215 +
 11.1216 +                    // Title text
 11.1217 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep5ExplanationText,
 11.1218 +
 11.1219 +                    // Central area
 11.1220 +                    AreTrustwordsVisible = true,
 11.1221 +                    IsUserTextVisible = false,
 11.1222 +
 11.1223 +                    // Back button
 11.1224 +                    IsBackButtonVisible = false,
 11.1225 +
 11.1226 +                    // Accept button
 11.1227 +                    AcceptButtonText = Properties.Resources.Handshake_ConfirmFingerprint,
 11.1228 +                    IsAcceptButtonVisible = true,
 11.1229 +                    AcceptButtonClick = new Action(() =>
 11.1230 +                    {
 11.1231 +                        this.GoToNextStep();
 11.1232 +                        this.TrustKey();
 11.1233 +                    }),
 11.1234 +
 11.1235 +                    // Cancel button
 11.1236 +                    CancelButtonText = Properties.Resources.Handshake_WrongFingerprint,
 11.1237 +                    IsCancelButtonVisible = true,
 11.1238 +                    CancelButtonClick = new Action(() =>
 11.1239 +                    {
 11.1240 +                        this.CancelWizard();
 11.1241 +                    }),
 11.1242 +
 11.1243 +                    // Subtitle area
 11.1244 +                    SubtitleText = null
 11.1245 +                });
 11.1246 +
 11.1247 +                // Step 6
 11.1248 +                states.Add(new WizardState
 11.1249 +                {
 11.1250 +                    // Step
 11.1251 +                    Step = Steps.Step6,
 11.1252 +
 11.1253 +                    // Title text
 11.1254 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep6ExplanationText,
 11.1255 +
 11.1256 +                    // Central area
 11.1257 +                    AreTrustwordsVisible = false,
 11.1258 +                    IsUserTextVisible = true,
 11.1259 +                    UserText = this.UserName,
 11.1260 +
 11.1261 +                    // Back button
 11.1262 +                    IsBackButtonVisible = false,
 11.1263 +
 11.1264 +                    // Accept button
 11.1265 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
 11.1266 +                    IsAcceptButtonVisible = true,
 11.1267 +                    AcceptButtonClick = new Action(() =>
 11.1268 +                    {
 11.1269 +                        this.GoToNextStep();
 11.1270 +                    }),
 11.1271 +
 11.1272 +                    // Cancel button
 11.1273 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1274 +                    IsCancelButtonVisible = true,
 11.1275 +                    CancelButtonClick = new Action(() =>
 11.1276 +                    {
 11.1277 +                        this.CancelWizard();
 11.1278 +                    }),
 11.1279 +
 11.1280 +                    // Subtitle area
 11.1281 +                    SubtitleText = null
 11.1282 +                });
 11.1283 +
 11.1284 +                // Step 7
 11.1285 +                states.Add(new WizardState
 11.1286 +                {
 11.1287 +                    // Step
 11.1288 +                    Step = Steps.Step7,
 11.1289 +
 11.1290 +                    // Title text
 11.1291 +                    TitleText = Properties.Resources.KeySyncWizard_PGPStep7ExplanationText,
 11.1292 +
 11.1293 +                    // Central area
 11.1294 +                    AreTrustwordsVisible = false,
 11.1295 +                    IsUserTextVisible = true,
 11.1296 +                    UserText = this.UserName,
 11.1297 +
 11.1298 +                    // Back button
 11.1299 +                    IsBackButtonVisible = true,
 11.1300 +                    BackButtonClick = new Action(() =>
 11.1301 +                    {
 11.1302 +                        this.GoToPreviousStep();
 11.1303 +                    }),
 11.1304 +
 11.1305 +                    // Accept button
 11.1306 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
 11.1307 +                    IsAcceptButtonVisible = true,
 11.1308 +                    AcceptButtonClick = new Action(() =>
 11.1309 +                    {
 11.1310 +                        this.GoToNextStep();
 11.1311 +                        this.ProcessReceivedSyncMessages();
 11.1312 +                    }),
 11.1313 +
 11.1314 +                    // Cancel button
 11.1315 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1316 +                    IsCancelButtonVisible = true,
 11.1317 +                    CancelButtonClick = new Action(() =>
 11.1318 +                    {
 11.1319 +                        this.CancelWizard();
 11.1320 +                    }),
 11.1321 +
 11.1322 +                    // Subtitle area
 11.1323 +                    SubtitleText = null
 11.1324 +                });
 11.1325 +
 11.1326 +                // Step 8
 11.1327 +                states.Add(new WizardState
 11.1328 +                {
 11.1329 +                    // Step
 11.1330 +                    Step = Steps.Step8,
 11.1331 +
 11.1332 +                    // Title text
 11.1333 +                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
 11.1334 +
 11.1335 +                    // Central area
 11.1336 +                    AreTrustwordsVisible = false,
 11.1337 +                    IsUserTextVisible = true,
 11.1338 +                    UserText = this.UserName,
 11.1339 +
 11.1340 +                    // Back button
 11.1341 +                    IsBackButtonVisible = true,
 11.1342 +                    BackButtonClick = new Action(() =>
 11.1343 +                    {
 11.1344 +                        this.GoToPreviousStep();
 11.1345 +                    }),
 11.1346 +
 11.1347 +                    // Accept button
 11.1348 +                    IsAcceptButtonVisible = false,
 11.1349 +
 11.1350 +                    // Cancel button
 11.1351 +                    CancelButtonText = Properties.Resources.Options_CancelText,
 11.1352 +                    IsCancelButtonVisible = true,
 11.1353 +                    CancelButtonClick = new Action(() =>
 11.1354 +                    {
 11.1355 +                        this.CancelWizard();
 11.1356 +                    }),
 11.1357 +
 11.1358 +                    // Subtitle area
 11.1359 +                    SubtitleText = null
 11.1360 +                });
 11.1361 +
 11.1362 +                // Success
 11.1363 +                states.Add(new WizardState
 11.1364 +                {
 11.1365 +                    // Step
 11.1366 +                    Step = Steps.Success,
 11.1367 +
 11.1368 +                    // Title text
 11.1369 +                    TitleText = Properties.Resources.KeySyncWizard_PGPSuccessExplanationText,
 11.1370 +
 11.1371 +                    // Central area
 11.1372 +                    AreTrustwordsVisible = false,
 11.1373 +                    IsUserTextVisible = true,
 11.1374 +                    UserText = this.UserName,
 11.1375 +
 11.1376 +                    // Back button
 11.1377 +                    IsBackButtonVisible = false,
 11.1378 +
 11.1379 +                    // Accept button
 11.1380 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
 11.1381 +                    IsAcceptButtonVisible = true,
 11.1382 +                    AcceptButtonClick = new Action(() =>
 11.1383 +                    {
 11.1384 +                        this.Close();
 11.1385 +                    }),
 11.1386 +
 11.1387 +                    // Cancel button
 11.1388 +                    IsCancelButtonVisible = false,
 11.1389 +
 11.1390 +                    // Subtitle area
 11.1391 +                    SubtitleText = null
 11.1392 +                });
 11.1393 +
 11.1394 +                // Error
 11.1395 +                states.Add(new WizardState
 11.1396 +                {
 11.1397 +                    // Step
 11.1398 +                    Step = Steps.Error,
 11.1399 +
 11.1400 +                    // Title text
 11.1401 +                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
 11.1402 +
 11.1403 +                    // Central area
 11.1404 +                    AreTrustwordsVisible = false,
 11.1405 +                    IsUserTextVisible = true,
 11.1406 +                    UserText = this.UserName,
 11.1407 +
 11.1408 +                    // Back button
 11.1409 +                    IsBackButtonVisible = false,
 11.1410 +
 11.1411 +                    // Accept button
 11.1412 +                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
 11.1413 +                    IsAcceptButtonVisible = true,
 11.1414 +                    AcceptButtonClick = new Action(() =>
 11.1415 +                    {
 11.1416 +                        this.CancelWizard();
 11.1417 +                    }),
 11.1418 +
 11.1419 +                    // Cancel button
 11.1420 +                    IsCancelButtonVisible = false,
 11.1421 +
 11.1422 +                    // Subtitle area
 11.1423 +                    SubtitleText = null
 11.1424 +                });
 11.1425 +            }
 11.1426 +            catch (Exception ex)
 11.1427 +            {
 11.1428 +                states = null;
 11.1429 +                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
 11.1430 +            }
 11.1431 +
 11.1432 +            return states;
 11.1433 +        }
 11.1434 +
 11.1435 +        /// <summary>
 11.1436          /// Navigates to the last step of the wizard.
 11.1437          /// </summary>
 11.1438          /// <param name="success">Whether or not the wizard has been completed successfully.</param>
 11.1439          private void GoToLastStep(bool success)
 11.1440          {
 11.1441              // Go to last step
 11.1442 -            this.State = WizardState.Step4;
 11.1443 -            this.Success = success;
 11.1444 +            this.Step = success ? Steps.Success : Steps.Error;
 11.1445  
 11.1446 -            // Update content
 11.1447 -            this.UpdateContent();
 11.1448 +            // Update wording and state
 11.1449 +            var lastState = this.states.Find(a => a.Step == this.Step);
 11.1450 +            if (this.IsInitiator)
 11.1451 +            {
 11.1452 +                if (this.SetImportedKeyAsDefault)
 11.1453 +                {
 11.1454 +                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault;
 11.1455 +                }
 11.1456 +                else
 11.1457 +                {
 11.1458 +                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
 11.1459 +                }
 11.1460 +            }
 11.1461 +            else
 11.1462 +            {
 11.1463 +                if (this.privateKeyImported)
 11.1464 +                {
 11.1465 +                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
 11.1466 +                }
 11.1467 +                else
 11.1468 +                {
 11.1469 +                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport;
 11.1470 +                }
 11.1471 +            }
 11.1472 +
 11.1473 +            // Apply state
 11.1474 +            this.CurrentState = lastState;
 11.1475  
 11.1476              Log.Verbose("GoToLastStep: Process finished. Success is " + success.ToString());
 11.1477          }
 11.1478 @@ -584,26 +1324,42 @@
 11.1479          private void GoToNextStep()
 11.1480          {
 11.1481              // Go to next step
 11.1482 -            this.State++;
 11.1483 +            this.Step++;
 11.1484  
 11.1485 -            // Update content
 11.1486 -            this.UpdateContent();
 11.1487 +            // Set current state
 11.1488 +            this.CurrentState = states.Find(a => a.Step == this.Step);
 11.1489  
 11.1490 -            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(WizardState), this.State));
 11.1491 +            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
 11.1492 +        }
 11.1493 +
 11.1494 +        /// <summary>
 11.1495 +        /// Navigates to the previous state of the wizard.
 11.1496 +        /// </summary>
 11.1497 +        private void GoToPreviousStep()
 11.1498 +        {
 11.1499 +            // Go to next step
 11.1500 +            this.Step--;
 11.1501 +
 11.1502 +            // Set current state
 11.1503 +            this.CurrentState = states.Find(a => a.Step == this.Step);
 11.1504 +
 11.1505 +            Log.Verbose("GoToPreviousStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
 11.1506          }
 11.1507  
 11.1508          /// <summary>
 11.1509          /// Initializes the wizard.
 11.1510          /// </summary>
 11.1511 -        private void InitializeWizard(WizardType type,
 11.1512 +        private void InitializeWizard(bool isInitiator,
 11.1513 +                                      WizardType type,
 11.1514                                        PEPIdentity myself,
 11.1515                                        string partnerFpr)
 11.1516          {
 11.1517              // Set initial state
 11.1518              this.DataContext = this;
 11.1519              this.Myself = myself;
 11.1520 -            this.State = WizardState.Step1;
 11.1521 +            this.Step = Steps.Step1;
 11.1522              this.Type = type;
 11.1523 +            this.IsInitiator = isInitiator;
 11.1524  
 11.1525              // If own identity is null, get default account
 11.1526              if (this.Myself == null)
 11.1527 @@ -696,8 +1452,39 @@
 11.1528                  this.Partner.Fingerprint = partnerFpr;
 11.1529              }
 11.1530  
 11.1531 -            // Update dialog content
 11.1532 -            this.UpdateContent();
 11.1533 +            // Define states
 11.1534 +            this.states = (this.Type == WizardType.pEp) ? this.CreatePEPWizardStates() : this.CreatePGPWizardStates();
 11.1535 +
 11.1536 +            // Set current state
 11.1537 +            this.CurrentState = states?.Find(a => a.Step == Steps.Step1);
 11.1538 +        }
 11.1539 +
 11.1540 +        /// <summary>
 11.1541 +        /// Runs through all received sync messages.
 11.1542 +        /// </summary>
 11.1543 +        private void ProcessReceivedSyncMessages()
 11.1544 +        {
 11.1545 +            lock (mutexReceivedSyncMessages)
 11.1546 +            {
 11.1547 +                if (this.receivedSyncMessages != null)
 11.1548 +                {
 11.1549 +                    foreach (var message in this.receivedSyncMessages)
 11.1550 +                    {
 11.1551 +                        try
 11.1552 +                        {
 11.1553 +                            Task.Factory.StartNew(new Action(() =>
 11.1554 +                            {
 11.1555 +                                MsgProcessor msgProcessor = new MsgProcessor();
 11.1556 +                                msgProcessor.Decrypt(message);
 11.1557 +                            }));
 11.1558 +                        }
 11.1559 +                        catch (Exception ex)
 11.1560 +                        {
 11.1561 +                            Log.Error("ProcessReceivedSyncMessages: Error processing sync message. " + ex.ToString());
 11.1562 +                        }
 11.1563 +                    }
 11.1564 +                }
 11.1565 +            }
 11.1566          }
 11.1567  
 11.1568          /// <summary>
 11.1569 @@ -711,93 +1498,117 @@
 11.1570              {
 11.1571                  try
 11.1572                  {
 11.1573 -                    // If we have no partner at this point, use a copy of myself
 11.1574 -                    if (this.Partner == null)
 11.1575 +                    // Start sending in background
 11.1576 +                    Task.Factory.StartNew(new Action(() =>
 11.1577                      {
 11.1578 -                        this.Partner = this.Myself.Copy();
 11.1579 -                        Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
 11.1580 -                    }
 11.1581 +                        // If we have no partner at this point, use a copy of myself
 11.1582 +                        if (this.Partner == null)
 11.1583 +                        {
 11.1584 +                            this.Partner = this.Myself.Copy();
 11.1585 +                            this.Partner.Fingerprint = null;
 11.1586 +                            Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
 11.1587 +                        }
 11.1588  
 11.1589 -                    // Create basic message
 11.1590 -                    bool processMessage = true;
 11.1591 -                    PEPMessage message = new PEPMessage
 11.1592 -                    {
 11.1593 -                        From = this.Myself,
 11.1594 -                        ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
 11.1595 -                        LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
 11.1596 -                        AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
 11.1597 -                        Direction = pEpMsgDirection.pEpDirOutgoing,
 11.1598 -                        ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
 11.1599 -                        KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
 11.1600 -                    };
 11.1601 -                    message.To.Add(this.Partner);
 11.1602 +                        // Create basic message
 11.1603 +                        bool processMessage = true;
 11.1604 +                        PEPMessage message = new PEPMessage
 11.1605 +                        {
 11.1606 +                            From = this.Myself,
 11.1607 +                            ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
 11.1608 +                            LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
 11.1609 +                            AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
 11.1610 +                            Direction = pEpMsgDirection.pEpDirOutgoing,
 11.1611 +                            ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
 11.1612 +                            KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
 11.1613 +                        };
 11.1614 +                        message.To.Add(this.Partner);
 11.1615  
 11.1616 -                    Log.Verbose("SendSyncMessage: Basic message successfully created.");
 11.1617 +                        Log.Verbose("SendSyncMessage: Basic message successfully created.");
 11.1618  
 11.1619 -                    // If the message is the private key transport message, add own private key
 11.1620 -                    PEPMessage msg;
 11.1621 -                    if (messageType == MessageTypes.PrivateKeyMessage)
 11.1622 -                    {
 11.1623 +                        // If message type isn't InitialMessage, encrypt it accordingly
 11.1624 +                        PEPMessage msg;
 11.1625                          MsgProcessor msgProcessor = new MsgProcessor();
 11.1626 -                        if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
 11.1627 +                        if ((messageType == MessageTypes.PrivateKeyMessage) &&
 11.1628 +                            (this.ExportPrivateKey))
 11.1629                          {
 11.1630 -                            Log.Verbose("SendSyncMessage: Private key message successfully created.");
 11.1631 -                            message = msg;
 11.1632 -                            processMessage = false;
 11.1633 +                            // Encrypt and add private key
 11.1634 +                            if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
 11.1635 +                            {
 11.1636 +                                Log.Verbose("SendSyncMessage: Private key message successfully created.");
 11.1637 +                                message = msg;
 11.1638 +                                processMessage = false;
 11.1639 +                            }
 11.1640 +                            else
 11.1641 +                            {
 11.1642 +                                Log.Error("SendSyncMessage: Error encrypting private key message.");
 11.1643 +                                message = null;
 11.1644 +                            }
 11.1645 +                        }
 11.1646 +                        else if (((messageType == MessageTypes.PrivateKeyMessage) &&
 11.1647 +                                  (this.ExportPrivateKey == false)) ||
 11.1648 +                                 (messageType == MessageTypes.PublicKeyMessage))
 11.1649 +                        {
 11.1650 +                            // Encrypt using partner fpr as extra key
 11.1651 +                            if (msgProcessor.Encrypt(message, new string[] { this.Partner.Fingerprint }, out msg))
 11.1652 +                            {
 11.1653 +                                Log.Verbose("SendSyncMessage: Public key message successfully created.");
 11.1654 +                                message = msg;
 11.1655 +                                processMessage = false;
 11.1656 +                            }
 11.1657 +                            else
 11.1658 +                            {
 11.1659 +                                Log.Error("SendSyncMessage: Error encrypting public key message.");
 11.1660 +                                message = null;
 11.1661 +                            }
 11.1662 +                        }
 11.1663 +
 11.1664 +                        // If we have a message, send it
 11.1665 +                        if (message != null)
 11.1666 +                        {
 11.1667 +                            Log.Verbose("SendSyncMessage: Sending message...");
 11.1668 +
 11.1669 +                            // Disable passive mode if needed
 11.1670 +                            bool reenablePassiveMode = false;
 11.1671 +                            if ((messageType == MessageTypes.InitialMessage) &&
 11.1672 +                                (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
 11.1673 +                            {
 11.1674 +                                try
 11.1675 +                                {
 11.1676 +                                    ThisAddIn.PEPEngine.PassiveMode(false);
 11.1677 +                                    reenablePassiveMode = true;
 11.1678 +                                    Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
 11.1679 +                                }
 11.1680 +                                catch (Exception ex)
 11.1681 +                                {
 11.1682 +                                    Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
 11.1683 +                                }
 11.1684 +                            }
 11.1685 +
 11.1686 +                            // Send message
 11.1687 +                            Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
 11.1688 +
 11.1689 +                            // Log that message has been sent
 11.1690 +                            this.sentMessages?.Add(messageType);
 11.1691 +
 11.1692 +                            // Reenable passive mode if needed
 11.1693 +                            if (reenablePassiveMode)
 11.1694 +                            {
 11.1695 +                                try
 11.1696 +                                {
 11.1697 +                                    ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
 11.1698 +                                    Log.Verbose("SendSyncMessage: Passive mode reenabled.");
 11.1699 +                                }
 11.1700 +                                catch (Exception ex)
 11.1701 +                                {
 11.1702 +                                    Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
 11.1703 +                                }
 11.1704 +                            }
 11.1705                          }
 11.1706                          else
 11.1707                          {
 11.1708 -                            Log.Error("SendSyncMessage: Error encrypting private key message.");
 11.1709 -                            message = null;
 11.1710 +                            Log.Error("SendSyncMessage: Myself identity is null.");
 11.1711                          }
 11.1712 -                    }
 11.1713 -
 11.1714 -                    // If we have a message, send it
 11.1715 -                    if (message != null)
 11.1716 -                    {
 11.1717 -                        Log.Verbose("SendSyncMessage: Sending message...");
 11.1718 -
 11.1719 -                        // Disable passive mode if needed
 11.1720 -                        bool reenablePassiveMode = false;
 11.1721 -                        if ((messageType == MessageTypes.InitialMessage) &&
 11.1722 -                            (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
 11.1723 -                        {
 11.1724 -                            try
 11.1725 -                            {
 11.1726 -                                ThisAddIn.PEPEngine.PassiveMode(false);
 11.1727 -                                reenablePassiveMode = true;
 11.1728 -                                Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
 11.1729 -                            }
 11.1730 -                            catch (Exception ex)
 11.1731 -                            {
 11.1732 -                                Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
 11.1733 -                            }
 11.1734 -                        }
 11.1735 -
 11.1736 -                        // Send message
 11.1737 -                        Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
 11.1738 -
 11.1739 -                        // Log that message has been sent
 11.1740 -                        this.sentMessages?.Add(messageType);
 11.1741 -
 11.1742 -                        // Reenable passive mode if needed
 11.1743 -                        if (reenablePassiveMode)
 11.1744 -                        {
 11.1745 -                            try
 11.1746 -                            {
 11.1747 -                                ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
 11.1748 -                                Log.Verbose("SendSyncMessage: Passive mode reenabled.");
 11.1749 -                            }
 11.1750 -                            catch (Exception ex)
 11.1751 -                            {
 11.1752 -                                Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
 11.1753 -                            }
 11.1754 -                        }
 11.1755 -                    }
 11.1756 -                    else
 11.1757 -                    {
 11.1758 -                        Log.Error("SendSyncMessage: Myself identity is null.");
 11.1759 -                    }
 11.1760 +                    }), TaskCreationOptions.LongRunning);
 11.1761                  }
 11.1762                  catch (Exception ex)
 11.1763                  {
 11.1764 @@ -807,7 +1618,7 @@
 11.1765          }
 11.1766  
 11.1767          /// <summary>
 11.1768 -        /// Trusts the communication partner key (makes the channel green)
 11.1769 +        /// Trusts the communication partner key (makes the channel green).
 11.1770          /// </summary>
 11.1771          private void TrustKey()
 11.1772          {
 11.1773 @@ -815,31 +1626,28 @@
 11.1774              {
 11.1775                  try
 11.1776                  {
 11.1777 -                    Log.Verbose("TrustKey: Trusting partner key...");
 11.1778 +                    // Run in background
 11.1779 +                    Task.Factory.StartNew(new Action(() =>
 11.1780 +                    {
 11.1781 +                        Log.Verbose("TrustKey: Trusting partner key...");
 11.1782  
 11.1783 -                    this._Partner = this.Items[0].Partner;
 11.1784 -                    pEpIdentity partner = this._Partner.ToCOMType();
 11.1785 -                    ThisAddIn.PEPEngine.TrustPersonalKey(partner);
 11.1786 +                        // Trust the partner's key
 11.1787 +                        this._Partner = this.Items[0].Partner;
 11.1788 +                        pEpIdentity partner = this._Partner.ToCOMType();
 11.1789 +                        ThisAddIn.PEPEngine.TrustPersonalKey(partner);
 11.1790  
 11.1791 -                    // If Trustwords are being accepted after having received
 11.1792 -                    // the private key, finish process.
 11.1793 -                    if (this.State == WizardState.Step3)
 11.1794 +                        // Process messages that might have been received
 11.1795 +                        this.ProcessReceivedSyncMessages();
 11.1796 +
 11.1797 +                    }), TaskCreationOptions.LongRunning).ContinueWith(new Action<Task>((result) =>
 11.1798                      {
 11.1799 -                        Log.Verbose("TrustKey: Private key already received. Completing wizard.");
 11.1800 -                        this.CompleteWizard();
 11.1801 -                    }
 11.1802 -                    else
 11.1803 -                    {
 11.1804 -                        Log.Verbose("TrustKey: No private key received yet. Going to next step.");
 11.1805 -                        this.GoToNextStep();
 11.1806 -                    }
 11.1807 -
 11.1808 -                    // In pEp sync mode, send private key to partner
 11.1809 -                    if (this.Type == WizardType.pEp)
 11.1810 -                    {
 11.1811 -                        Log.Verbose("TrustKey: Sending private key to partner.");
 11.1812 -                        this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
 11.1813 -                    }
 11.1814 +                        // In pEp sync mode, send private key message to partner
 11.1815 +                        if (this.Type == WizardType.pEp)
 11.1816 +                        {
 11.1817 +                            Log.Verbose("TrustKey: Sending private key to partner.");
 11.1818 +                            this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
 11.1819 +                        }
 11.1820 +                    }));
 11.1821                  }
 11.1822                  catch (Exception ex)
 11.1823                  {
 11.1824 @@ -855,108 +1663,42 @@
 11.1825          }
 11.1826  
 11.1827          /// <summary>
 11.1828 -        /// Updates the dialog content according to its current state.
 11.1829 -        /// </summary>
 11.1830 -        private void UpdateContent()
 11.1831 -        {
 11.1832 -            // Set title
 11.1833 -            if (string.IsNullOrEmpty(this._TitleText))
 11.1834 -            {
 11.1835 -                this.TitleText = this.TitleText = this.Myself?.Address;
 11.1836 -            }
 11.1837 -
 11.1838 -            // Set content according to state
 11.1839 -            switch (this.State)
 11.1840 -            {
 11.1841 -                case WizardState.Step1:
 11.1842 -                    {
 11.1843 -                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
 11.1844 -                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step1PEPExplanationText : Properties.Resources.KeySyncWizard_Step1PGPExplanationText;
 11.1845 -                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_WaitingForResponseText : Properties.Resources.KeySyncWizard_Step1PGPSubtitleText;
 11.1846 -                    }
 11.1847 -                    break;
 11.1848 -                case WizardState.Step2:
 11.1849 -                    {
 11.1850 -                        this.NextButtonText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
 11.1851 -                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step2PEPExplanationText : Properties.Resources.KeySyncWizard_Step2PGPExplanationText;
 11.1852 -                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
 11.1853 -                    }
 11.1854 -                    break;
 11.1855 -                case WizardState.Step3:
 11.1856 -                    {
 11.1857 -                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
 11.1858 -                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step3PEPExplanationText : Properties.Resources.KeySyncWizard_Step3PGPExplanationText;
 11.1859 -                        this.SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText;
 11.1860 -                    }
 11.1861 -                    break;
 11.1862 -                case WizardState.Step4:
 11.1863 -                    {
 11.1864 -                        this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
 11.1865 -
 11.1866 -                        if (this.Success)
 11.1867 -                        {
 11.1868 -                            this.SubtitleText = Properties.Resources.KeySyncWizard_SuccessText;
 11.1869 -
 11.1870 -                            switch (this.Type)
 11.1871 -                            {
 11.1872 -                                case WizardType.PGP:
 11.1873 -                                    {
 11.1874 -                                        this.ExplanationText = Properties.Resources.KeySyncWizard_Step4SuccessExplanationText;
 11.1875 -                                    }
 11.1876 -                                    break;
 11.1877 -                                case WizardType.pEp:
 11.1878 -                                    {
 11.1879 -                                        if (this.isInitiator)
 11.1880 -                                        {
 11.1881 -                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessInitiatorExplanationText;
 11.1882 -                                        }
 11.1883 -                                        else
 11.1884 -                                        {
 11.1885 -                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText;
 11.1886 -                                        }
 11.1887 -                                    }
 11.1888 -                                    break;
 11.1889 -                                case WizardType.Undefined:
 11.1890 -                                default:
 11.1891 -                                    {
 11.1892 -                                        this.ExplanationText = string.Empty;
 11.1893 -                                    }
 11.1894 -                                    break;
 11.1895 -                            }
 11.1896 -                        }
 11.1897 -                        else
 11.1898 -                        {
 11.1899 -                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4ErrorExplanationText;
 11.1900 -                            this.SubtitleText = Properties.Resources.KeySyncWizard_ErrorText;
 11.1901 -                        }
 11.1902 -                    }
 11.1903 -                    break;
 11.1904 -                case WizardState.Undefined:
 11.1905 -                default:
 11.1906 -                    this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
 11.1907 -                    this.ExplanationText = string.Empty;
 11.1908 -                    this.SubtitleText = string.Empty;
 11.1909 -                    break;
 11.1910 -            }
 11.1911 -        }
 11.1912 -
 11.1913 -        /// <summary>
 11.1914          /// Resets the object to its defaults.
 11.1915          /// </summary>
 11.1916          public void Reset()
 11.1917          {
 11.1918 -            this._ExplanationText = null;
 11.1919 +            this._CurrentState = new WizardState();
 11.1920 +            this._ExportPrivateKey = true;
 11.1921 +            this._IsInitiator = false;
 11.1922              this._Items = new ObservableCollection<HandshakeItem>();
 11.1923              this._Myself = null;
 11.1924 -            this._NextButtonText = null;
 11.1925              this._Partner = null;
 11.1926 -            this._State = WizardState.Undefined;
 11.1927 -            this._SubtitleText = null;
 11.1928 -            this._Success = false;
 11.1929 +            this._Step = Steps.Undefined;
 11.1930 +            this._SetImportedKeyAsDefault = true;
 11.1931              this._Type = WizardType.Undefined;
 11.1932 -            this._TitleText = null;
 11.1933          }
 11.1934  
 11.1935          #endregion
 11.1936 +
 11.1937 +        /// <summary>
 11.1938 +        /// Container to define a wizard state.
 11.1939 +        /// </summary>
 11.1940 +        public class WizardState
 11.1941 +        {
 11.1942 +            public Action                   AcceptButtonClick           { get; set; }   =   null;
 11.1943 +            public string                   AcceptButtonText            { get; set; }   =   null;
 11.1944 +            public bool                     AreTrustwordsVisible        { get; set; }   =   false;
 11.1945 +            public Action                   BackButtonClick             { get; set; }   =   null;
 11.1946 +            public Action                   CancelButtonClick           { get; set; }   =   null;
 11.1947 +            public string                   CancelButtonText            { get; set; }   =   null;
 11.1948 +            public bool                     IsAcceptButtonVisible       { get; set; }   =   true;
 11.1949 +            public bool                     IsBackButtonVisible         { get; set; }   =   false;
 11.1950 +            public bool                     IsCancelButtonVisible       { get; set; }   =   true;
 11.1951 +            public bool                     IsUserTextVisible           { get; set; }   =   true;
 11.1952 +            public KeySyncWizard.Steps      Step                        { get; set; }   =   Steps.Undefined;
 11.1953 +            public string                   SubtitleText                { get; set; }   =   null;
 11.1954 +            public string                   TitleText                   { get; set; }   =   null;
 11.1955 +            public string                   UserText                    { get; set; }   =   null;
 11.1956 +        }
 11.1957      }
 11.1958  }
    12.1 --- a/UI/ValueConverters.cs	Thu May 10 15:04:25 2018 +0200
    12.2 +++ b/UI/ValueConverters.cs	Thu May 17 11:21:56 2018 +0200
    12.3 @@ -276,61 +276,6 @@
    12.4      }
    12.5  
    12.6      /// <summary>
    12.7 -    /// Returns a bool value indicating if the wizard state matches any of the given parameter.
    12.8 -    /// </summary>
    12.9 -    public class IsWizardStateConverter : IValueConverter
   12.10 -    {
   12.11 -        public object Convert(object value,
   12.12 -                              Type targetType,
   12.13 -                              object parameter,
   12.14 -                              CultureInfo culture)
   12.15 -        {
   12.16 -            bool success;
   12.17 -            KeySyncWizard.WizardState param;
   12.18 -
   12.19 -            if ((value is KeySyncWizard.WizardState) &&
   12.20 -                (parameter is string))
   12.21 -            {
   12.22 -                string[] parameters = (parameter as string).Split('|');
   12.23 -
   12.24 -                if (parameters?.Length > 0)
   12.25 -                {
   12.26 -                    foreach (var p in parameters)
   12.27 -                    {
   12.28 -                        success = Enum.TryParse(p, out param);
   12.29 -
   12.30 -                        if (success)
   12.31 -                        {
   12.32 -                            if (((KeySyncWizard.WizardState)value) == param)
   12.33 -                            {
   12.34 -                                return true;
   12.35 -                            }
   12.36 -                        }
   12.37 -                        else
   12.38 -                        {
   12.39 -                            throw new ArgumentException();
   12.40 -                        }
   12.41 -                    }
   12.42 -                }
   12.43 -
   12.44 -                return false;
   12.45 -            }
   12.46 -            else
   12.47 -            {
   12.48 -                throw new ArgumentException();
   12.49 -            }
   12.50 -        }
   12.51 -
   12.52 -        public object ConvertBack(object value,
   12.53 -                                  Type targetType,
   12.54 -                                  object parameter,
   12.55 -                                  CultureInfo culture)
   12.56 -        {
   12.57 -            throw new NotImplementedException();
   12.58 -        }
   12.59 -    }
   12.60 -
   12.61 -    /// <summary>
   12.62      /// Converter to check if a list is empty.
   12.63      /// </summary>
   12.64      public class IsListEmptyConverter : IValueConverter
   12.65 @@ -530,6 +475,38 @@
   12.66      }
   12.67  
   12.68      /// <summary>
   12.69 +    /// Returns true if the Wizard is in the given state.
   12.70 +    /// </summary>
   12.71 +    public class IsWizardTypeConverter : IValueConverter
   12.72 +    {
   12.73 +        public object Convert(object value,
   12.74 +                              Type targetType,
   12.75 +                              object parameter,
   12.76 +                              CultureInfo culture)
   12.77 +        {
   12.78 +            string val = null;
   12.79 +            string param = parameter as string;
   12.80 +
   12.81 +            try
   12.82 +            {
   12.83 +                val = Enum.GetName(typeof(KeySyncWizard.WizardType), value);
   12.84 +            }
   12.85 +            catch
   12.86 +            {
   12.87 +                val = null;
   12.88 +            }
   12.89 +
   12.90 +            return (param?.Equals(val) == true);
   12.91 +        }
   12.92 +
   12.93 +        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   12.94 +        {
   12.95 +            throw new NotImplementedException();
   12.96 +        }
   12.97 +    }
   12.98 +
   12.99 +
  12.100 +    /// <summary>
  12.101      /// Converter to AND several bool values and convert to Visibility.
  12.102      /// </summary>
  12.103      public class MultiBooleanToVisibilityConverter : IMultiValueConverter