public void EncryptedDataWithPasswordBytes() { var encryptedData = new EncryptedDataWithPassword(Encoding.UTF8.GetBytes(TestString), TestPassword); var encryptedDataString = encryptedData.ToString(); var decryptedTestBytes = EncryptedDataWithPassword.DecryptDataAsBytes(encryptedDataString, TestPassword); Assert.AreEqual(TestString, Encoding.UTF8.GetString(decryptedTestBytes)); }
public void EncryptedDataWithPasswordString() { var encryptedData = new EncryptedDataWithPassword(TestString, TestPassword); var encryptedDataString = encryptedData.ToString(); var decryptedTestString = EncryptedDataWithPassword.DecryptData(TestPassword, encryptedDataString); Assert.AreEqual(TestString, decryptedTestString); }
private void BackupEntrySecrets() { var accountSettings = _model.ServerAccountSettings.Query().First(); if (!accountSettings.BackupRecoveryPasswordHashSet) return; var secrets = _model.EntriesSharedSecrets.Query().ToList(); foreach (var secret in secrets) { var entry = _model.Entries.Query().First(r => r.Id == secret.EntryId); var database = _model.Links.Query().First(r => r.Id == entry.LinkId); if (secret.ToBeDeleted) { var deleteRequest = new DeleteDatabaseEntryDeviceSecret { LinkIdentifier = database.Identifier, SecretIdentifier = secret.SecretIdentifier }; try { deleteRequest.GetResponse(GetApiClient()); } catch (RequestException) { // Try again next time. continue; } _model.EntriesSharedSecretsData.Delete(secret.EntrySecretDataId); _model.EntriesSharedSecrets.Delete(secret.Id); continue; } // Is there an update request for this entry? var updateRequests = _model.EntriesSharedSecretsSync.Query() .Where(r => r.EntrySecretId == secret.Id).ToList(); if (updateRequests.Count == 0) continue; var updateRequestsSorted = updateRequests.OrderByDescending(update => update.CreatedAt); var latestUpdateRequest = updateRequestsSorted.First(); // Remove duplicate update requests foreach (var updateRequest in updateRequestsSorted) { if (updateRequest.Id == latestUpdateRequest.Id) continue; _model.EntriesSharedSecretsSync.Delete(updateRequest.Id); } var secretData = _model.EntriesSharedSecretsData.Query().First(r => r.Id == secret.EntrySecretDataId); var serializedEntry = JsonConvert.SerializeObject(secretData); var encryptedData = new EncryptedDataWithPassword( Compression.Compress(serializedEntry), accountSettings.BackupRecoveryPasswordHash).ToString(); var request = new SetDatabaseEntryDeviceSecret { LinkIdentifier = database.Identifier, EntryIdentifier = entry.Identifier, SecretIdentifier = secret.SecretIdentifier, DataType = "ModelJsonGz", Data = encryptedData }; try { request.GetResponse(GetApiClient()); } catch (RequestException) { // Try again later continue; } // Sync completed _model.EntriesSharedSecretsSync.Delete(latestUpdateRequest.Id); } }
private void SyncDatabaseUploadEntries(int databaseId) { if (_databaseEntriesUploadRunning) return; if (_requestErrors > 0) return; var serverAccount = GetServerAccount(); var linkedClientCryptoKey = Model.CryptoKeys.Get(serverAccount.LinkedDeviceCryptoKeyId); var database = Model.Databases.Get(databaseId); var entriesToBeDeleted = Model.DatabasesEntries.Find(new DatabaseEntry {ToBeDeleted = true}).ToList(); foreach (var entryToBeDeleted in entriesToBeDeleted) { if (_stopSyncLoop || _processMessagesOnly) return; var deleteRequest = new DeleteDatabaseEntry { LinkIdentifier = database.Identifier, EntryIdentifier = entryToBeDeleted.Identifier }; var deleteOnDeviceMessageContent = new DeviceToDeviceMessages.DeleteEntry { LinkIdentifier = database.Identifier, EntryIdentifier = entryToBeDeleted.Identifier }; var deleteOnDeviceMessageRequest = new SendLinkedDeviceMessage(); deleteOnDeviceMessageRequest.SetMessage(deleteOnDeviceMessageContent, linkedClientCryptoKey.PublicKeyPem); try { deleteRequest.GetResponse(GetApiClient()); deleteOnDeviceMessageRequest.GetResponse(GetApiClient()); _requestErrors = 0; } catch (NetworkErrorException) { _requestErrors++; return; } catch (RequestException) { // Try again next time. continue; } var versions = Model.DatabasesEntriesDataVersions.Find(new DatabaseEntryDataVersion { DatabaseEntryId = entryToBeDeleted.Id }); foreach (var version in versions) { Model.DatabasesEntriesData.Delete(version.DatabaseEntryDataId); Model.DatabasesEntriesDataVersions.Delete(version.Id); } Model.DatabasesEntries.Delete(entryToBeDeleted.Id); } _databaseEntriesUploadRunning = true; Task.Run(() => { var databaseEntries = Model.DatabasesEntries.Find(new DatabaseEntry { DatabaseId = databaseId }); var entriesToSend = new List<DatabaseEntry>(); var entriesDataToSend = new List<DatabaseEntryData>(); var entriesDataSerialized = new List<string>(); var entriesSyncRequest = new List<DatabaseEntryDataSync>(); var entriesUploadItems = new List<SetDatabaseEntries.EntryItem>(); foreach (var entry in databaseEntries) { if (_stopSyncLoop || _processMessagesOnly) { _databaseEntriesUploadRunning = false; return; } var entryData = Model.DatabasesEntriesData.Get(entry.DatabaseEntryDataId); if (!entryData.PasswordShared) continue; // Is there an update request for this entry? var updateRequests = Model.DatabasesEntriesDataSync.Find(new DatabaseEntryDataSync { DatabaseEntryId = entry.Id }); var updateRequestsSorted = updateRequests?.OrderByDescending(update => update.CreatedAt); var latestUpdateRequest = updateRequestsSorted?.FirstOrDefault(); if (latestUpdateRequest == null) continue; // Remove duplicate update requests foreach (var updateRequest in updateRequestsSorted) { if (updateRequest.Id == latestUpdateRequest.Id) continue; Model.DatabasesEntriesDataSync.Delete(updateRequest.Id); } var newVersion = entry.Version + 1; var serializedEntry = JsonConvert.SerializeObject(entryData); var encryptedData = new EncryptedDataWithPassword( Util.CompressData(serializedEntry), serverAccount.BackupEncryptionPassword).ToString(); var group = Model.DatabasesGroups.Get(entry.DatabaseGroupId); entriesUploadItems.Add(new SetDatabaseEntries.EntryItem { Version = newVersion, GroupIdentifier = group.Identifier, EntryIdentifier = entry.Identifier, DataType = "ModelJsonGz", Data = encryptedData }); entriesToSend.Add(entry); entriesDataToSend.Add(entryData); entriesDataSerialized.Add(serializedEntry); entriesSyncRequest.Add(latestUpdateRequest); } if (entriesToSend.Count == 0) { _databaseEntriesUploadRunning = false; return; } _controller.SetDatabaseSyncStatus(databaseId, Statuses.Syncing); var request = new SetDatabaseEntries { LinkIdentifier = database.Identifier, Entries = entriesUploadItems }; try { request.GetResponse(GetApiClient()); _requestErrors = 0; } catch (ConflictException) { if (Program.AppEnvDebug) throw new NotImplementedException("TODO: Download update to group"); _databaseEntriesUploadRunning = false; return; } catch (NetworkErrorException) { _requestErrors++; _databaseEntriesUploadRunning = false; return; } catch (RequestException) { _databaseEntriesUploadRunning = false; return; } for (var i = 0; i < entriesToSend.Count; i++) { var entry = entriesToSend[i]; var entryUploadItem = entriesUploadItems[i]; var serializedEntry = entriesDataSerialized[i]; var latestUpdateRequest = entriesSyncRequest[i]; var newVersion = entryUploadItem.Version; // Create archive version var archiveData = JsonConvert.DeserializeObject<DatabaseEntryData>(serializedEntry); archiveData.RemoveId(); var archiveDataId = Model.DatabasesEntriesData.Create(archiveData); Model.DatabasesEntriesDataVersions.Create(new DatabaseEntryDataVersion { DatabaseEntryId = entry.Id, Version = newVersion, DatabaseEntryDataId = archiveDataId }); // Update current record Model.DatabasesEntries.Update(entry.Id, new DatabaseEntry { Version = newVersion }); // Sync completed Model.DatabasesEntriesDataSync.Delete(latestUpdateRequest.Id); } _controller.SetDatabaseSyncStatus(databaseId, Statuses.UpToDate); _databaseEntriesUploadRunning = false; }); }
private void SyncDatabaseUploadGroups(int databaseId) { var serverAccount = GetServerAccount(); var database = Model.Databases.Get(databaseId); var databaseGroups = Model.DatabasesGroups.Find(new DatabaseGroup {DatabaseId = databaseId}); foreach (var group in databaseGroups) { if (_stopSyncLoop) return; if (_processMessagesOnly) return; var updateRequests = Model.DatabasesGroupsMetaSync.Find(new DatabaseGroupMetaSync { DatabaseGroupId = group.Id }); var updateRequestsSorted = updateRequests?.OrderByDescending(update => update.CreatedAt); var latestUpdateRequest =updateRequestsSorted?.FirstOrDefault(); if (latestUpdateRequest == null) continue; _controller.SetDatabaseSyncStatus(databaseId, Statuses.Syncing); // Remove duplicate update requests foreach (var updateRequest in updateRequestsSorted) { if (updateRequest.Id == latestUpdateRequest.Id) continue; Model.DatabasesGroupsMetaSync.Delete(updateRequest.Id); } var newVersion = group.Version + 1; var groupMeta = Model.DatabasesGroupsMeta.Get(group.DatabaseGroupMetaId); var serializedEntry = JsonConvert.SerializeObject(groupMeta); var encryptedData = new EncryptedDataWithPassword( Util.CompressData(serializedEntry), serverAccount.BackupEncryptionPassword).ToString(); var request = new SetDatabaseGroup { Version = newVersion, DatabaseIdentifier = database.Identifier, GroupIdentifier = group.Identifier, DataType = "ModelJsonGz", Data = encryptedData }; try { request.GetResponse(GetApiClient()); _requestErrors = 0; } catch (ConflictException) { if (Program.AppEnvDebug) throw new NotImplementedException("TODO: Download update to group"); continue; } catch (NetworkErrorException) { _requestErrors++; return; } catch (RequestException) { continue; } // Create archive version var archiveMetaData = JsonConvert.DeserializeObject<DatabaseGroupMeta>(serializedEntry); archiveMetaData.RemoveId(); var archiveMetaDataId = Model.DatabasesGroupsMeta.Create(archiveMetaData); Model.DatabasesGroupsMetaVersions.Create(new DatabaseGroupMetaVersion { DatabaseGroupId = group.Id, Version = newVersion, DatabaseGroupMetaId = archiveMetaDataId }); // Update current record Model.DatabasesGroups.Update(group.Id, new DatabaseGroup { Version = newVersion }); // Sync completed Model.DatabasesGroupsMetaSync.Delete(latestUpdateRequest.Id); _controller.SetDatabaseSyncStatus(databaseId, Statuses.UpToDate); } }