public async Task TestForEach()
        {
            using (FileSystemState state = FileSystemState.Create(Resolve.WorkFolder.FileInfo.FileItemInfo("mystate.txt")))
            {
                ActiveFile activeFile;
                activeFile = new ActiveFile(New <IDataStore>(_encrypted1AxxPath), New <IDataStore>(_decrypted1TxtPath), new LogOnIdentity("passphrase1"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);
                state.Add(activeFile);
                activeFile = new ActiveFile(New <IDataStore>(_encrypted2AxxPath), New <IDataStore>(_decrypted2TxtPath), new LogOnIdentity("passphrase2"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);
                state.Add(activeFile);
                activeFile = new ActiveFile(New <IDataStore>(_encrypted3AxxPath), New <IDataStore>(_decrypted3TxtPath), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().CryptoId);
                state.Add(activeFile);

                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(3), "There should be three.");
                int i = 0;
                await state.ForEach((ActiveFile activeFileArgument) =>
                {
                    ++i;
                    return(Task.FromResult(activeFileArgument));
                });

                Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files.");

                i = 0;
                await state.ForEach((ActiveFile activeFileArgument) =>
                {
                    ++i;
                    return(Task.FromResult(new ActiveFile(activeFileArgument, activeFile.Status | ActiveFileStatus.Error)));
                });

                Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files.");
            }
        }
Example #2
0
        private static ActiveFile TryDecryptToActiveFile(IDataStore encryptedDataStore, IEnumerable <LogOnIdentity> identities)
        {
            ActiveFile activeFile = null;

            foreach (LogOnIdentity identity in identities)
            {
                if (Resolve.Log.IsInfoEnabled)
                {
                    Resolve.Log.LogInfo("Decrypting '{0}'".InvariantFormat(encryptedDataStore.FullName));
                }
                using (FileLock encryptedLock = New <FileLocker>().Acquire(encryptedDataStore))
                {
                    using (IAxCryptDocument document = New <AxCryptFile>().Document(encryptedDataStore, identity, new ProgressContext()))
                    {
                        if (!document.PassphraseIsValid)
                        {
                            continue;
                        }

                        activeFile = DestinationActiveFileFromDocument(encryptedDataStore, activeFile?.DecryptedFileInfo?.Container, identity, document);
                        break;
                    }
                }
            }
            return(activeFile);
        }
        private static void UpdateListViewItem(ListViewItem item, ActiveFile activeFile)
        {
            OpenFileProperties openProperties = OpenFileProperties.Create(activeFile.EncryptedFileInfo);

            item.SubItems[nameof(ColumnName.EncryptedPath)].Text = activeFile.EncryptedFileInfo.FullName;
            item.SubItems[nameof(ColumnName.AccessedDate)].Text  = activeFile.Properties.LastActivityTimeUtc.ToLocalTime().ToString(CultureInfo.CurrentCulture);
            item.SubItems[nameof(ColumnName.AccessedDate)].Tag   = activeFile.Properties.LastActivityTimeUtc;
            item.SubItems[nameof(ColumnName.ModifiedDate)].Text  = activeFile.EncryptedFileInfo.LastWriteTimeUtc.ToLocalTime().ToString(CultureInfo.CurrentCulture);
            item.SubItems[nameof(ColumnName.ModifiedDate)].Tag   = activeFile.EncryptedFileInfo.LastWriteTimeUtc;

            LogOnIdentity decryptIdentity = ValidateActiveFileIdentity(activeFile.Identity);

            UpdateStatusDependentPropertiesOfListViewItem(item, activeFile, activeFile.EncryptedFileInfo.IsKeyShared(decryptIdentity));

            try
            {
                if (activeFile.Properties.CryptoId != Guid.Empty)
                {
                    item.SubItems[nameof(ColumnName.CryptoName)].Text = Resolve.CryptoFactory.Create(activeFile.Properties.CryptoId).Name;
                    if (activeFile.VisualState.HasFlag(ActiveFileVisualStates.LowEncryption))
                    {
                        item.SubItems[nameof(ColumnName.CryptoName)].ForeColor = Styling.WarningColor;
                    }
                }
            }
            catch (ArgumentException aex)
            {
                New <IReport>().Exception(aex);
                item.SubItems[nameof(ColumnName.CryptoName)].Text = Texts.UnknownCrypto;
            }
        }
Example #4
0
        private void UpdateRecentFilesListView(ActiveFile activeFile)
        {
            recentFilesListView.ListViewItemSorter = null;
            ListViewItem item = recentFilesListView.Items[activeFile.EncryptedFileInfo.FullName];

            if (item == null)
            {
                string text = Path.GetFileName(activeFile.DecryptedFileInfo.FullName);
                item      = recentFilesListView.Items.Add(text);
                item.Name = activeFile.EncryptedFileInfo.FullName;

                ListViewItem.ListViewSubItem dateColumn = item.SubItems.Add(String.Empty);
                dateColumn.Name = "Date"; //MLHIDE

                ListViewItem.ListViewSubItem encryptedPathColumn = item.SubItems.Add(String.Empty);
                encryptedPathColumn.Name = "EncryptedPath"; //MLHIDE
            }

            UpdateListViewItem(item, activeFile);
            recentFilesListView.ListViewItemSorter = _currentRecentFilesSorter;
            while (recentFilesListView.Items.Count > Settings.Default.MaxNumberRecentFiles)
            {
                recentFilesListView.Items.RemoveAt(recentFilesListView.Items.Count - 1);
            }
        }
Example #5
0
        public static void TestDecryptedActiveFiles()
        {
            using (FileSystemState state = new FileSystemState())
            {
                state.Load(OS.Current.FileInfo(_mystateXmlPath));

                ActiveFile decryptedFile1 = new ActiveFile(OS.Current.FileInfo(_encryptedAxxPath), OS.Current.FileInfo(_decryptedTxtPath), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null);
                state.Add(decryptedFile1);

                ActiveFile decryptedFile2 = new ActiveFile(OS.Current.FileInfo(_encrypted2AxxPath), OS.Current.FileInfo(_decrypted2TxtPath), new AesKey(), ActiveFileStatus.DecryptedIsPendingDelete, null);
                state.Add(decryptedFile2);

                ActiveFile notDecryptedFile = new ActiveFile(OS.Current.FileInfo(_encrypted3AxxPath), OS.Current.FileInfo(_decrypted3TxtPath), new AesKey(), ActiveFileStatus.NotDecrypted, null);
                state.Add(notDecryptedFile);

                ActiveFile errorFile = new ActiveFile(OS.Current.FileInfo(_encrypted4AxxPath), OS.Current.FileInfo(_decrypted4TxtPath), new AesKey(), ActiveFileStatus.Error, null);
                state.Add(errorFile);

                IList <ActiveFile> decryptedFiles = state.DecryptedActiveFiles;
                Assert.That(decryptedFiles.Count, Is.EqualTo(2), "There should be two decrypted files.");
                Assert.That(decryptedFiles.Contains(decryptedFile1), "A file marked as AssumedOpenAndDecrypted should be found.");
                Assert.That(decryptedFiles.Contains(decryptedFile2), "A file marked as DecryptedIsPendingDelete should be found.");
                Assert.That(decryptedFiles.Contains(notDecryptedFile), Is.Not.True, "A file marked as NotDecrypted should not be found.");
            }
        }
Example #6
0
        private static ActiveFile TryDecrypt(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFolderInfo, IEnumerable <AesKey> keys, ProgressContext progress)
        {
            ActiveFile destinationActiveFile = null;

            foreach (AesKey key in keys)
            {
                if (OS.Log.IsInfoEnabled)
                {
                    OS.Log.LogInfo("Decrypting '{0}'".InvariantFormat(sourceFileInfo.FullName));
                }
                using (FileLock sourceLock = FileLock.Lock(sourceFileInfo))
                {
                    using (AxCryptDocument document = AxCryptFile.Document(sourceFileInfo, key, new ProgressContext()))
                    {
                        if (!document.PassphraseIsValid)
                        {
                            continue;
                        }

                        destinationActiveFile = DecryptActiveFileDocument(sourceFileInfo, destinationFolderInfo, document, progress);
                        break;
                    }
                }
            }
            return(destinationActiveFile);
        }
        public static void TestDateComparer()
        {
            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2013, 01, 01);
            ActiveFile activeFile1a = new ActiveFile(New <IDataStore>((@"C:\encrypted1.axx")), New <IDataStore>(@"C:\decrypted1.txt"), new LogOnIdentity("activeFile1a"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().CryptoId);

            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2013, 01, 01);
            ActiveFile activeFile1b = new ActiveFile(New <IDataStore>((@"C:\encrypted2.axx")), New <IDataStore>(@"C:\decrypted2.txt"), new LogOnIdentity("activeFile1b"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            ActiveFileComparer comparer = ActiveFileComparer.DateComparer;

            Assert.That(comparer.ReverseSort, Is.False);

            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
            comparer.ReverseSort = true;
            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
            comparer.ReverseSort = false;

            ((FakeNow)New <INow>()).TimeFunction = () => new DateTime(2013, 01, 02);
            ActiveFile activeFile2 = new ActiveFile(New <IDataStore>((@"C:\encrypted3.axx")), New <IDataStore>(@"C:\decrypted3.txt"), new LogOnIdentity("activeFile2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.LessThan(0));
            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.GreaterThan(0));
            comparer.ReverseSort = true;
            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.GreaterThan(0));
            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.LessThan(0));
            comparer.ReverseSort = false;
        }
        public static void TestEncryptedNameComparer()
        {
            ActiveFile activeFile1a = new ActiveFile(New <IDataStore>((@"C:\encrypted1.axx")), New <IDataStore>(@"C:\decrypted1a.txt"), new LogOnIdentity("activeFile1a"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().CryptoId);
            ActiveFile activeFile1b = new ActiveFile(New <IDataStore>((@"C:\encrypted1.axx")), New <IDataStore>(@"C:\decrypted1b.txt"), new LogOnIdentity("activeFile1b"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().CryptoId);

            ActiveFileComparer comparer = ActiveFileComparer.EncryptedNameComparer;

            Assert.That(comparer.ReverseSort, Is.False);

            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
            comparer.ReverseSort = true;
            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
            comparer.ReverseSort = false;

            ActiveFile activeFile2 = new ActiveFile(New <IDataStore>((@"C:\encrypted2.axx")), New <IDataStore>(@"C:\decrypted1a.txt"), new LogOnIdentity("activeFile2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.LessThan(0));
            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.GreaterThan(0));
            comparer.ReverseSort = true;
            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.GreaterThan(0));
            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.LessThan(0));
            comparer.ReverseSort = false;
        }
Example #9
0
        public async Task TestCheckProcessExitedWhenExited()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            await New <KnownIdentities>().SetDefaultEncryptionIdentity(new LogOnIdentity(EmailAddress.Parse("*****@*****.**"), new Passphrase("test")));

            FakeLauncher fakeLauncher = new FakeLauncher();

            fakeLauncher.Launch(_decryptedFile1);
            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().CryptoId);

            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable);
            Resolve.FileSystemState.Add(activeFile, fakeLauncher);

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });
            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
            fakeLauncher.HasExited = true;
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_anAxxPath);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the process has exited.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The ActiveFile plain text should be deleted after the checking of active files because the launcher is no longer active.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.False, "The file should be shareable after checking of active files because the launcher is no longer active.");
        }
