Example #1
0
        public static DirectoryHeader Load(string filePath, DerivedBytesProvider derivedBytesProvider)
        {
            DirectoryHeader directoryHeader = new DirectoryHeader();

            using Stream streamIn = File.OpenRead(filePath);
            using HelixFileDecryptor decryptor = new HelixFileDecryptor(streamIn);
            decryptor.Initialize(derivedBytesProvider);
            directoryHeader.FileVersion = decryptor.FileVersion;

            directoryHeader.Header      = decryptor.ReadHeader();
            directoryHeader.FileVersion = decryptor.FileVersion;

            var contentSerialized = decryptor.GetContentString();

            //var contentDeserialized = JsonConvert.DeserializeAnonymousType(contentSerialized, new { EncryptedFileNameSalt = new byte[] { } });
            JsonConvert.PopulateObject(contentSerialized, directoryHeader);

            if (!Regex.IsMatch(directoryHeader.DirectoryId, "^[0-9A-F]{32}$"))
            {
                throw new HelixException("Data curruption directory header, DirectoryId malformed");
            }
            if (directoryHeader.FileNameKey == null || directoryHeader.FileNameKey.Length != 32)
            {
                throw new HelixException("Data curruption directory header, FileNameKey missing or insufficient length");
            }

            return(directoryHeader);
        }
Example #2
0
        /// <summary>
        /// Returns the header for an encrypted file
        /// </summary>
        public static FileEntry DecryptHeader(string encrFile, DerivedBytesProvider derivedBytesProvider)
        {
            using var inputStream = File.OpenRead(encrFile);
            using var decryptor   = new HelixFileDecryptor(inputStream);
            try
            {
                decryptor.Initialize(derivedBytesProvider);

                FileEntry header = decryptor.ReadHeader();

                if (!header.IsValid(out HeaderCorruptionException ex))
                {
                    throw ex;
                }

                return(header);
            }
            catch (FileCorruptionException ex)
            {
                throw new FileCorruptionException($"Failed to decrypt {encrFile}, {ex.Message}", ex);
            }
            catch (AuthenticatedEncryptionException ex)
            {
                throw new FileCorruptionException($"Failed to decrypt {encrFile}, {ex.Message}", ex);
            }
        }
Example #3
0
        public static int Inspect(InspectOptions options, ConsoleEx consoleEx = null)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            consoleEx ??= new ConsoleEx();

            using (Stream fileIn = File.OpenRead(options.File))
                using (HelixFileDecryptor decryptor = new HelixFileDecryptor(fileIn))
                {
                    consoleEx.WriteLine("== Outer Header ==");
                    Dictionary <string, byte[]> header = null;
                    decryptor.Initialize(DerivedBytesProvider.FromPassword(options.Password, options.KeyFile), (h) => header = h);
                    consoleEx.WriteLine("Designator:    "
                                        + BitConverter.ToString(header[nameof(FileHeader.fileDesignator)]).Replace("-", "")
                                        + " (" + new string(Encoding.ASCII.GetString(header[nameof(FileHeader.fileDesignator)])
                                                            .Select(c => Char.IsControl(c) ? '?' : c)
                                                            .ToArray()) + ")");
                    consoleEx.WriteLine("Password Salt: " + BitConverter.ToString(header[nameof(FileHeader.passwordSalt)]).Replace("-", ""));
                    consoleEx.WriteLine("HMAC Salt:     " + BitConverter.ToString(header[nameof(FileHeader.hmacSalt)]).Replace("-", ""));
                    consoleEx.WriteLine("IV:            " + BitConverter.ToString(header[nameof(FileHeader.iv)]).Replace("-", ""));
                    consoleEx.WriteLine("Authn (HMAC):  " + BitConverter.ToString(header[nameof(FileHeader.headerAuthnDisk)]).Replace("-", ""));
                    consoleEx.WriteLine();

                    consoleEx.WriteLine("== Inner Header ==");
                    decryptor.ReadHeader(
                        afterRawMetadata: (r) => consoleEx.WriteLine(JsonFormat(r)));
                    consoleEx.WriteLine();

                    using Stream content = decryptor.GetContentStream();
                    ContentPreview(content, consoleEx, options.ContentFormat);
                    consoleEx.WriteLine();
                }

            //Reopen to calculate the checksum
            using (Stream fileIn = File.OpenRead(options.File))
                using (HelixFileDecryptor decryptor = new HelixFileDecryptor(fileIn))
                {
                    decryptor.Initialize(DerivedBytesProvider.FromPassword(options.Password, options.KeyFile));
                    decryptor.ReadHeader();
                    using Stream content = decryptor.GetContentStream();
                    Checksum(content, consoleEx);


                    return(0);
                }
        }
