public async Task Initialize() { CancellationTokenSource cts = new CancellationTokenSource(); MethodInfo testMethod = GetType().GetRuntimeMethod( TestContext.TestName, new Type[0] ); var specAttr = testMethod.GetCustomAttribute <DetailsForAttribute>(); var dataAttr = testMethod.GetCustomAttribute <TestDataAttribute>(); Assert.IsTrue(specAttr != null || dataAttr != null); try { Utils.DatabaseInfo databaseInfo = await Utils.GetDatabaseInfoForTest(TestContext); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await databaseInfo.Database.AsIStorageFile.OpenReadAsync()) { Assert.IsFalse((await reader.ReadHeaderAsync(stream, cts.Token)).IsError); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, databaseInfo.Password, databaseInfo.Keyfile, cts.Token); Assert.IsFalse(decryption.Result.IsError); this.document = decryption.GetDocument(); if (specAttr != null && (dataAttr == null || !dataAttr.SkipInitialization)) { IDatabaseNavigationViewModel navVm = new DatabaseNavigationViewModel(); navVm.SetGroup(this.document.Root.DatabaseGroup); IDatabasePersistenceService persistenceService = new DummyPersistenceService(); this.instantiationTime = DateTime.Now; if (specAttr.IsNew) { this.expectedParent = this.document.Root.DatabaseGroup; this.viewModel = GetNewViewModel(navVm, persistenceService, this.document, this.expectedParent); } else { this.expectedParent = this.document.Root.DatabaseGroup; this.viewModel = GetExistingViewModel( navVm, persistenceService, this.document, specAttr.IsOpenedReadOnly ); } } else { this.expectedParent = null; Assert.IsTrue(dataAttr.SkipInitialization); } } } catch (InvalidOperationException) { } }
public async Task Initialize() { CancellationTokenSource cts = new CancellationTokenSource(); this.clipboardService = new SensitiveClipboardService(this.clipboard); try { Utils.DatabaseInfo databaseInfo = await Utils.GetDatabaseInfoForTest(TestContext); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await databaseInfo.Database.AsIStorageFile.OpenReadAsync()) { Assert.IsFalse((await reader.ReadHeaderAsync(stream, cts.Token)).IsError); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, databaseInfo.Password, databaseInfo.Keyfile, cts.Token); Assert.IsFalse(decryption.Result.IsError); this.viewModel = new DatabaseViewModel( decryption.GetDocument(), new MockResourceProvider(), reader.HeaderData.GenerateRng(), new DatabaseNavigationViewModel(), new DummyPersistenceService(), new AppSettingsService(new InMemorySettingsProvider()), this.clipboardService ); await this.viewModel.ActivateAsync(); } } catch (InvalidOperationException) { } }
private async Task RoundTrip() { ReaderResult initialHeaderResult = await this.reader.ReadHeaderAsync(await this.thisTestInfo.Database.AsIStorageFile.OpenReadAsync(), CancellationToken.None); Assert.AreEqual(ReaderResult.Success, initialHeaderResult, "Initial header read should be successful"); KdbxDecryptionResult result = await this.reader.DecryptFileAsync(await this.thisTestInfo.Database.AsIStorageFile.OpenReadAsync(), this.thisTestInfo.Password, this.thisTestInfo.Keyfile, CancellationToken.None); Assert.AreEqual(ReaderResult.Success, result.Result, "File should have initially decrypted properly"); KdbxDocument kdbxDoc = result.GetDocument(); IKdbxWriter writer = this.reader.GetWriter(); using (var stream = new InMemoryRandomAccessStream()) { bool writeResult = await writer.WriteAsync(stream, kdbxDoc, CancellationToken.None); Assert.IsTrue(writeResult, "File should have written successfully"); stream.Seek(0); KdbxReader newReader = new KdbxReader(); ReaderResult result2 = await newReader.ReadHeaderAsync(stream, CancellationToken.None); Assert.AreEqual(ReaderResult.Success, result2, "Header should been read back successfully after write"); KdbxDecryptionResult result3 = await newReader.DecryptFileAsync(stream, this.thisTestInfo.Password, this.thisTestInfo.Keyfile, CancellationToken.None); Assert.AreEqual(ReaderResult.Success, result3.Result, "File should have decrypted successfully after write"); KdbxDocument roundTrippedDocument = result3.GetDocument(); Assert.AreEqual(kdbxDoc, roundTrippedDocument, "Round-tripped document should be equal to original document"); } }
public async Task ChangePassword() { string newPw = "TestPW"; this.masterKeyVm.MasterPassword = newPw; Assert.IsFalse(this.masterKeyVm.ConfirmCommand.CanExecute(null), "Should not be able to confirm new password until password is entered twice"); this.masterKeyVm.ConfirmedPassword = newPw; Assert.IsTrue(this.masterKeyVm.ConfirmCommand.CanExecute(null), "Should be able to confirm new password when second password matches"); this.masterKeyVm.ConfirmedPassword = "******"; Assert.IsFalse(this.masterKeyVm.ConfirmCommand.CanExecute(null), "Mismatched passwords should not be able to be confirmed"); this.masterKeyVm.ConfirmedPassword = newPw; DateTime lastPasswordChange = this.document.Metadata.MasterKeyChanged.Value; this.masterKeyVm.ConfirmCommand.Execute(null); DateTime passwordChangeTime = DateTime.Parse(this.document.Metadata.MasterKeyChanged.Value.ToString()); Assert.IsTrue(passwordChangeTime > lastPasswordChange, "MasterKeyChanged value should have changed in document metadata"); Assert.IsTrue(await this.persistenceService.Save(this.document)); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await this.saveFile.AsIStorageFile.OpenReadAsync()) { await reader.ReadHeaderAsync(stream, CancellationToken.None); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, newPw, null, CancellationToken.None); Assert.AreEqual(KdbxParserCode.Success, decryption.Result.Code, "Database should decrypt with the new credentials"); KdbxDocument document = decryption.GetDocument(); Assert.AreEqual(passwordChangeTime, document.Metadata.MasterKeyChanged.Value, "MasterKeyChanged timestamp should have been persisted"); } }
public async Task DowngradeCipherSettings() { DateTime lastPasswordChange = this.document.Metadata.MasterKeyChanged.Value; Assert.AreEqual(EncryptionAlgorithm.ChaCha20, this.settingsVm.Cipher, "ChaCha20 should be the encryption algorithm before the test starts"); this.writer.Cipher = EncryptionAlgorithm.Aes; Assert.IsInstanceOfType(this.settingsVm.GetKdfParameters(), typeof(Argon2Parameters), "Argon2 should be the KDF before the test starts according to the VM"); Assert.IsInstanceOfType(this.writer.KdfParameters, typeof(Argon2Parameters), "Argon2 should be the KDF before the test starts according to the KdbxWriter"); this.settingsVm.KdfGuid = AesParameters.AesUuid; this.settingsVm.KdfIterations = 6001; Assert.IsInstanceOfType(this.writer.KdfParameters, typeof(AesParameters), "Changes to the settings VM should be reflected in the KdbxWriter"); Assert.IsTrue(await this.persistenceService.Save(this.document)); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await this.saveFile.AsIStorageFile.OpenReadAsync()) { await reader.ReadHeaderAsync(stream, CancellationToken.None); Assert.AreEqual(EncryptionAlgorithm.Aes, reader.HeaderData.Cipher, "New reader should have the correct cipher"); AesParameters aesParams = reader.HeaderData.KdfParameters as AesParameters; Assert.IsNotNull(aesParams, "Database should have properly persisted with AES"); Assert.AreEqual(6001, (int)aesParams.Rounds, "AES iteration count should have been persisted correctly"); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, this.dbPassword, this.dbKeyFile, CancellationToken.None); Assert.AreEqual(KdbxParserCode.Success, decryption.Result.Code); KdbxDocument document = decryption.GetDocument(); Assert.AreEqual(lastPasswordChange, document.Metadata.MasterKeyChanged.Value, "MasterKeyChanged timestamp should not have changed"); } }
public async Task Init() { // Get database from test attributes Utils.DatabaseInfo dbInfo = await Utils.GetDatabaseInfoForTest(TestContext); this.dbPassword = dbInfo.Password; this.dbKeyFile = dbInfo.Keyfile; // Assert that databases named *ReadOnly* are actually readonly after a clone if (dbInfo.Database.Name.IndexOf("ReadOnly", StringComparison.OrdinalIgnoreCase) >= 0) { Assert.IsFalse( await dbInfo.Database.CheckWritableAsync(), $"This file is expected to be read-only; please verify this before testing: {dbInfo.Database.Name}" ); } this.saveFile = (await dbInfo.Database.AsIStorageFile.CopyAsync( ApplicationData.Current.TemporaryFolder, $"PersistenceTestDb-{Guid.NewGuid()}.kdbx", NameCollisionOption.ReplaceExisting )).AsWrapper(); // Use a KdbxReader to parse the database and get a corresponding writer KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await this.saveFile.AsIStorageFile.OpenReadAsync()) { await reader.ReadHeaderAsync(stream, CancellationToken.None); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, dbInfo.Password, dbInfo.Keyfile, CancellationToken.None); Assert.AreEqual(KdbxParserCode.Success, decryption.Result.Code); this.document = decryption.GetDocument(); } // Construct services we can use for the test this.writer = reader.GetWriter(); this.persistenceService = new DefaultFilePersistenceService( this.writer, this.writer, new StorageFileDatabaseCandidate(this.saveFile, true), new MockSyncContext(), true ); this.credentialStorage = new MockCredentialProvider(); this.masterKeyVm = new MasterKeyChangeViewModel( this.document, this.saveFile, new DatabaseCredentialProvider(this.persistenceService, this.credentialStorage), new MockFileService() ); this.settingsVm = new DatabaseSettingsViewModel(this.writer); }
public async Task Initialize() { Utils.DatabaseInfo databaseInfo = await Utils.GetDatabaseInfoForTest(TestContext); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await databaseInfo.Database.AsIStorageFile.OpenReadAsync()) { Assert.IsFalse((await reader.ReadHeaderAsync(stream, CancellationToken.None)).IsError); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, databaseInfo.Password, databaseInfo.Keyfile, CancellationToken.None); Assert.IsFalse(decryption.Result.IsError); this.document = decryption.GetDocument(); this.rng = reader.HeaderData.GenerateRng(); } }
public async Task Initialize() { try { CancellationTokenSource cts = new CancellationTokenSource(); Utils.DatabaseInfo databaseInfo = await Utils.GetDatabaseInfoForTest(TestContext); KdbxReader reader = new KdbxReader(); using (IRandomAccessStream stream = await databaseInfo.Database.AsIStorageFile.OpenReadAsync()) { Assert.IsFalse((await reader.ReadHeaderAsync(stream, cts.Token)).IsError); KdbxDecryptionResult decryption = await reader.DecryptFileAsync(stream, databaseInfo.Password, databaseInfo.Keyfile, cts.Token); Assert.IsFalse(decryption.Result.IsError); this.document = decryption.GetDocument(); } } catch (InvalidOperationException) { } this.viewModel = new DatabaseNavigationViewModel(); }
public async Task MultiEdit_Degenerate() { StorageFileDatabaseCandidateFactory factory = new StorageFileDatabaseCandidateFactory(new MockFileProxyProvider { ScopeValue = true }); StorageFolder work = await Utils.GetWorkFolder(); IDatabaseCandidate workDb = await factory.AssembleAsync( (await this.thisTestInfo.Database.AsIStorageFile.CopyAsync(work, "Work.kdbx", NameCollisionOption.ReplaceExisting)) .AsWrapper() ); IKdbxWriter writer; KdbxDocument doc; var reader = new KdbxReader(); using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { ReaderResult headerResult = await reader.ReadHeaderAsync(stream, CancellationToken.None); Assert.AreEqual(headerResult, ReaderResult.Success); } KdbxDecryptionResult bodyResult = null; using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { bodyResult = await reader.DecryptFileAsync(stream, this.thisTestInfo.Password, this.thisTestInfo.Keyfile, CancellationToken.None); Assert.AreEqual(bodyResult.Result, ReaderResult.Success); } writer = reader.GetWriter(); doc = bodyResult.GetDocument(); IDatabasePersistenceService persistor = new DefaultFilePersistenceService(writer, writer, workDb, new MockSyncContext(), await workDb.File.CheckWritableAsync()); Assert.IsTrue(persistor.CanSave); Assert.IsTrue(await persistor.Save(doc)); // Remove the last group doc.Root.DatabaseGroup.Children.RemoveAt( doc.Root.DatabaseGroup.Children.IndexOf( doc.Root.DatabaseGroup.Children.Last(node => node is IKeePassGroup) ) ); Assert.IsTrue(await persistor.Save(doc)); reader = new KdbxReader(); using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { ReaderResult headerResult = await reader.ReadHeaderAsync(stream, CancellationToken.None); Assert.AreEqual(headerResult, ReaderResult.Success); } using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { bodyResult = await reader.DecryptFileAsync(stream, this.thisTestInfo.Password, this.thisTestInfo.Keyfile, CancellationToken.None); Assert.AreEqual(bodyResult.Result, ReaderResult.Success); } writer = reader.GetWriter(); doc = bodyResult.GetDocument(); doc.Root.DatabaseGroup.Children.RemoveAt( doc.Root.DatabaseGroup.Children.IndexOf( doc.Root.DatabaseGroup.Children.Last(node => node is IKeePassGroup) ) ); Assert.IsTrue(await persistor.Save(doc)); reader = new KdbxReader(); using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { ReaderResult headerResult = await reader.ReadHeaderAsync(stream, CancellationToken.None); Assert.AreEqual(headerResult, ReaderResult.Success); } using (IRandomAccessStream stream = await workDb.GetRandomReadAccessStreamAsync()) { bodyResult = await reader.DecryptFileAsync(stream, this.thisTestInfo.Password, this.thisTestInfo.Keyfile, CancellationToken.None); Assert.AreEqual(bodyResult.Result, ReaderResult.Success); } writer = reader.GetWriter(); doc = bodyResult.GetDocument(); }