Example #10
0
        public async Task TestPurgeActiveFilesWhenFileIsLocked()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            IDataStore encryptedFileInfo = New <IDataStore>(_anAxxPath);
            IDataStore decryptedFileInfo = New <IDataStore>(_decryptedFile1);
            ActiveFile activeFile        = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            Resolve.FileSystemState.Add(activeFile);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            using (FileLock fileLock = New <FileLocker>().Acquire(decryptedFileInfo))
            {
                await Task.Run(() => New <ActiveFileAction>().PurgeActiveFiles(new ProgressContext()));
            }

            Assert.That(changedWasRaised, Is.False, "A changed event should not be raised because the decrypted file is locked.");
        }
Example #11
0
        public async Task TestCheckActiveFilesNotDecryptedAndDoesNotExist()
        {
            DateTime utcNow = New <INow>().Utc;

            FakeDataStore.AddFile(_anAxxPath, utcNow, utcNow, utcNow, new MemoryStream(Resources.helloworld_key_a_txt));
            FakeDataStore.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(New <IDataStore>(_anAxxPath), New <IDataStore>(_decryptedFile1), new LogOnIdentity("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().CryptoId);

            New <IDataStore>(_decryptedFile1).Delete();
            activeFile = new ActiveFile(activeFile, ActiveFileStatus.NotDecrypted);
            Resolve.FileSystemState.Add(activeFile);
            await Resolve.KnownIdentities.AddAsync(activeFile.Identity);

            bool changedWasRaised = false;

            Resolve.SessionNotify.AddCommand((SessionNotification notification) =>
            {
                changedWasRaised = notification.NotificationType == SessionNotificationType.ActiveFileChange;
                return(Constant.CompletedTask);
            });

            ((FakeNow)New <INow>()).TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            await New <ActiveFileAction>().CheckActiveFiles(new ProgressContext());

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because it's already deleted.");
        }
        private Task <FileOperationContext> VerifyAndAddActiveWorkAsync(IDataStore fullName, IProgressContext progress)
        {
            FileOperationsController operationsController = new FileOperationsController(progress);

            operationsController.QueryDecryptionPassphrase += HandleQueryDecryptionPassphraseEventAsync;

            operationsController.KnownKeyAdded = new AsyncDelegateAction <FileOperationEventArgs>(async(FileOperationEventArgs e) =>
            {
                if (!_fileSystemState.KnownPassphrases.Any(i => i.Thumbprint == e.LogOnIdentity.Passphrase.Thumbprint))
                {
                    _fileSystemState.KnownPassphrases.Add(e.LogOnIdentity.Passphrase);
                }
                await _knownIdentities.AddAsync(e.LogOnIdentity);
            });

            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
            {
                if (e.Status.ErrorStatus == ErrorStatus.Success)
                {
                    IDataStore encryptedInfo = New <IDataStore>(e.OpenFileFullName);
                    IDataStore decryptedInfo = New <IDataStore>(FileOperation.GetTemporaryDestinationName(e.SaveFileFullName));
                    ActiveFile activeFile    = new ActiveFile(encryptedInfo, decryptedInfo, e.LogOnIdentity, ActiveFileStatus.NotDecrypted, e.CryptoId);
                    _fileSystemState.Add(activeFile);
                }
            };

            return(operationsController.VerifyEncryptedAsync(fullName));
        }
Example #13
0
        public async Task TestFileContainedByActiveFilesButNotDecrypted()
        {
            IDataStore dataStore = New <IDataStore>(_helloWorldAxxPath);

            TypeMap.Register.New <ILauncher>(() => new FakeLauncher());

            IEnumerable <LogOnIdentity> keys = new LogOnIdentity[] { new LogOnIdentity("a") };

            FileOperation        fileOperation = new FileOperation(Resolve.FileSystemState, new SessionNotify());
            FileOperationContext status        = await fileOperation.OpenAndLaunchApplication(keys, dataStore, new ProgressContext());

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The launch should succeed.");

            IDataStore fileInfo = New <IDataStore>(_helloWorldAxxPath);
            ActiveFile destinationActiveFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);

            destinationActiveFile.DecryptedFileInfo.Delete();
            destinationActiveFile = new ActiveFile(destinationActiveFile, ActiveFileStatus.NotDecrypted);
            Resolve.FileSystemState.Add(destinationActiveFile);
            await Resolve.FileSystemState.Save();

            status = await fileOperation.OpenAndLaunchApplication(keys, dataStore, new ProgressContext());

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The launch should once again succeed.");
        }
        private void UpdateOneItem(Dictionary <string, int> currentFiles, ActiveFile file)
        {
            string       text = Path.GetFileName(file.DecryptedFileInfo.FullName);
            ListViewItem item = new ListViewItem(text);

            item.UseItemStyleForSubItems = false;
            item.Name = file.EncryptedFileInfo.FullName;

            ListViewItem.ListViewSubItem accessedDateColumn = item.SubItems.Add(String.Empty);
            accessedDateColumn.Name = nameof(ColumnName.AccessedDate);

            ListViewItem.ListViewSubItem encryptedPathColumn = item.SubItems.Add(String.Empty);
            encryptedPathColumn.Name = nameof(ColumnName.EncryptedPath);

            ListViewItem.ListViewSubItem modifiedDateColumn = item.SubItems.Add(String.Empty);
            modifiedDateColumn.Name = nameof(ColumnName.ModifiedDate);

            ListViewItem.ListViewSubItem cryptoNameColumn = item.SubItems.Add(String.Empty);
            cryptoNameColumn.Name = nameof(ColumnName.CryptoName);

            UpdateListViewItem(item, file);

            int i;

            if (!currentFiles.TryGetValue(item.Name, out i))
            {
                Items.Add(item);
                return;
            }

            if (!CompareRecentFileItem(item, Items[i]))
            {
                Items[i] = item;
            }
        }
        private static Task ChangeEncryptionAsync(IEnumerable <string> files, EncryptionParameters encryptionParameters)
        {
            return(Resolve.ParallelFileOperation.DoFilesAsync(files.Select(f => New <IDataStore>(f)),
                                                              async(IDataStore file, IProgressContext progress) =>
            {
                ActiveFile activeFile = New <FileSystemState>().FindActiveFileFromEncryptedPath(file.FullName);
                LogOnIdentity decryptIdentity = activeFile?.Identity ?? New <KnownIdentities>().DefaultEncryptionIdentity;

                await New <AxCryptFile>().ChangeEncryptionAsync(file, decryptIdentity, encryptionParameters, progress);

                if (activeFile != null)
                {
                    New <FileSystemState>().Add(new ActiveFile(activeFile, encryptionParameters.CryptoId, New <KnownIdentities>().DefaultEncryptionIdentity));
                    await New <FileSystemState>().Save();
                }

                return new FileOperationContext(file.FullName, ErrorStatus.Success);
            },
                                                              async(FileOperationContext foc) =>
            {
                if (foc.ErrorStatus != ErrorStatus.Success)
                {
                    New <IStatusChecker>().CheckStatusAndShowMessage(foc.ErrorStatus, foc.FullName, foc.InternalMessage);
                    return;
                }
                await Resolve.SessionNotify.NotifyAsync(new SessionNotification(SessionNotificationType.ActiveFileChange, files));
            }));
        }
        private Task <bool> WipeFileOperationAsync()
        {
            if (_eventArgs.Skip)
            {
                _eventArgs.Status = new FileOperationContext(String.Empty, ErrorStatus.Success);
                return(Constant.TrueTask);
            }

            ActiveFile activeFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(_eventArgs.SaveFileFullName);

            if (activeFile != null && activeFile.Status.HasFlag(ActiveFileStatus.AssumedOpenAndDecrypted))
            {
                _eventArgs.Status = new FileOperationContext(_eventArgs.OpenFileFullName, ErrorStatus.FileLocked);
                return(Constant.FalseTask);
            }

            _progress.NotifyLevelStart();
            try
            {
                using (FileLock wipeFileLock = New <FileLocker>().Acquire(New <IDataStore>(_eventArgs.SaveFileFullName)))
                {
                    New <AxCryptFile>().Wipe(wipeFileLock, _progress);
                }
            }
            finally
            {
                _progress.NotifyLevelFinished();
            }

            _eventArgs.Status = new FileOperationContext(String.Empty, ErrorStatus.Success);
            return(Constant.TrueTask);
        }
Example #17
0
        public void TestConstructor()
        {
            LogOnIdentity key = new LogOnIdentity("key");
            IDataStore    decryptedFileInfo = New <IDataStore>(_testTextPath);
            IDataStore    encryptedFileInfo = New <IDataStore>(_helloWorldAxxPath);

            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().CryptoId);

            decryptedFileInfo = activeFile.DecryptedFileInfo;
            Assert.That(decryptedFileInfo.IsAvailable, Is.True, "The file should exist in the fake file system.");
            Assert.That(decryptedFileInfo.FullName, Is.EqualTo(_testTextPath), "The file should be named as it was in the constructor");
            Assert.That(decryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(decryptedFileInfo.LastWriteTimeUtc), "When a LastWriteTime is not specified, the decrypted file should be used to determine the value.");
            ((FakeNow)New <INow>()).TimeFunction = (() => { return(DateTime.UtcNow.AddMinutes(1)); });

            ActiveFile otherFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);

            Assert.That(otherFile.Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted), "The status should be as given in the constructor.");
            Assert.That(otherFile.DecryptedFileInfo.FullName, Is.EqualTo(activeFile.DecryptedFileInfo.FullName), "This should be copied from the original instance.");
            Assert.That(otherFile.EncryptedFileInfo.FullName, Is.EqualTo(activeFile.EncryptedFileInfo.FullName), "This should be copied from the original instance.");
            Assert.That(otherFile.Identity, Is.EqualTo(activeFile.Identity), "This should be copied from the original instance.");
            Assert.That(otherFile.Properties.LastActivityTimeUtc, Is.GreaterThan(activeFile.Properties.LastActivityTimeUtc), "This should not be copied from the original instance, but should be a later time.");
            Assert.That(otherFile.ThumbprintMatch(activeFile.Identity.Passphrase), Is.True, "The thumbprints should match.");

            activeFile.DecryptedFileInfo.LastWriteTimeUtc = activeFile.DecryptedFileInfo.LastWriteTimeUtc.AddDays(1);
            otherFile = new ActiveFile(activeFile, New <INow>().Utc, ActiveFileStatus.AssumedOpenAndDecrypted);
            Assert.That(activeFile.IsModified, Is.True, "The original instance has not been encrypted since the last change.");
            Assert.That(otherFile.IsModified, Is.False, "The copy indicates that it has been encrypted and thus is not modified.");
        }