Example #4
0
        public static string Decrypt(string encrPath, string decrPath, DerivedBytesProvider derivedBytesProvider, FileDecryptOptions options = null)
        {
            if (string.IsNullOrWhiteSpace(encrPath))
            {
                throw new ArgumentNullException(nameof(encrPath));
            }
            if (string.IsNullOrWhiteSpace(decrPath))
            {
                throw new ArgumentNullException(nameof(decrPath));
            }
            if (derivedBytesProvider == null)
            {
                throw new ArgumentNullException(nameof(derivedBytesProvider));
            }

            options ??= new FileDecryptOptions();

            using (FileStream inputStream = File.OpenRead(encrPath))
                using (HelixFileDecryptor decryptor = new HelixFileDecryptor(inputStream))
                {
                    decryptor.Initialize(derivedBytesProvider);

                    FileEntry header = decryptor.ReadHeader();

                    options?.AfterMetadataRead?.Invoke(header, options);

                    if (!header.IsValid(out HeaderCorruptionException ex))
                    {
                        throw ex;
                    }

                    string decrFullFileName   = decrPath;
                    string decrStagedFileName = decrPath + HelixConsts.StagedHxExtention;
                    string decrBackupFileName = decrPath + HelixConsts.BackupExtention;

                    if (header.EntryType == FileEntryType.File)
                    {
                        if (!string.IsNullOrEmpty(Path.GetDirectoryName(decrStagedFileName)))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(decrStagedFileName));
                        }

                        using (var contentStream = decryptor.GetContentStream())
                            using (var stagedFile = File.OpenWrite(decrStagedFileName))
                            {
                                contentStream.CopyTo(stagedFile);
                            }
                        File.SetLastWriteTimeUtc(decrStagedFileName, header.LastWriteTimeUtc);


                        if (File.Exists(decrFullFileName))
                        {
                            File.Move(decrFullFileName, decrBackupFileName);
                        }
                        else if (Directory.Exists(decrFullFileName))
                        {
                            if (Directory.GetFiles(decrFullFileName).Length > 0)
                            {
                                throw new IOException($"Unable to process entry, directory is not empty ({decrFullFileName})");
                            }
                            Directory.Move(decrFullFileName, decrBackupFileName);
                        }

                        File.Move(decrStagedFileName, decrFullFileName);

                        if (File.Exists(decrBackupFileName))
                        {
                            File.SetAttributes(decrBackupFileName, FileAttributes.Normal); //incase it was read only
                            File.Delete(decrBackupFileName);
                        }
                        else if (Directory.Exists(decrBackupFileName))
                        {
                            Directory.Delete(decrBackupFileName);
                        }
                    }
                    else if (header.EntryType == FileEntryType.Directory)
                    {
                        if (File.Exists(decrFullFileName))
                        {
                            File.Move(decrFullFileName, decrBackupFileName);
                        }

                        if (Directory.Exists(decrFullFileName))
                        {
                            //If there is a case difference need to delete the directory
                            if (Path.GetFileName(decrFullFileName) != Path.GetFileName(new DirectoryInfo(decrFullFileName).Name))
                            {
                                if (Directory.GetFiles(decrFullFileName).Length > 0)
                                {
                                    throw new IOException($"Unable to process entry, directory is not empty ({decrFullFileName})");
                                }
                                Directory.Move(decrFullFileName, decrBackupFileName);
                            }
                        }


                        Directory.CreateDirectory(decrFullFileName);
                    }
                    else //purge or delete
                    {
                        if (File.Exists(decrFullFileName))
                        {
                            File.Move(decrFullFileName, decrBackupFileName);
                        }
                        else if (Directory.Exists(decrFullFileName))
                        {
                            if (Directory.GetFiles(decrFullFileName).Length > 0)
                            {
                                throw new IOException($"Unable to process entry, directory is not empty ({decrFullFileName})");
                            }
                            Directory.Move(decrFullFileName, decrBackupFileName);
                        }
                    }

                    if (File.Exists(decrBackupFileName))
                    {
                        File.Delete(decrBackupFileName);
                    }
                    else if (Directory.Exists(decrBackupFileName))
                    {
                        Directory.Delete(decrBackupFileName);
                    }
                }
            return(decrPath);
        }