Вы должны войти, чтобы создавать сообщения и темы.

Шифрования больших файлов?

Всем привет.
Есть вопросик. Можете подсказать простенькое шифрование для больших файлов. Чтобы можно было получить прогресс шифрования. Для этого как минимум нужно знать позицию шифрования файла и размер целиком. Так как файлы большие то как минимум читать по 1 байту и подменять другим очень глупо было бы.

Добрый день.
Большой файл, это сколько?

P.S. первая ссылка в Гугле - Encrypting/Decrypting large files (.NET)

Добрый вечер.
Ну разный от 500 МБ до 50 ГБ и больше.
Но чаще всего это в пределах 3 ГБ.
Вообще давненько писал код:

Код модуля

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AL7CreatePackageLib
{
    public enum Operation
    {
        None,
        StartCreateArchive,
        CreateArchiveFile,
        CreateArchiveProgress,
        CreateArchiveProgressFile,
        StopCreateArchive,
        StartEncryptArchive,
        ProgressEncryptArchive,
        StopEncryptArchive,
        StartDecryptArchive,
        ProgressDecryptArchive,
        StopDecryptArchive
    }

    public class CreatedPackage
    {
        #region Класс обработчика событий

        class CreatedPackageInfo
        {
            public Operation operation { get; set; }

            public string FileName { get; set; }

            public decimal? Value { get; set; }

            public decimal? MaxValue { get; set; }

            public string ErrorMsg { get; set; }

            public CreatedPackageInfo(Operation _operation)
            {
                this.operation = _operation;
            }
        }

        #endregion

        private Operation operation;

        #region Объявления событий

        public delegate void EventStartProcess(Operation _operation);
        public event EventStartProcess StartProcess;

        public delegate void EventStopProcess(Operation _operation, bool _isError, string _sError);
        public event EventStopProcess StopProcess;

        public delegate void EventAddFile(string _sFile);
        public event EventAddFile AddFile;

        public delegate void EventProgress(Operation _operation, int _progressValue, long _value, long _maxValue);
        public event EventProgress Progress;

        #endregion

        #region Обработчик событий

        private readonly IProgress<CreatedPackageInfo> progressInfo;

        private void OnProgressInfo(CreatedPackageInfo pInfo)
        {
            if (pInfo.ErrorMsg != null && pInfo.ErrorMsg.Length > 0)
            {
                StopProcess?.Invoke(pInfo.operation, true, pInfo.ErrorMsg);
                return;
            }

            switch (pInfo.operation)
            {
                case Operation.StartCreateArchive:
                case Operation.StartEncryptArchive:
                case Operation.StartDecryptArchive:
                    StartProcess?.Invoke(pInfo.operation);
                    break;
                case Operation.CreateArchiveFile:
                    AddFile?.Invoke(pInfo.FileName);
                    break;
                case Operation.CreateArchiveProgress:
                case Operation.CreateArchiveProgressFile:
                case Operation.ProgressEncryptArchive:
                case Operation.ProgressDecryptArchive:
                    {
                        var prcD = pInfo.Value / pInfo.MaxValue;
                        var prc = Convert.ToInt32(prcD * 100);
                        Progress?.Invoke(pInfo.operation, prc, Convert.ToInt64(pInfo.Value), Convert.ToInt64(pInfo.MaxValue));
                    }
                    break;
                case Operation.StopCreateArchive:
                case Operation.StopEncryptArchive:
                case Operation.StopDecryptArchive:
                    StopProcess?.Invoke(pInfo.operation, false, "");
                    break;

                default:
                    return;

            }
        }

        #endregion

        public CreatedPackage()
        {
            this.operation = Operation.None;
            progressInfo = new Progress<CreatedPackageInfo>(OnProgressInfo);
        }

        #region Создание архифа

        private void zipArchive_SaveProgress(object sender, Ionic.Zip.SaveProgressEventArgs e)
        {
            try
            {
                if (e.EventType == Ionic.Zip.ZipProgressEventType.Saving_Started)
                {
                    this.operation = Operation.StartCreateArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });
                }
                else if (e.EventType == Ionic.Zip.ZipProgressEventType.Saving_BeforeWriteEntry)
                {
                    this.operation = Operation.CreateArchiveFile;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { FileName = e.CurrentEntry.FileName });
                    this.operation = Operation.CreateArchiveProgress;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(e.EntriesSaved+1), MaxValue = Convert.ToDecimal(e.EntriesTotal) });
                }
                else if (e.EventType == Ionic.Zip.ZipProgressEventType.Saving_EntryBytesRead)
                {
                    this.operation = Operation.CreateArchiveProgressFile;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(e.BytesTransferred), MaxValue = Convert.ToDecimal(e.TotalBytesToTransfer) });
                }
                else if (e.EventType == Ionic.Zip.ZipProgressEventType.Saving_Completed)
                {
                    this.operation = Operation.StopCreateArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" } );
                }
            }
            catch (Exception ex)
            {
                progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = ex.Message });
            }
        }

        public void CreatedArchive(string sourceDirectoryName, string saveFile)
        {
            new Thread(() =>
            {
                using (var zipArchive = new Ionic.Zip.ZipFile())
                {
                    zipArchive.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
                    zipArchive.StatusMessageTextWriter = System.Console.Out;
                    zipArchive.SaveProgress += zipArchive_SaveProgress;
                    zipArchive.AddDirectory(sourceDirectoryName);
                    zipArchive.Save(saveFile);
                }

            }).Start();
        }

        public void EncryptArchive(string archiveFile, string encryptArchiveFile, string password = @"3302-1107-8890-4470-6645")
        {
            new Thread(() =>
            {
                try
                {
                    this.operation = Operation.StartEncryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });

                    UnicodeEncoding UE = new UnicodeEncoding();
                    byte[] passwordBytes = new byte[256];
                    var id = 0;
                    foreach (var x in UE.GetBytes(password))
                    {
                        passwordBytes[id] = x;
                        id++;
                    }
                    

                    FileStream fsCrypt = new FileStream(encryptArchiveFile, FileMode.Create);
                    RijndaelManaged RMCrypto = new RijndaelManaged();
                    CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(passwordBytes, passwordBytes), CryptoStreamMode.Write);

                    FileStream fsIn = new FileStream(archiveFile, FileMode.Open);

                    int data;
                    byte[] buffer = new byte[51200];
                    int writed = 0;
                    while ((data = fsIn.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        writed += data;
                        cs.WriteByte((byte)data);

                        this.operation = Operation.ProgressEncryptArchive;
                        progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(writed), MaxValue = Convert.ToDecimal(fsIn.Length) }); ;
                    }

                    fsIn.Close();
                    cs.Close();
                    fsCrypt.Close();

                    File.Delete(archiveFile);

                    this.operation = Operation.StopEncryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });
                }
                catch (Exception ex)
                {
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = ex.Message });
                }

            }).Start();
        }

        public void DecryptArchive(string encryptArchiveFile, string archiveFile, string password = @"3302-1107-8890-4470-6645")
        {
            new Thread(() =>
            {
                try
                {
                    this.operation = Operation.StartDecryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });

                    UnicodeEncoding UE = new UnicodeEncoding();
                    byte[] passwordBytes = new byte[256];
                    var id = 0;
                    foreach (var x in UE.GetBytes(password))
                    {
                        passwordBytes[id] = x;
                        id++;
                    }

                    FileStream fsCrypt = new FileStream(encryptArchiveFile, FileMode.Open);
                    RijndaelManaged RMCrypto = new RijndaelManaged();
                    CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateDecryptor(passwordBytes, passwordBytes), CryptoStreamMode.Read);

                    FileStream fsOut = new FileStream(archiveFile, FileMode.Create);

                    int data;
                    byte[] buffer = new byte[51200];
                    int writed = 0;
                    while ((data = cs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        writed += data;
                        fsOut.WriteByte((byte)data);

                        this.operation = Operation.ProgressEncryptArchive;
                        progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(writed), MaxValue = Convert.ToDecimal(cs.Length) }); ;
                    }

                    fsOut.Close();
                    cs.Close();
                    fsCrypt.Close();

                    this.operation = Operation.StopDecryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });
                }
                catch (Exception ex)
                {
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = ex.Message });
                }

            }).Start();
        }

        #endregion
    }
}