Example #18
0
        public void TestVisualStateHiEncryption()
        {
            ActiveFile    activeFile;
            LogOnIdentity key = new LogOnIdentity("key");

            activeFile = new ActiveFile(New <IDataStore>(@"C:\encrypted.axx"), New <IDataStore>(@"C:\decrypted.txt"), key, ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().CryptoId);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.EncryptedWithKnownKey));

            activeFile = new ActiveFile(activeFile);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.EncryptedWithoutKnownKey));

            activeFile = new ActiveFile(activeFile, ActiveFileStatus.DecryptedIsPendingDelete);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.DecryptedWithoutKnownKey));

            activeFile = new ActiveFile(activeFile, key);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.DecryptedWithKnownKey));

            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.DecryptedWithKnownKey));

            activeFile = new ActiveFile(activeFile);
            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualStates.DecryptedWithoutKnownKey));

            activeFile = new ActiveFile(activeFile, ActiveFileStatus.Error);
            Assert.Throws <InvalidOperationException>(() => { if (activeFile.VisualState == ActiveFileVisualStates.None)
                                                              {
                                                              }
                                                      });
        }
Example #19
0
        public static void TestPurgeActiveFilesWhenFileIsModified()
        {
            DateTime utcNow = OS.Current.UtcNow;

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_encryptedFile1);
            IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_decryptedFile1);
            ActiveFile       activeFile        = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, null);

            _fileSystemState.Add(activeFile);

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            DateTime utcLater = OS.Current.UtcNow;

            decryptedFileInfo.SetFileTimes(utcLater, utcLater, utcLater);

            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });

            _fileSystemState.PurgeActiveFiles(new ProgressContext());

            activeFile = _fileSystemState.FindEncryptedPath(_encryptedFile1);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the decrypted file is modified.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The NotShareable not withstanding, the purge should have updated the file and removed the decrypted file.");
        }
        private void InitializePropertyValues()
        {
            WatchedFoldersEnabled  = false;
            WatchedFolders         = new string[0];
            DragAndDropFiles       = new string[0];
            RecentFiles            = new ActiveFile[0];
            SelectedRecentFiles    = new string[0];
            SelectedWatchedFolders = new string[0];
            DecryptedFiles         = new ActiveFile[0];
            DebugMode               = _userSettings.DebugMode;
            FolderOperationMode     = _userSettings.FolderOperationMode;
            DownloadVersion         = DownloadVersion.Empty;
            VersionUpdateStatus     = DownloadVersion.CalculateStatus(New <IVersion>().Current, New <INow>().Utc, _userSettings.LastUpdateCheckUtc);
            License                 = New <LicensePolicy>().Capabilities;
            EncryptionUpgradeMode   = _userSettings.EncryptionUpgradeMode;
            AddWatchedFolders       = new AsyncDelegateAction <IEnumerable <string> >((folders) => AddWatchedFoldersActionAsync(folders), (folders) => Task.FromResult(LoggedOn));
            RemoveRecentFiles       = new AsyncDelegateAction <IEnumerable <string> >((files) => RemoveRecentFilesAction(files));
            EncryptPendingFiles     = new AsyncDelegateAction <object>((parameter) => EncryptPendingFilesAction());
            ClearPassphraseMemory   = new AsyncDelegateAction <object>((parameter) => ClearPassphraseMemoryAction());
            DecryptWatchedFolders   = new AsyncDelegateAction <IEnumerable <string> >((folders) => DecryptWatchedFoldersAction(folders), (folders) => Task.FromResult(LoggedOn));
            OpenSelectedFolder      = new DelegateAction <string>((folder) => OpenSelectedFolderAction(folder));
            AxCryptUpdateCheck      = new AsyncDelegateAction <DateTime>((utc) => AxCryptUpdateCheckAction(utc));
            LicenseUpdate           = new DelegateAction <object>((o) => License = New <LicensePolicy>().Capabilities);
            RemoveWatchedFolders    = new AsyncDelegateAction <IEnumerable <string> >((folders) => RemoveWatchedFoldersAction(folders), (folders) => Task.FromResult(LoggedOn));
            WarnIfAnyDecryptedFiles = new AsyncDelegateAction <object>((o) => WarnIfAnyDecryptedFilesActionAsync());

            DecryptFileEnabled   = true;
            OpenEncryptedEnabled = true;
            RandomRenameEnabled  = true;
        }
