public void InitializeFull(ConsoleEx consoleEx, HelixFileVersion fileVersion = null) { PreInitializationCheck(); //Initialize Encr Directory consoleEx?.WriteLine(VerbosityLevel.Detailed, 0, "Initializing Encrypted Directory..."); Header = DirectoryHeader.New(); EncrDirectory.Create(); if (WhatIf) { EncrDirectory.WhatIfAddFile(HelixConsts.HeaderFileName, 10); } else { Header.Save(EncrDirectory.PathFull(HelixConsts.HeaderFileName), DerivedBytesProvider, fileVersion); EncrDirectory.RefreshEntry(HelixConsts.HeaderFileName); } this.FileNameEncoder = new FileNameEncoder(Header.FileNameKey); consoleEx?.WriteLine(VerbosityLevel.Detailed, 1, "Encrypted Directory Initialized (" + Header.DirectoryId.Substring(0, 6) + "...)"); InitializeDecr(consoleEx); }
public void Initialize(DerivedBytesProvider derivedBytesProvider, Action <Dictionary <string, byte[]> > afterHeaderRead = null) { if (derivedBytesProvider == null) { throw new ArgumentNullException(nameof(derivedBytesProvider)); } //header //FileDesignator (8 bytes) + passwordSalt (32 bytes) + hmac salt (32 bytes) + iv (32 bytes) FileHeader header = new FileHeader(); StreamRead(streamIn, header.fileDesignator); StreamRead(streamIn, header.passwordSalt); StreamRead(streamIn, header.hmacSalt); StreamRead(streamIn, header.iv); StreamRead(streamIn, header.headerAuthnDisk); afterHeaderRead?.Invoke(header.ToDictionary()); FileVersion = HelixFileVersion.GetVersion(header.fileDesignator); if (FileVersion == null) { throw new FileDesignatorException("Invalid file format, file designator not correct"); } DerivedBytes = derivedBytesProvider.GetDerivedBytes(header.passwordSalt, FileVersion.DerivedBytesIterations); byte[] headerBytes = header.GetBytesToHash(); byte[] hmacFullKey = ByteBlock.ConcatenateBytes(header.hmacSalt, DerivedBytes.Key); hmacHash = new HMACSHA256(hmacFullKey); //Validate Header HMAC byte[] headerAuthnComputed = hmacHash.ComputeHash(headerBytes); if (!ByteBlock.Equals(header.headerAuthnDisk, headerAuthnComputed)) { throw new HMACAuthenticationException("Header HMAC Authentication Failed"); } hmacTransform = new HMACDecrypt(headerAuthnComputed, hmacHash); hmacStream = new CryptoStream2(streamIn, hmacTransform, CryptoStreamMode.Read); aesTransform = Aes.Create(); aesTransform.KeySize = 256; aesTransform.BlockSize = 128; aesTransform.Mode = CipherMode.CBC; aesTransform.Padding = PaddingMode.PKCS7; aesTransform.IV = header.iv; aesTransform.Key = DerivedBytes.Key; aesStream = new CryptoStream2(hmacStream, aesTransform.CreateDecryptor(), CryptoStreamMode.Read); gzipStream = new GZipStream(aesStream, CompressionMode.Decompress, true); initialized = true; }
public HelixFileEncryptor(Stream streamOut, DerivedBytesProvider derivedBytesProvider, HelixFileVersion fileVersion = null) { if (streamOut == null) { throw new ArgumentNullException(nameof(streamOut)); } if (!streamOut.CanWrite) { throw new ArgumentException("streamOut must be writable", nameof(streamOut)); } if (derivedBytesProvider == null) { throw new ArgumentNullException(nameof(derivedBytesProvider)); } this.FileVersion = fileVersion ?? HelixFileVersion.Default; this.StreamOut = streamOut; this.DerivedBytes = derivedBytesProvider.GetDerivedBytes(FileVersion.DerivedBytesIterations); }
public void Save(string filePath, DerivedBytesProvider derivedBytesProvider, HelixFileVersion fileVersion = null) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException(nameof(filePath)); } if (derivedBytesProvider == null) { throw new ArgumentNullException(nameof(derivedBytesProvider)); } FileVersion = fileVersion ?? HelixFileVersion.Default; using Stream streamOut = File.Open(filePath, FileMode.Create, FileAccess.Write); using HelixFileEncryptor encryptor = new HelixFileEncryptor(streamOut, derivedBytesProvider, fileVersion); encryptor.WriteHeader(Header); var contentSerialized = JsonConvert.SerializeObject(this); encryptor.WriteContent(contentSerialized); }
public MultiBlockEncryptor(Stream streamOut, DerivedBytes derivedBytes, HelixFileVersion fileVersion) : base(new AuthenticatedEncryptor(streamOut, derivedBytes, fileVersion)) { }
public AuthenticatedEncryptor(Stream streamOut, DerivedBytes derivedBytes, HelixFileVersion hxVersion, byte[] hmacSalt = null, byte[] iv = null) { if (derivedBytes == null) { throw new ArgumentNullException(nameof(derivedBytes)); } if (hxVersion == null) { throw new ArgumentNullException(nameof(hxVersion)); } if (hmacSalt != null && hmacSalt.Length != HelixConsts.HMACSaltSize) { throw new ArgumentOutOfRangeException(nameof(hmacSalt)); } if (iv != null && iv.Length != HelixConsts.IVSize) { throw new ArgumentOutOfRangeException(nameof(iv)); } using (var random = RandomNumberGenerator.Create()) { if (hmacSalt == null) { hmacSalt = new byte[HelixConsts.HMACSaltSize]; random.GetBytes(hmacSalt); } if (iv == null) { iv = new byte[HelixConsts.IVSize]; random.GetBytes(iv); } } FileHeader header = new FileHeader { fileDesignator = hxVersion.FileDesignator, passwordSalt = derivedBytes.Salt, hmacSalt = hmacSalt, iv = iv, }; byte[] hmacFullKey = ByteBlock.ConcatenateBytes(hmacSalt, derivedBytes.Key); this.streamOut = streamOut ?? throw new ArgumentNullException(nameof(streamOut)); byte[] bytesToHash = header.GetBytesToHash(); streamOut.Write(bytesToHash, 0, bytesToHash.Length); hmacHash = new HMACSHA256(hmacFullKey); header.headerAuthnDisk = hmacHash.ComputeHash(header.GetBytesToHash()); streamOut.Write(header.headerAuthnDisk, 0, header.headerAuthnDisk.Length); hmacTransform = new HMACEncrypt(header.headerAuthnDisk, hmacHash); hmacStream = new CryptoStream(streamOut, hmacTransform, CryptoStreamMode.Write); aesTransform = Aes.Create(); aesTransform.KeySize = 256; aesTransform.BlockSize = 128; aesTransform.Mode = CipherMode.CBC; aesTransform.Padding = PaddingMode.PKCS7; aesTransform.IV = iv; aesTransform.Key = derivedBytes.Key; aesStream = new CryptoStream(hmacStream, aesTransform.CreateEncryptor(), CryptoStreamMode.Write); gzipStream = new GZipStream(aesStream, CompressionMode.Compress, true); }
public static DirectoryPair Open(string decrDirectoryPath, string encrDirectoryPath, DerivedBytesProvider derivedBytesProvider, bool initialize = false, HelixFileVersion fileVersion = null) { if (derivedBytesProvider == null) { throw new ArgumentNullException(nameof(derivedBytesProvider)); } DirectoryPair pair = new DirectoryPair(decrDirectoryPath, encrDirectoryPath, derivedBytesProvider, false); if (initialize && pair.InitializeFullNeeded()) { pair.InitializeFull(null, fileVersion); } pair.OpenEncr(null); if (initialize && pair.InitializeDecrNeeded()) { pair.InitializeDecr(null); } pair.OpenDecr(null); return(pair); }
public static SyncSummary Sync(SyncOptions options, ConsoleEx consoleEx = null, HelixFileVersion fileVersion = null) { var sum = new SyncSummary(); consoleEx ??= new ConsoleEx(); consoleEx.Verbosity = options.Verbosity; consoleEx.WriteLine("Sync"); if (options.WhatIf) { consoleEx.WriteLine("..Options: WhatIf"); } consoleEx.WriteLine($"..DecrDir: {options.DecrDirectory}"); consoleEx.WriteLine($"..EncrDir: {options.EncrDirectory}"); //consoleEx.WriteLine($"..Direction: {options.Direction}"); consoleEx.WriteLine($"..Verbosity: {options.Verbosity}"); consoleEx.WriteLine(); if (options.WhatIf) { consoleEx.WriteLine("** WhatIf Mode - No Changes Made **"); consoleEx.WriteLine(""); } DerivedBytesProvider derivedBytesProvider = DerivedBytesProvider.FromPassword(options.Password, options.KeyFile); using DirectoryPair pair = new DirectoryPair(options.DecrDirectory, options.EncrDirectory, derivedBytesProvider, options.WhatIf); pair.PreInitializationCheck(); if (pair.InitializeFullNeeded()) { if (options.Initialize) { //continue, unprompted if (pair.InitializeMergeWarning()) { consoleEx.WriteLine("WARNING: Decrypted directory is not empty and will be merged"); } } else { consoleEx.WriteLine("Directories require initialization..."); if (!consoleEx.PromptBool("Initialized encrypted and decrypted directories now? [y/N] ", false)) { consoleEx.WriteErrorLine("Operation cancelled"); sum.Error = new InitializationCanceledException(); return(sum); } if (pair.InitializeMergeWarning()) { if (!consoleEx.PromptBool("Decrypted directory is not empty and will be merged, continue? [y/N] ", false)) { consoleEx.WriteErrorLine("Operation cancelled"); sum.Error = new InitializationCanceledException(); return(sum); } } } pair.InitializeFull(consoleEx); } pair.OpenEncr(consoleEx); if (pair.InitializeDecrNeeded()) { if (options.Initialize) { //continue, unprompted if (pair.InitializeMergeWarning()) { consoleEx.WriteLine("WARNING: Decrypted directory is not empty and will be merged"); } } else { consoleEx.WriteLine("Decrypted directory require initialization..."); if (!consoleEx.PromptBool("Initialized decrypted directories now? [y/N] ", false)) { consoleEx.WriteErrorLine("Operation cancelled"); sum.Error = new InitializationCanceledException(); return(sum); } if (pair.InitializeMergeWarning()) { if (!consoleEx.PromptBool("Decrypted directory is not empty and will be merged, continue? [y/N] ", false)) { consoleEx.WriteErrorLine("Operation cancelled"); sum.Error = new InitializationCanceledException(); return(sum); } } } pair.InitializeDecr(consoleEx); } pair.OpenDecr(consoleEx); pair.Cleanup(consoleEx); List <PreSyncDetails> changes = pair.FindChanges(clearCache: false, console: consoleEx); if (changes.Count == 0) { consoleEx.WriteLine("--No Changes--"); } var defaultConflictAction = ""; consoleEx.WriteLine(VerbosityLevel.Normal, 0, "Performing Sync..."); foreach (PreSyncDetails change in changes) { consoleEx.WriteLine(change); if (change.SyncMode == PreSyncMode.Conflict) { var decrModified = change.DecrInfo == null ? (object)null : change.DecrInfo.LastWriteTimeUtc.ToLocalTime(); var decrSize = change.DecrInfo == null ? (object)null : HelixUtil.FormatBytes5(change.DecrInfo.Length); var encrModified = change.EncrInfo == null ? (object)null : change.EncrInfo.LastWriteTimeUtc.ToLocalTime(); var encrSize = change.EncrHeader == null ? (object)null : HelixUtil.FormatBytes5(change.EncrHeader.Length); string response; if (defaultConflictAction != "") { response = defaultConflictAction; } else { consoleEx.WriteLine($" Decrypted - Modified: {decrModified}, Size: {decrSize}"); consoleEx.WriteLine($" Encrypted - Modified: {encrModified}, Size: {encrSize}"); consoleEx.WriteLine($""); consoleEx.WriteLine($" D - Decrypted, E - Encrypted, S - Skip, + Always perform this action"); //todo: support newer, support always response = consoleEx.PromptChoice(" Select Option [D,E,S,D+,E+,S+]? ", new string[] { "D", "E", "S", "D+", "E+", "S+" }, "S"); if (response.EndsWith("+")) { response = response.Substring(0, 1); defaultConflictAction = response; } } if (response == "D") { change.SyncMode = PreSyncMode.DecryptedSide; } else if (response == "E") { change.SyncMode = PreSyncMode.EncryptedSide; } if (change.SyncMode != PreSyncMode.Conflict) { consoleEx.WriteLine(change); } } if (change.SyncMode == PreSyncMode.EncryptedSide) { //todo: make display operation be the actual operation if (change.DisplayOperation == PreSyncOperation.Add) { sum.EncrAdd++; } else if (change.DisplayOperation == PreSyncOperation.Remove) { sum.EncrRemove++; } else if (change.DisplayOperation == PreSyncOperation.Change) { sum.EncrChange++; } else { sum.EncrOther++; } } else if (change.SyncMode == PreSyncMode.DecryptedSide) { if (change.DisplayOperation == PreSyncOperation.Add) { sum.DecrAdd++; } else if (change.DisplayOperation == PreSyncOperation.Remove) { sum.DecrRemove++; } else if (change.DisplayOperation == PreSyncOperation.Change) { sum.DecrChange++; } else { sum.DecrOther++; } } else if (change.SyncMode == PreSyncMode.Conflict) { sum.Conflict++; } var syncResult = pair.TrySync(change, consoleEx); //todo: add to error log if (syncResult.Exception != null) { consoleEx.WriteErrorLine("..." + syncResult.Exception.Message); } } consoleEx.WriteLine("== Summary =="); consoleEx.WriteLine(sum); //todo: fix unchanged consoleEx.WriteLine(); //consoleEx.WriteLine(VerbosityLevel.Diagnostic, 0, ""); //consoleEx.WriteLine(VerbosityLevel.Diagnostic, 0, "==Decr Directory=="); //foreach (var entry in decrDirectory.FSDirectory.GetEntries(SearchOption.AllDirectories)) //{ // if (entry is FSDirectory dirEntry) // consoleEx.WriteLine(VerbosityLevel.Diagnostic, 1, $"<dir> {entry.RelativePath}"); // else if (entry is FSFile fileEntry) // consoleEx.WriteLine(VerbosityLevel.Diagnostic, 1, $"{HelixUtil.FormatBytes5(entry.Length)} {entry.RelativePath}"); //} //consoleEx.WriteLine(VerbosityLevel.Diagnostic, 0, ""); //consoleEx.WriteLine(VerbosityLevel.Diagnostic, 0, "==Encr Directory=="); //foreach (var entry in encrDirectory.FSDirectory.GetEntries(SearchOption.AllDirectories)) //{ // if (entry is FSDirectory dirEntry) // consoleEx.WriteLine(VerbosityLevel.Diagnostic, 1, $"<dir> {entry.RelativePath}"); // else if (entry is FSFile fileEntry) // consoleEx.WriteLine(VerbosityLevel.Diagnostic, 1, $"{HelixUtil.FormatBytes5(entry.Length)} {entry.RelativePath}"); //} return(sum); }