Ejemplo n.º 1
0
        public static RecordExtra ExtractRecordExtra(this PasswordRecord record, RecordExtra existingExtra = null)
        {
            IDictionary <string, RecordExtraFile> extraFiles = null;

            if (existingExtra != null && existingExtra.files != null && existingExtra.files.Length > 0)
            {
                extraFiles = new Dictionary <string, RecordExtraFile>();
                foreach (var f in existingExtra.files)
                {
                    extraFiles.Add(f.id, f);
                }
            }
            return(new RecordExtra
            {
                files = record.Attachments?.Select(x =>
                {
                    RecordExtraFile extraFile;
                    if (extraFiles != null)
                    {
                        if (extraFiles.TryGetValue(x.Id, out extraFile))
                        {
                            return extraFile;
                        }
                    }
                    extraFile = new RecordExtraFile
                    {
                        id = x.Id,
                        key = x.Key,
                        name = x.Name,
                        title = x.Title ?? x.Name,
                        size = x.Size,
                        type = x.Type
                    };
                    if (x.Thumbnails != null && x.Thumbnails.Length > 0)
                    {
                        extraFile.thumbs = x.Thumbnails.Select(y =>
                                                               new RecordExtraFileThumb
                        {
                            id = y.Id,
                            size = y.Size,
                            type = y.Type
                        })
                                           .ToArray();
                    }
                    return extraFile;
                }).ToArray(),
                ExtensionData = existingExtra?.ExtensionData
            });
        }
Ejemplo n.º 2
0
 public static RecordData ExtractRecordData(this PasswordRecord record, RecordData existingData = null)
 {
     return(new RecordData
     {
         title = record.Title,
         folder = existingData?.folder,
         secret1 = record.Login,
         secret2 = record.Password,
         link = record.Link,
         notes = record.Notes,
         custom = record.Custom?.Select(x => new RecordDataCustom
         {
             name = x.Name,
             value = x.Value,
             type = x.Type
         }).ToArray()
     });
 }