Example #21
0
        public static void TestCheckProcessExitedWhenExited()
        {
            DateTime utcNow = OS.Current.UtcNow;

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            FakeLauncher fakeLauncher = new FakeLauncher(_decryptedFile1);
            ActiveFile   activeFile   = new ActiveFile(OS.Current.FileInfo(_encryptedFile1), OS.Current.FileInfo(_decryptedFile1), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, fakeLauncher);

            _fileSystemState.Add(activeFile);

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });
            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
            fakeLauncher.HasExited = true;
            _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());

            activeFile = _fileSystemState.FindEncryptedPath(_encryptedFile1);
            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the process has exited.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The ActiveFile plain text should be deleted after the checking of active files because the launcher is no longer active.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.False, "The file should be shareable after checking of active files because the launcher is no longer active.");
        }
Example #22
0
        public static void TestPurgeActiveFilesWhenFileIsLocked()
        {
            DateTime utcNow = OS.Current.UtcNow;

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            IRuntimeFileInfo encryptedFileInfo = OS.Current.FileInfo(_encryptedFile1);
            IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_decryptedFile1);
            ActiveFile       activeFile        = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null);

            _fileSystemState.Add(activeFile);

            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });

            using (FileLock fileLock = FileLock.Lock(decryptedFileInfo))
            {
                _fileSystemState.PurgeActiveFiles(new ProgressContext());
            }

            Assert.That(changedWasRaised, Is.False, "A changed event should not be raised because the decrypted file is locked.");
        }
