Exemplo n.º 1
0
        /// <summary>
        /// Encrypts a file and returns the name of the encrypted file
        /// </summary>
        /// <param name="decrFilePath">The file name and path of the file to be encrypted</param>
        /// <param name="encrFilePath">The file name and path for th encrypted file to be saved</param>
        public static void Encrypt(string decrFilePath, string encrFilePath, DerivedBytesProvider derivedBytesProvider, FileEncryptOptions options = null)
        {
            if (string.IsNullOrWhiteSpace(decrFilePath))
            {
                throw new ArgumentNullException(nameof(decrFilePath));
            }
            if (string.IsNullOrEmpty(encrFilePath))
            {
                throw new ArgumentNullException(nameof(encrFilePath));
            }
            if (derivedBytesProvider == null)
            {
                throw new ArgumentNullException(nameof(derivedBytesProvider));
            }

            options ??= new FileEncryptOptions();

            var encrStagedFileName = encrFilePath + HelixConsts.StagedHxExtention;
            var encrBackupFileName = encrFilePath + HelixConsts.BackupExtention;

            if (!string.IsNullOrEmpty(Path.GetDirectoryName(encrStagedFileName)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(encrStagedFileName));
            }

            FileEntry header = FileEntry.FromFile(decrFilePath, Path.GetDirectoryName(decrFilePath));

            if (!string.IsNullOrWhiteSpace(options.StoredFileName))
            {
                header.FileName = options.StoredFileName;
            }

            using (Stream streamIn = (header.EntryType != FileEntryType.File)
                                       ? (Stream)(new MemoryStream())
                                       : File.Open(decrFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (var streamOut = File.Open(encrStagedFileName, FileMode.CreateNew, FileAccess.Write))
                    using (var encryptor = new HelixFileEncryptor(streamOut, derivedBytesProvider, options.FileVersion))
                    {
                        options.Log?.Invoke("Writing: Header");
                        options.BeforeWriteHeader?.Invoke(header);
                        encryptor.WriteHeader(header);

                        options.Log?.Invoke("Writing: Content");
                        encryptor.WriteContent(streamIn, streamIn.Length);
                    }


            if (File.Exists(encrFilePath))
            {
                if (File.Exists(encrBackupFileName))
                {
                    options.Log?.Invoke("Destaging: Removing incomplete backup");
                    File.Delete(encrBackupFileName);
                }

                options.Log?.Invoke("Destaging: Moving staged to normal");

                if (File.Exists(encrFilePath))
                {
                    File.Move(encrFilePath, encrBackupFileName);
                }
                File.Move(encrStagedFileName, encrFilePath);

                options.Log?.Invoke("Destaging: Removing backup");
                File.Delete(encrBackupFileName);
            }
            else
            {
                options.Log?.Invoke("Destaging: Moving staged to normal");
                File.Move(encrStagedFileName, encrFilePath);
            }
        }
Exemplo n.º 2
0
 public static void Encrypt(string decrFile, string encrFile, string password, FileEncryptOptions options = null)
 {
     Encrypt(decrFile, encrFile, DerivedBytesProvider.FromPassword(password), options);
 }
Exemplo n.º 3
0
        public SyncResults TrySync(PreSyncDetails entry, ConsoleEx console = null)
        {
            const int encrTimespanPrecisionMS = 1000;

            //todo: ensure the entry direction and operation end up being the same
            //todo: ensure all the calling methods do something with the results

            //if (WhatIf)
            //    throw new InvalidOperationException("Unable to perform sync when WhatIf mode is set to true");
            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }

            if (entry.SyncMode == PreSyncMode.DecryptedSide)
            {
                SyncLogEntry logEntry = entry.LogEntry;


                string             encrPath = Path.Combine(EncrDirectory.FullName, HelixUtil.PathNative(entry.EncrFileName));
                string             decrPath = Path.Combine(DecrDirectory.FullName, HelixUtil.PathNative(entry.DecrFileName));
                FileEncryptOptions options  = new FileEncryptOptions();
                FileEntry          header   = null;
                options.BeforeWriteHeader = (h) => header = h;
                options.StoredFileName    = entry.DecrFileName;
                options.FileVersion       = Header.FileVersion;
                options.Log = (s) => console?.WriteLine(VerbosityLevel.Diagnostic, 1, s);

                if (WhatIf)
                {
                    EncrDirectory.WhatIfReplaceFile(encrPath, entry.DisplayFileLength);
                    if (entry.DecrInfo == null)
                    {
                        header = new FileEntry()
                        {
                            EntryType = FileEntryType.Removed,
                            FileName  = entry.DecrFileName,
                        };
                    }
                    else
                    {
                        header = entry.DecrInfo.ToFileEntry();
                    }
                }
                else
                {
                    HelixFile.Encrypt(decrPath, encrPath, DerivedBytesProvider, options);


                    //forces a change if the file was modified to quickly
                    if (logEntry != null && (File.GetLastWriteTimeUtc(encrPath) - logEntry.EncrModified).TotalMilliseconds < encrTimespanPrecisionMS)
                    {
                        File.SetLastWriteTimeUtc(encrPath, logEntry.EncrModified + TimeSpan.FromMilliseconds(encrTimespanPrecisionMS));
                    }

                    EncrDirectory.RefreshEntry(encrPath);
                }
                var newLogEntry = CreateEntryFromHeader(header, EncrDirectory.TryGetEntry(entry.EncrFileName));
                SyncLog.Add(newLogEntry);


                return(SyncResults.Success());
            }
            else if (entry.SyncMode == PreSyncMode.EncryptedSide)
            {
                if (entry.DisplayOperation == PreSyncOperation.Purge)
                {
                    SyncLog.Add(entry.GetUpdatedLogEntry());
                    return(SyncResults.Success());
                }
                else
                {
                    //todo: use the DisplayOperation to determine what to do (ensures the counts stay consistant)

                    SyncLogEntry logEntry        = entry.LogEntry;
                    SyncLogEntry fileSystemEntry = CreateNewLogEntryFromEncrPath(entry.EncrFileName);
                    if (logEntry?.ToString() == fileSystemEntry?.ToString())
                    {
                        return(SyncResults.Success()); //Unchanged
                    }
                    //todo: test to see if there are illegal characters
                    //todo: check if the name matches

                    string encrPath = HelixUtil.JoinNative(EncrDirectory.FullName, fileSystemEntry.EncrFileName);
                    string decrPath = HelixUtil.JoinNative(DecrDirectory.FullName, fileSystemEntry.DecrFileName);

                    //todo: if file exists with different case - skip file
                    var     exactPath = HelixUtil.GetExactPathName(decrPath);
                    FSEntry decrEntry = DecrDirectory.TryGetEntry(fileSystemEntry.DecrFileName);

                    if (decrEntry != null && decrEntry.RelativePath != fileSystemEntry.DecrFileName)
                    {
                        //todo: throw more specific exception
                        return(SyncResults.Failure(new HelixException($"Case only conflict file \"{decrPath}\" exists as \"{exactPath}\".")));
                    }

                    if (WhatIf)
                    {
                        if (entry.EncrHeader.EntryType == FileEntryType.File)
                        {
                            DecrDirectory.WhatIfReplaceFile(decrPath, entry.EncrHeader.Length, entry.EncrHeader.LastWriteTimeUtc);
                        }
                        else if (entry.EncrHeader.EntryType == FileEntryType.Removed)
                        {
                            DecrDirectory.WhatIfDeleteFile(decrPath);
                        }
                        else if (entry.EncrHeader.EntryType == FileEntryType.Directory)
                        {
                            DecrDirectory.WhatIfAddDirectory(decrPath);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                    }
                    else
                    {
                        HelixFile.Decrypt(encrPath, decrPath, DerivedBytesProvider);
                        //todo: get the date on the file system (needed if the filesystem has less precision
                        DecrDirectory.RefreshEntry(decrPath);
                    }

                    SyncLog.Add(fileSystemEntry);

                    return(SyncResults.Success());
                }
            }
            else if (entry.SyncMode == PreSyncMode.Match)
            {
                //Add to Log file (changed to be equal on both sides)
                SyncLogEntry fileSystemEntry = CreateNewLogEntryFromDecrPath(entry.DecrFileName);
                SyncLog.Add(fileSystemEntry);
                return(SyncResults.Success());
            }
            else if (entry.SyncMode == PreSyncMode.Unchanged)
            {
                //do nothing
                return(SyncResults.Success());
            }

            return(SyncResults.Failure(new HelixException($"Invalid sync mode {entry.SyncMode}")));
        }