Ejemplo n.º 3
0
        internal static void DecryptRecords(this Vault vault)
        {
            var uids = new HashSet <string>();

            uids.UnionWith(vault.records.Keys);
            uids.ExceptWith(vault.keeperRecords.Keys);
            if (uids.Count > 0)
            {
                var dataSerializer  = new DataContractJsonSerializer(typeof(RecordData));
                var extraSerializer = new DataContractJsonSerializer(typeof(RecordExtra));

                foreach (var uid in uids)
                {
                    if (vault.records.TryGetValue(uid, out SyncDownRecord sdr))
                    {
                        try
                        {
                            var record = new PasswordRecord(uid);

                            var unencrypted_data = CryptoUtils.DecryptAesV1(sdr.data.Base64UrlDecode(), sdr.unencryptedRecordKey);
                            using (var ms = new MemoryStream(unencrypted_data))
                            {
                                var data = (RecordData)dataSerializer.ReadObject(ms);
                                record.Title    = data.title;
                                record.Login    = data.secret1;
                                record.Password = data.secret2;
                                record.Link     = data.link;
                                record.Notes    = data.notes;
                                if (data.custom != null)
                                {
                                    foreach (var cr in data.custom)
                                    {
                                        record.Custom.Add(new CustomField
                                        {
                                            Name  = cr.name,
                                            Value = cr.value,
                                            Type  = cr.type
                                        });
                                    }
                                }
                            }

                            if (!string.IsNullOrEmpty(sdr.extra))
                            {
                                var unencrypted_extra = CryptoUtils.DecryptAesV1(sdr.extra.Base64UrlDecode(), sdr.unencryptedRecordKey);
                                using (var ms = new MemoryStream(unencrypted_extra))
                                {
                                    var extra = (RecordExtra)extraSerializer.ReadObject(ms);
                                    if (extra.files != null && extra.files.Length > 0)
                                    {
                                        foreach (var file in extra.files)
                                        {
                                            var atta = new AttachmentFile
                                            {
                                                Id           = file.id,
                                                Key          = file.key,
                                                Name         = file.name,
                                                Title        = file.title ?? "",
                                                Type         = file.type ?? "",
                                                Size         = file.size ?? 0,
                                                LastModified = file.lastModified != null?file.lastModified.Value.FromUnixTimeMilliseconds() : DateTimeOffset.Now
                                            };
                                            if (file.thumbs != null)
                                            {
                                                atta.Thumbnails = file.thumbs
                                                                  .Select(t => new AttachmentFileThumb
                                                {
                                                    Id   = t.id,
                                                    Type = t.type,
                                                    Size = t.size ?? 0
                                                })
                                                                  .ToArray();
                                            }
                                            record.Attachments.Add(atta);
                                        }
                                    }
                                }
                            }

                            vault.keeperRecords.Add(uid, record);
                        }
                        catch (Exception e)
                        {
                            Trace.TraceError("Decrypt Record: UID: {0}, {1}: \"{2}\"", uid, e.GetType().Name, e.Message);
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public static async Task UploadAttachment(this Vault vault, PasswordRecord record, IAttachmentUploadTask uploadTask)
        {
            var fileStream = uploadTask.Stream;

            if (fileStream == null)
            {
                throw new KeeperInvalidParameter("Vault::UploadAttachment", "uploadTask", "GetStream()", "null");
            }
            var thumbStream = uploadTask.Thumbnail?.Stream;
            var command     = new RequestUploadCommand();

            command.fileCount      = 1;
            command.thumbnailCount = thumbStream != null ? 1 : 0;

            var rs = await vault.Auth.ExecuteAuthCommand <RequestUploadCommand, RequestUpoadResponse>(command);

            if (rs.fileUploads == null || rs.fileUploads.Length < 1)
            {
                throw new KeeperInvalidParameter("Vault::UploadAttachment", "request_upload", "file_uploads", "empty");
            }

            UploadParameters fileUpload  = rs.fileUploads[0];
            UploadParameters thumbUpload = null;

            if (rs.thumbnailUploads != null && rs.thumbnailUploads.Length > 0)
            {
                thumbUpload = rs.thumbnailUploads[0];
            }

            var key  = CryptoUtils.GenerateEncryptionKey();
            var atta = new AttachmentFile {
                Id           = fileUpload.fileID,
                Name         = uploadTask.Name,
                Title        = uploadTask.Title,
                Key          = key.Base64UrlEncode(),
                Type         = uploadTask.MimeType,
                LastModified = DateTimeOffset.Now,
            };
            var transform = new EncryptAesV1Transform(key);

            using (var cryptoStream = new CryptoStream(fileStream, transform, CryptoStreamMode.Read)) {
                await UploadSingleFile(fileUpload, cryptoStream);

                atta.Size = transform.EncryptedBytes;
            }
            if (thumbUpload != null)
            {
                try {
                    transform = new EncryptAesV1Transform(key);
                    using (var cryptoStream = new CryptoStream(thumbStream, transform, CryptoStreamMode.Read))
                    {
                        await UploadSingleFile(thumbUpload, cryptoStream);
                    }
                    var thumbnail = new AttachmentFileThumb
                    {
                        Id   = thumbUpload.fileID,
                        Type = uploadTask.Thumbnail.MimeType,
                        Size = uploadTask.Thumbnail.Size
                    };
                    var ts = new AttachmentFileThumb[] { thumbnail };
                    if (atta.Thumbnails == null)
                    {
                        atta.Thumbnails = ts;
                    }
                    else
                    {
                        atta.Thumbnails = atta.Thumbnails.Concat(ts).ToArray();
                    }
                }
                catch (Exception e) {
                    Trace.TraceError("Upload Thumbname: {0}: \"{1}\"", e.GetType().Name, e.Message);
                }
            }

            record.Attachments.Add(atta);
        }
Ejemplo n.º 5
0
        public static async Task DownloadAttachment(this Vault vault, PasswordRecord record, string attachment, Stream destination)
        {
            if (record.Attachments == null)
            {
                throw new KeeperInvalidParameter("Vault::DownloadAttachment", "record", record.Uid, "has no attachments");
            }
            AttachmentFile attachmentFile = null;

            if (string.IsNullOrEmpty(attachment))
            {
                if (record.Attachments.Count == 1)
                {
                    attachmentFile = record.Attachments[0];
                }
                else
                {
                    throw new KeeperInvalidParameter("Vault::DownloadAttachment", "attachment", "", "is empty");
                }
            }
            else
            {
                attachmentFile = record.Attachments
                                 .FirstOrDefault(x =>
                {
                    if (attachment == x.Id || attachment == x.Name || attachment == x.Title)
                    {
                        return(true);
                    }
                    if (x.Thumbnails != null)
                    {
                        var thumbId = x.Thumbnails.Select(y => y.Id).FirstOrDefault(y => y == attachment);
                        if (!string.IsNullOrEmpty(thumbId))
                        {
                            return(true);
                        }
                    }
                    return(false);
                });
            }
            if (attachmentFile == null)
            {
                throw new KeeperInvalidParameter("Vault::DownloadAttachment", "attachment", attachment, "not found");
            }

            var attachmentId = attachmentFile.Id;

            if (attachmentFile.Thumbnails != null)
            {
                foreach (var th in attachmentFile.Thumbnails)
                {
                    if (th.Id == attachment)
                    {
                        attachmentId = th.Id;
                        break;
                    }
                }
            }

            var request = await CreateAttachmentDownloadRequest(vault, record.Uid, attachmentId);

            using (var response = await request.GetResponseAsync() as HttpWebResponse)
            {
                using (var stream = response.GetResponseStream())
                {
                    var transform = new DecryptAesV1Transform(attachmentFile.Key.Base64UrlDecode());
                    using (var decodeStream = new CryptoStream(stream, transform, CryptoStreamMode.Read))
                    {
                        if (destination != null)
                        {
                            await decodeStream.CopyToAsync(destination);
                        }
                    }
                }
            }
        }
Ejemplo n.º 6
0
        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();
        }
Ejemplo n.º 7
0
        public async Task AddRecord(PasswordRecord record, string folderUid)
        {
            IFolderNode node = null;

            if (!string.IsNullOrEmpty(folderUid))
            {
                userFolders.TryGetValue(folderUid, out node);
            }
            var recordKey = CryptoUtils.GenerateEncryptionKey();
            var recordAdd = new RecordAddCommand
            {
                recordUid  = CryptoUtils.GenerateUid(),
                recordKey  = CryptoUtils.EncryptAesV1(recordKey, Auth.DataKey).Base64UrlEncode(),
                recordType = "password"
            };

            if (node == null)
            {
                recordAdd.folderType = "user_folder";
            }
            else
            {
                switch (node.Type)
                {
                case FolderType.UserFolder:
                    recordAdd.folderType = "user_folder";
                    recordAdd.folderUid  = node.FolderUid;
                    break;

                case FolderType.SharedFolder:
                case FolderType.SharedFolderForder:
                    recordAdd.folderUid  = node.FolderUid;
                    recordAdd.folderType = node.Type == FolderType.SharedFolder ? "shared_folder" : "shared_folder_folder";
                    if (node is ISharedFolderNode sfn)
                    {
                        if (sharedFolders.TryGetValue(sfn.SharedFolderUid, out SyncDownSharedFolder sf))
                        {
                            recordAdd.folderKey = CryptoUtils.EncryptAesV1(recordKey, sf.unencryptedSharedFolderKey).Base64UrlEncode();
                        }
                    }
                    if (string.IsNullOrEmpty(recordAdd.folderKey))
                    {
                        throw new Exception(string.Format("Cannot resolve shared folder for folder UID", folderUid));
                    }
                    break;
                }
            }
            var settings = new DataContractJsonSerializerSettings
            {
                UseSimpleDictionaryFormat = true
            };
            var dataSerializer = new DataContractJsonSerializer(typeof(RecordData), settings);
            var data           = record.ExtractRecordData();

            using (var ms = new MemoryStream())
            {
                dataSerializer.WriteObject(ms, data);
                recordAdd.data = CryptoUtils.EncryptAesV1(ms.ToArray(), recordKey).Base64UrlEncode();
            }

            await Auth.ExecuteAuthCommand <RecordAddCommand>(recordAdd);

            await this.SyncDown();
        }
Ejemplo n.º 8
0
 public bool TryGetRecord(string recordUid, out PasswordRecord node)
 {
     return(keeperRecords.TryGetValue(recordUid, out node));
 }