Example #23
0
        public static void TestCheckActiveFilesNotDecryptedAndDoesNotExist()
        {
            DateTime utcNow = OS.Current.UtcNow;

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedFile1), OS.Current.FileInfo(_decryptedFile1), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null);

            OS.Current.FileInfo(_decryptedFile1).Delete();
            activeFile = new ActiveFile(activeFile, ActiveFileStatus.NotDecrypted, null);
            _fileSystemState.Add(activeFile);

            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());

            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because it's already deleted.");
        }
Example #24
0
        public static void TestCheckActiveFilesNoDeleteWhenNotDesktopWindows()
        {
            DateTime utcNow = OS.Current.UtcNow;

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);

            ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedFile1), OS.Current.FileInfo(_decryptedFile1), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null);

            _fileSystemState.Add(activeFile);

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });

            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.Unknown;
            _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
            Assert.That(changedWasRaised, Is.False, "No change should be raised when the file is not modified and not Desktop Windows.");
            activeFile = _fileSystemState.FindEncryptedPath(_encryptedFile1);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "Nothing should happen with the file when not running as Desktop Windows.");

            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
            changedWasRaised = false;
            _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
            Assert.That(changedWasRaised, Is.True, "Since the file should be deleted because running as Desktop Windows the changed event should be raised.");
            activeFile = _fileSystemState.FindEncryptedPath(_encryptedFile1);
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The file should be deleted and marked as Not Decrypted when running as Desktop Windows.");
        }
