Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #4
0
        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))
 {
 }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }