public static async Task PutNonSharedData <T>(this VaultOnline vault, string recordUid, T nonSharedData) where T : RecordNonSharedData, new() { var existingData = vault.LoadNonSharedData <T>(recordUid) ?? new T(); nonSharedData.ExtensionData = existingData.ExtensionData; var data = JsonUtils.DumpJson(nonSharedData); var existingRecord = vault.Storage.Records.GetEntity(recordUid); var updateRecord = new RecordUpdateRecord { RecordUid = recordUid, Revision = existingRecord?.Revision ?? 0, NonSharedData = CryptoUtils.EncryptAesV1(data, vault.Auth.AuthContext.DataKey).Base64UrlEncode() }; var command = new RecordUpdateCommand { deviceId = vault.Auth.Endpoint.DeviceName, UpdateRecords = new[] { updateRecord } }; await vault.Auth.ExecuteAuthCommand <RecordUpdateCommand, RecordUpdateResponse>(command); await vault.ScheduleSyncDown(TimeSpan.FromSeconds(0)); }
public static async Task <PasswordRecord> PutRecord(this VaultOnline vault, PasswordRecord record, bool skipData = false, bool skipExtra = true) { IPasswordRecord existingRecord = null; if (!string.IsNullOrEmpty(record.Uid)) { existingRecord = vault.Storage.Records.GetEntity(record.Uid); } if (existingRecord == null) { return(await vault.AddRecordToFolder(record)); } var updateRecord = new RecordUpdateRecord { RecordUid = existingRecord.RecordUid }; var rmd = vault.ResolveRecordAccessPath(updateRecord, true); if (rmd != null) { if (rmd.RecordKeyType == (int)KeyType.NoKey || rmd.RecordKeyType == (int)KeyType.PrivateKey) { updateRecord.RecordKey = CryptoUtils.EncryptAesV1(record.RecordKey, vault.Auth.AuthContext.DataKey) .Base64UrlEncode(); } } updateRecord.Revision = existingRecord.Revision; if (!skipData) { var dataSerializer = new DataContractJsonSerializer(typeof(RecordData), JsonUtils.JsonSettings); RecordData existingData = null; try { var unencryptedData = CryptoUtils.DecryptAesV1(existingRecord.Data.Base64UrlDecode(), record.RecordKey); using (var ms = new MemoryStream(unencryptedData)) { existingData = (RecordData)dataSerializer.ReadObject(ms); } } catch (Exception e) { Trace.TraceError("Decrypt Record: UID: {0}, {1}: \"{2}\"", existingRecord.RecordUid, e.GetType().Name, e.Message); } var data = record.ExtractRecordData(existingData); using (var ms = new MemoryStream()) { dataSerializer.WriteObject(ms, data); updateRecord.Data = CryptoUtils.EncryptAesV1(ms.ToArray(), record.RecordKey).Base64UrlEncode(); } } if (!skipExtra) { var extraSerializer = new DataContractJsonSerializer(typeof(RecordExtra), JsonUtils.JsonSettings); RecordExtra existingExtra = null; try { var unencryptedExtra = CryptoUtils.DecryptAesV1(existingRecord.Extra.Base64UrlDecode(), record.RecordKey); using (var ms = new MemoryStream(unencryptedExtra)) { existingExtra = (RecordExtra)extraSerializer.ReadObject(ms); } } catch (Exception e) { Trace.TraceError("Decrypt Record: UID: {0}, {1}: \"{2}\"", existingRecord.RecordUid, e.GetType().Name, e.Message); } var extra = record.ExtractRecordExtra(existingExtra); using (var ms = new MemoryStream()) { extraSerializer.WriteObject(ms, extra); updateRecord.Extra = CryptoUtils.EncryptAesV1(ms.ToArray(), record.RecordKey).Base64UrlEncode(); } var udata = new RecordUpdateUData(); var ids = new HashSet <string>(); if (record.Attachments != null) { foreach (var atta in record.Attachments) { ids.Add(atta.Id); if (atta.Thumbnails != null) { foreach (var thumb in atta.Thumbnails) { ids.Add(thumb.Id); } } } } udata.FileIds = ids.ToArray(); updateRecord.Udata = udata; } var command = new RecordUpdateCommand { deviceId = vault.Auth.Endpoint.DeviceName, UpdateRecords = new[] { updateRecord } }; await vault.Auth.ExecuteAuthCommand <RecordUpdateCommand, RecordUpdateResponse>(command); await vault.ScheduleSyncDown(TimeSpan.FromSeconds(0)); return(vault.TryGetRecord(record.Uid, out var r) ? r : record); }
public async Task SaveRecord(PasswordRecord record, bool skipData = false, bool skipExtra = true) { SyncDownRecord existingRecord = null; if (!string.IsNullOrEmpty(record.Uid)) { records.TryGetValue(record.Uid, out existingRecord); } var updateRecord = new RecordUpdateRecord(); byte[] recordKey = null; if (existingRecord != null) { updateRecord.recordUid = existingRecord.recordUid; recordKey = existingRecord.unencryptedRecordKey; if (metaData.TryGetValue(existingRecord.recordUid, out SyncDownRecordMetaData sdrmd)) { if (sdrmd.recordKeyType == 2) { updateRecord.recordKey = CryptoUtils.EncryptAesV1(recordKey, Auth.DataKey).Base64UrlEncode(); } } updateRecord.revision = existingRecord.revision; ResolveRecordAccessPath(updateRecord); } else { updateRecord.recordUid = CryptoUtils.GenerateUid(); recordKey = CryptoUtils.GenerateEncryptionKey(); updateRecord.recordKey = CryptoUtils.EncryptAesV1(recordKey, Auth.DataKey).Base64UrlEncode(); updateRecord.revision = 0; } var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }; if (!skipData) { var dataSerializer = new DataContractJsonSerializer(typeof(RecordData), settings); RecordData existingData = null; if (existingRecord != null) { try { var unencrypted_data = CryptoUtils.DecryptAesV1(existingRecord.data.Base64UrlDecode(), existingRecord.unencryptedRecordKey); using (var ms = new MemoryStream(unencrypted_data)) { existingData = (RecordData)dataSerializer.ReadObject(ms); } } catch (Exception e) { Trace.TraceError("Decrypt Record: UID: {0}, {1}: \"{2}\"", existingRecord.recordUid, e.GetType().Name, e.Message); } } var data = record.ExtractRecordData(existingData); using (var ms = new MemoryStream()) { dataSerializer.WriteObject(ms, data); updateRecord.data = CryptoUtils.EncryptAesV1(ms.ToArray(), recordKey).Base64UrlEncode(); } } if (!skipExtra) { var extraSerializer = new DataContractJsonSerializer(typeof(RecordExtra), settings); RecordExtra existingExtra = null; if (existingRecord != null) { try { var unencrypted_extra = CryptoUtils.DecryptAesV1(existingRecord.extra.Base64UrlDecode(), existingRecord.unencryptedRecordKey); using (var ms = new MemoryStream(unencrypted_extra)) { existingExtra = (RecordExtra)extraSerializer.ReadObject(ms); } } catch (Exception e) { Trace.TraceError("Decrypt Record: UID: {0}, {1}: \"{2}\"", existingRecord.recordUid, e.GetType().Name, e.Message); } } var extra = record.ExtractRecordExtra(existingExtra); using (var ms = new MemoryStream()) { extraSerializer.WriteObject(ms, extra); updateRecord.extra = CryptoUtils.EncryptAesV1(ms.ToArray(), recordKey).Base64UrlEncode(); } var udata = new RecordUpdateUData(); var ids = new HashSet <string>(); if (record.Attachments != null) { foreach (var atta in record.Attachments) { ids.Add(atta.Id); if (atta.Thumbnails != null) { foreach (var thumb in atta.Thumbnails) { ids.Add(thumb.Id); } } } } udata.fileIds = ids.ToArray(); updateRecord.udata = udata; } var command = new RecordUpdateCommand(); if (existingRecord != null) { command.updateRecords = new RecordUpdateRecord[] { updateRecord }; } else { command.addRecords = new RecordUpdateRecord[] { updateRecord }; } var rs = await Auth.ExecuteAuthCommand <RecordUpdateCommand, RecordUpdateResponse>(command); await this.SyncDown(); }