Example #25
0
        public static void TestCheckActiveFilesKeyIsSet()
        {
            DateTime utcNow     = OS.Current.UtcNow;
            DateTime utcJustNow = utcNow.AddMinutes(-1);

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcJustNow, utcJustNow, utcJustNow, Stream.Null);

            ActiveFile activeFile;

            activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedFile1), OS.Current.FileInfo(_decryptedFile1), new AesKey(), ActiveFileStatus.AssumedOpenAndDecrypted, null);
            _fileSystemState.Add(activeFile);

            IRuntimeFileInfo decryptedFileInfo = OS.Current.FileInfo(_decryptedFile1);

            decryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(1)); });
            bool changedWasRaised = false;

            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });
            _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
            Assert.That(changedWasRaised, Is.True, "The file should be detected as modified, because it is considered open and decrypted, has a proper key, is modified, no running process so it should be re-encrypted and deleted.");
            activeFile = _fileSystemState.FindEncryptedPath(_encryptedFile1);
            Assert.That(activeFile, Is.Not.Null, "The encrypted file should be found.");
            Assert.That(activeFile.IsModified, Is.False, "The file should no longer be flagged as modified.");
            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The file should no longer be decrypted, since it was re-encrypted and deleted.");
        }
Example #26
0
        public static void TestCheckActiveFilesIsLocked()
        {
            DateTime utcNow       = OS.Current.UtcNow;
            DateTime utcYesterday = utcNow.AddDays(-1);

            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcYesterday, utcYesterday, utcYesterday, Stream.Null);

            ActiveFile activeFile = new ActiveFile(OS.Current.FileInfo(_encryptedFile1), OS.Current.FileInfo(_decryptedFile1), new AesKey(), ActiveFileStatus.NotDecrypted, null);

            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return(utcNow.AddMinutes(10)); });
            bool changedWasRaised = false;

            _fileSystemState.Add(activeFile);
            _fileSystemState.Changed += ((object sender, ActiveFileChangedEventArgs e) =>
            {
                changedWasRaised = true;
            });
            using (FileLock fileLock = FileLock.Lock(activeFile.EncryptedFileInfo))
            {
                _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
            }
            Assert.That(changedWasRaised, Is.False, "The file should be not be detected as decrypted being created because the encrypted file is locked.");
            using (FileLock fileLock = FileLock.Lock(activeFile.DecryptedFileInfo))
            {
                _fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
            }
            Assert.That(changedWasRaised, Is.False, "The file should be not be detected as decrypted being created because the decrypted file is locked.");
        }
        public static bool IsDisplayEquivalentTo(this ActiveFile left, ActiveFile right)
        {
            if (object.ReferenceEquals(left, right))
            {
                return(true);
            }
            if (left.Properties != right.Properties)
            {
                return(false);
            }
            if (left.Status != right.Status)
            {
                return(false);
            }
            if (left.DecryptedFileInfo.FullName != right.DecryptedFileInfo.FullName)
            {
                return(false);
            }
            if (left.EncryptedFileInfo.FullName != right.EncryptedFileInfo.FullName)
            {
                return(false);
            }
            if (left.IsShared != right.IsShared)
            {
                return(false);
            }

            return(true);
        }
