Есть ли более быстрая альтернатива методу FileStream.WriteByte () или какой-либо способ ускорить FileStream.WriteByte () в C #? - PullRequest
0 голосов
/ 25 февраля 2019

Я новичок в программировании на C #.Недавно я создал простую программу шифрования файлов и программу дешифрования.Сначала я взял файл в FileStream и изменил каждый байт файла в соответствии с паролем.Вот какой у меня код

Код шифратора

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

namespace Encrypter
{
    class Program
    {
        static void Main(string[] args)
        {         
            //Actual code starts from here
            string file_path = @args[0];

            string[] splited_filepath = file_path.Split('\\');
            string file_name = splited_filepath[splited_filepath.GetLength(0) - 1];

            FileStream file;
            if (File.Exists(file_path))
            {
                file = new FileStream(file_path, FileMode.Open);
                if (!file.CanWrite)
                {
                    Console.WriteLine("The file exists, but not writable!");
                    return;
                    //goto exit;
                }
            }
            else
            {
                Console.WriteLine("The file does not exist!\n{0}", file_path);
                return;
                //goto exit;
            }

            Console.Write("Enter the password : ");
            string password = Console.ReadLine();

            if(password == "")
            {
                Console.WriteLine("Password Cannot be empty!");
                return;
            }

            try
            {
                while(file.Position < file.Length)
                { 
                    int b_input = file.ReadByte();
                    file.Position--;
                    file.WriteByte(encrypt_byte(b_input,password,file.Position));
                    file.Position++;
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
                //goto exit;
            }

            file.Close();
            string encrypted_file_name = base64_enc(file_name) + compute_hash(password, new MD5CryptoServiceProvider());
            string encrypted_file_path = create_encrypted_file_path(encrypted_file_name, splited_filepath);

            try
            {
                File.Move(file_path, encrypted_file_path);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            //exit:;
        }

        static string create_encrypted_file_path(string enc_filename, string[] splited_fp)
        {
            string output = "";
            for(int a = 0; a < splited_fp.GetLength(0) - 1; a++)
            {
                output += (splited_fp[a] + "\\");
            }
            output += enc_filename;
            return output;
        }

        //Encrypting method starts here
        static byte encrypt_byte(int input, string pass, long pos)
        {
            char[] pass_char = pass.ToArray();
            int char_pos = Convert.ToInt32(pos % pass_char.GetLength(0));
            byte output = Convert.ToByte(
                (input + Convert.ToInt32(pass_char[char_pos])) % 256
                );
            return output;
        }

        static string compute_hash(string input,HashAlgorithm algorithm)
        {
            return BitConverter.ToString(algorithm.ComputeHash(Encoding.UTF8.GetBytes(input)));
        }

        //base64 encoding method
        static string base64_enc(string input)
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
        }
    }
}

Код расшифровщика

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

namespace Decrypter
{
    class Program
    {
        static void Main(string[] args)
        {
            //Actual code starts from here
            string file_path = args[0];

            string[] splited_filepath = file_path.Split('\\');
            string file_name = splited_filepath[splited_filepath.GetLength(0) - 1];

            string encrypted_filename = file_name.Substring(0, file_name.Length - 47);
            string hashed_password = file_name.Substring(file_name.Length - 47);

            FileStream file;
            if (File.Exists(file_path))
            {
                file = new FileStream(file_path, FileMode.Open);
                if (!file.CanWrite)
                {
                    Console.WriteLine("The file exists, but not writable!");
                    return;
                    //goto exit;
                }
            }
            else
            {
                Console.WriteLine("The file does not exist!\n{0}", file_path);
                Console.ReadLine();
                return;
                //goto exit;
            }

            Console.Write("Enter the password : ");
            string password = Console.ReadLine();
            if(password == "")
            {
                Console.WriteLine("Password cannot be empty!");
                return;
            }

            //Varify the password
            if(compute_hash(password,new MD5CryptoServiceProvider()) != hashed_password)
            {
                Console.WriteLine(compute_hash(password, new MD5CryptoServiceProvider()));
                Console.WriteLine(hashed_password);
                Console.WriteLine("Invalid password!");
                return;
            }

            try
            {
                while(file.Position < file.Length)
                {                
                    int b_input = file.ReadByte();
                    file.Position--;
                    file.WriteByte(decrypt_byte(b_input, password, file.Position));
                    file.Position++;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
                return;
                //goto exit;
            }
            file.Close();
            string decrypted_filename = base64_dec(encrypted_filename);
            string decrypted_filepath = create_decrypted_file_path(decrypted_filename, splited_filepath);

            try
            {
                File.Move(file_path, decrypted_filepath);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            //exit:;
        }

        //Decrypting method starts here
        static byte decrypt_byte(int input, string pass, long pos)
        {
            char[] pass_char = pass.ToArray();
            int char_pos = Convert.ToInt32(pos % pass_char.GetLength(0));
            byte output = Convert.ToByte(
                get_output_byte(input - Convert.ToInt32(pass_char[char_pos]))
                );
            return output;
        }

        //a simple method to get the numaric value of the output byte
        static int get_output_byte(int number)
        {
            if (number < 0) return 256 + number;
            else return number;
        }

        static string compute_hash(string input, HashAlgorithm algorithm)
        {
            return BitConverter.ToString(algorithm.ComputeHash(Encoding.UTF8.GetBytes(input)));
        }

        //base64 decoding method
        static string base64_dec(string input)
        {
            return Encoding.UTF8.GetString(Convert.FromBase64String(input));
        }

        static string create_decrypted_file_path(string enc_filename, string[] splited_fp)
        {
            string output = "";
            for (int a = 0; a < splited_fp.GetLength(0) - 1; a++)
            {
                output += (splited_fp[a] + "\\");
            }
            output += enc_filename;
            return output;
        }
    }
}

Проблема в том, что обе эти программы значительно медленные и занимают часышифровать или расшифровывать большие файлы.Любые предложения по ускорению процесса?

1 Ответ

0 голосов
/ 25 февраля 2019

Это примерно худший из возможных способов использования FileStream в цикле:

int b_input = file.ReadByte();
file.Position--;
file.WriteByte(encrypt_byte(b_input,password,file.Position));
file.Position++;

Хорошо, первая строка неплохая.Вторая строка заставляет поток очищать свой буфер записи и делать недействительным свой буфер чтения.Затем мы записываем новый байт и снова корректируем позицию, вызывая еще одну очистку и аннулирование (и заставляя нас пропускать каждый второй байт для загрузки, потому что WriteByte уже обновил позицию файла).

Простое решениеиспользовать File.ReadAllBytes и просто работать в памяти.Однако, как вы сами заметили, это не работает для больших файлов.

Вместо этого вам следует работать с буфером разумного размера (скажем, var buffer = new byte[4096];), а затем использовать file.Read для чтения файла вломти 1 .Лучше, если вы также можете использовать отдельный поток, указывающий на второй файл для стороны записи, так что вы по-прежнему извлекаете выгоду из буферов с обеих сторон.

Вы должны поддерживать свой собственный счет позиции в файле, а нечем полагаться на свойство Position файла, и ваш цикл должен завершиться, когда Read вернет 0 (но убедитесь, что вы всегда обращаете внимание на это значение и обрабатываете только большую часть буфера).

Наконец, закройте оба потока, удалите старый файл и переместите / переименуйте новый файл, чтобы заменить его.


Обратите внимание, что этот вид «шифрования» подходит для использования в игрушках, но не долженсерьезно используется для чего угодно.Вы уже знаете о пространстве имен System.Security.Cryptography.Для любой серьезной работы по шифрованию вы должны искать уже существующие классы, а не свои собственные.


1 Также рассмотрите возможность использования Async вариантов.Большую часть времени все равно будет потрачено на ввод / вывод .Блокировка потока, пока это происходит, не увеличивает ценность системы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...