Но само шифрование вызывает ошибку. Так и не разобрался в чём дело.

Забыл добавить.
Способ выше то мне не понятно как вообще получать прогресс шифрования ибо файлы огромного размера. Речь о десяток ГБ.

Привет 🖐
Понимаю, что это не прямой ответ на Ваш вопрос, но не проще будет положить файлы в архив под пароль WinRAR? Можно шифровать имена файлов и будет непонятно даже, что там за файлы, пока пароль не введён.

Цитата: Сергей от 21.05.2022, 16:13

Привет 🖐
Понимаю, что это не прямой ответ на Ваш вопрос, но не проще будет положить файлы в архив под пароль WinRAR? Можно шифровать имена файлов и будет непонятно даже, что там за файлы, пока пароль не введён.

Проще но мне не нравится такой способ. Да и найти библиотеку для этого под C# будет проблематично.

Код функций шифрования и дешифрования

public void EncryptArchive(string archiveFile, string encryptedArchiveFile, string password = @"3302-1107-8890-4470-6645")
        {
            new Thread(() =>
            {
                try
                {
                    this.operation = Operation.StartEncryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });

                    using (Aes aesCrypto = Aes.Create())
                    {
                        byte[] salt = password.Replace("-", "").ToEncryptBytes(5);

                        using (Rfc2898DeriveBytes keyGen = new Rfc2898DeriveBytes(password, salt))
                        {
                            byte[] key = keyGen.GetBytes(32);
                            byte[] iv = keyGen.GetBytes(16);

                            File.WriteAllText("KeysEncrypt.log", $"Key {BitConverter.ToString(key)}" + Environment.NewLine + $"IV {BitConverter.ToString(iv)}");

                            aesCrypto.Key = key;
                            aesCrypto.IV = iv;
                        }

                        using (FileStream fsCrypt = new FileStream(encryptedArchiveFile, FileMode.Create))
                        using (CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateEncryptor(), CryptoStreamMode.Write))
                        using (FileStream fsIn = new FileStream(archiveFile, FileMode.Open))
                        {
                            int read;
                            byte[] buffer = new byte[4096];
                            int written = 0;
                            while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                written += read;
                                cs.Write(buffer, 0, read);

                                this.operation = Operation.ProgressEncryptArchive;
                                progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(written), MaxValue = Convert.ToDecimal(fsIn.Length) }); ;
                            }
                        }
                    }

                    File.Delete(archiveFile);

                    this.operation = Operation.StopEncryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });
                }
                catch (Exception ex)
                {
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = ex.Message });
                }

            }).Start();
        }

        public void DecryptArchive(string encryptedArchiveFile, string archiveFile, string password = @"3302-1107-8890-4470-6645")
        {
            new Thread(() =>
            {
                try
                {
                    this.operation = Operation.StartDecryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });

                    using (Aes aesCrypto = Aes.Create())
                    {
                        byte[] salt = password.Replace("-", "").ToDecryptBytes(5);

                        using (Rfc2898DeriveBytes keyGen = new Rfc2898DeriveBytes(password, salt))
                        {
                            byte[] key = keyGen.GetBytes(32);
                            byte[] iv = keyGen.GetBytes(16);

                            File.WriteAllText("KeysDecrypt.log", $"Key {BitConverter.ToString(key)}" + Environment.NewLine + $"IV {BitConverter.ToString(iv)}");

                            aesCrypto.Key = key;
                            aesCrypto.IV = iv;
                        }

                        using (FileStream fsCrypt = new FileStream(encryptedArchiveFile, FileMode.Open))
                        using (CryptoStream cs = new CryptoStream(fsCrypt, aesCrypto.CreateDecryptor(), CryptoStreamMode.Read))
                        using (FileStream fsOut = new FileStream(archiveFile, FileMode.Create))
                        {
                            int read;
                            byte[] buffer = new byte[4096];
                            int written = 0;
                            while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                written += read;
                                fsOut.Write(buffer, 0, read);

                                this.operation = Operation.ProgressDecryptArchive;
                                progressInfo.Report(new CreatedPackageInfo(this.operation) { Value = Convert.ToDecimal(written), MaxValue = Convert.ToDecimal(cs.Length) }); ;
                            }
                        }
                    }

                    this.operation = Operation.StopDecryptArchive;
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = "" });
                }
                catch (Exception ex)
                {
                    progressInfo.Report(new CreatedPackageInfo(this.operation) { ErrorMsg = ex.Message });
                }

            }).Start();
        }


Ошибка происходит при дешифровании:
СкопированоЗаполнение неверно и не может быть удалено.
При этом Key и IV и там и там одинаковый.