Example #28
0
        public async Task TestFileAlreadyDecryptedButWithUnknownKey()
        {
            IDataStore dataStore = New <IDataStore>(_helloWorldAxxPath);

            TypeMap.Register.New <ILauncher>(() => new FakeLauncher());
            IEnumerable <LogOnIdentity> keys = new LogOnIdentity[] { new LogOnIdentity("a") };

            DateTime utcNow = DateTime.UtcNow;

            ((FakeNow)New <INow>()).TimeFunction = () => { return(utcNow); };
            FileOperation        fileOperation = new FileOperation(Resolve.FileSystemState, new SessionNotify());
            FileOperationContext status        = await fileOperation.OpenAndLaunchApplication(keys, dataStore, new ProgressContext());

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.Success), "The launch should succeed.");

            ActiveFile destinationActiveFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(dataStore.FullName);

            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.Not.EqualTo(utcNow), "The decryption should restore the time stamp of the original file, and this is not now.");
            destinationActiveFile.DecryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);

            IEnumerable <LogOnIdentity> badKeys = new LogOnIdentity[] { new LogOnIdentity("b") };

            status = await fileOperation.OpenAndLaunchApplication(badKeys, dataStore, new ProgressContext());

            Assert.That(status.ErrorStatus, Is.EqualTo(ErrorStatus.InvalidKey), "The launch should fail this time, since the key is not known.");
            destinationActiveFile = Resolve.FileSystemState.FindActiveFileFromEncryptedPath(dataStore.FullName);
            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(utcNow), "There should be no decryption, and thus the time stamp should be as just set.");
        }
Example #29
0
        public virtual async Task <FileOperationContext> OpenAndLaunchApplication(IEnumerable <LogOnIdentity> identities, IDataStore encryptedDataStore, IProgressContext progress)
        {
            if (identities == null)
            {
                throw new ArgumentNullException(nameof(identities));
            }
            if (encryptedDataStore == null)
            {
                throw new ArgumentNullException(nameof(encryptedDataStore));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            if (!encryptedDataStore.IsAvailable)
            {
                if (Resolve.Log.IsWarningEnabled)
                {
                    Resolve.Log.LogWarning("Tried to open non-existing '{0}'.".InvariantFormat(encryptedDataStore.FullName));
                }
                return(new FileOperationContext(encryptedDataStore.FullName, ErrorStatus.FileDoesNotExist));
            }

            ActiveFile activeFile = _fileSystemState.FindActiveFileFromEncryptedPath(encryptedDataStore.FullName);

            if (activeFile == null || !activeFile.DecryptedFileInfo.IsAvailable)
            {
                activeFile = TryDecryptToActiveFile(encryptedDataStore, identities);
            }
            else
            {
                activeFile = CheckKeysForAlreadyDecryptedFile(activeFile, identities, progress);
            }

            if (activeFile == null)
            {
                return(new FileOperationContext(encryptedDataStore.FullName, ErrorStatus.InvalidKey));
            }

            using (FileLock destinationLock = New <FileLocker>().Acquire(activeFile.DecryptedFileInfo))
            {
                if (!activeFile.DecryptedFileInfo.IsAvailable)
                {
                    activeFile = Decrypt(activeFile.Identity, activeFile.EncryptedFileInfo, destinationLock, activeFile, progress);
                }
                _fileSystemState.Add(activeFile);
                await _fileSystemState.Save();

                if (encryptedDataStore.IsWriteProtected || !New <LicensePolicy>().Capabilities.Has(LicenseCapability.EditExistingFiles))
                {
                    activeFile.DecryptedFileInfo.IsWriteProtected = true;
                }

                FileOperationContext status = await LaunchApplicationForDocument(activeFile, destinationLock);

                return(status);
            }
        }
Example #30
0
        private void EncryptFile(string file, IThreadWorker worker, ProgressContext progress)
        {
            FileOperationsController operationsController = new FileOperationsController(persistentState.Current, progress);

            operationsController.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
            {
                using (SaveFileDialog sfd = new SaveFileDialog())
                {
                    sfd.Title            = Resources.EncryptFileSaveAsDialogTitle;
                    sfd.AddExtension     = true;
                    sfd.ValidateNames    = true;
                    sfd.CheckPathExists  = true;
                    sfd.DefaultExt       = OS.Current.AxCryptExtension;
                    sfd.FileName         = e.SaveFileFullName;
                    sfd.Filter           = Resources.EncryptedFileDialogFilterPattern.InvariantFormat(OS.Current.AxCryptExtension);
                    sfd.InitialDirectory = Path.GetDirectoryName(e.SaveFileFullName);
                    sfd.ValidateNames    = true;
                    DialogResult saveAsResult = sfd.ShowDialog();
                    if (saveAsResult != DialogResult.OK)
                    {
                        e.Cancel = true;
                        return;
                    }
                    e.SaveFileFullName = sfd.FileName;
                }
            };

            operationsController.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
            {
                string passphrase = AskForEncryptionPassphrase();
                if (String.IsNullOrEmpty(passphrase))
                {
                    e.Cancel = true;
                    return;
                }
                e.Passphrase = passphrase;
                AesKey defaultEncryptionKey = new Passphrase(e.Passphrase).DerivedPassphrase;
                persistentState.Current.KnownKeys.DefaultEncryptionKey = defaultEncryptionKey;
            };

            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
            {
                if (e.Status == FileOperationStatus.FileAlreadyEncrypted)
                {
                    e.Status = FileOperationStatus.Success;
                    return;
                }
                if (CheckStatusAndShowMessage(e.Status, e.OpenFileFullName))
                {
                    IRuntimeFileInfo encryptedInfo = OS.Current.FileInfo(e.SaveFileFullName);
                    IRuntimeFileInfo decryptedInfo = OS.Current.FileInfo(FileOperation.GetTemporaryDestinationName(e.OpenFileFullName));
                    ActiveFile       activeFile    = new ActiveFile(encryptedInfo, decryptedInfo, e.Key, ActiveFileStatus.NotDecrypted, null);
                    persistentState.Current.Add(activeFile);
                    persistentState.Current.Save();
                }
            };

            operationsController.EncryptFile(file, worker);
        }