简体   繁体   English

逐行加密/解密文件?

[英]Encrypting/decrypting a file line by line?

I'm fairly novice to encryption, and I'm trying to get a line-by-line encryptor working; 我是加密的新手,我正在努力让逐行加密器工作; I need to be able to append encrypted lines to a file as I go during an application's run, rather than just one big massive encrypt-everything-and-save. 我需要能够在应用程序运行期间将加密的行附加到文件中,而不是仅仅进行一次大规模加密 - 一切和保存。 I'm having a beast of a time with it though. 虽然我有一个时间的野兽。 Here's my encryptor, shamelessly stolen after several failed attempts at my own: 这是我的加密器,经过多次尝试失败后无耻地被盗:


class Encryption
    {
        private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };

        public static byte[] Encrypt(byte[] plain, string password)
        {
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(plain, 0, plain.Length);
            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();
            return memoryStream.ToArray();
        }

        public static byte[] Decrypt(byte[] cipher, string password)
        {
            MemoryStream memoryStream;
            CryptoStream cryptoStream;
            Rijndael rijndael = Rijndael.Create();
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, SALT);
            rijndael.Key = pdb.GetBytes(32);
            rijndael.IV = pdb.GetBytes(16);
            memoryStream = new MemoryStream();
            cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(cipher, 0, cipher.Length);
            cryptoStream.FlushFinalBlock();
            cryptoStream.Close();
            return memoryStream.ToArray();
        }
    }

And here's a dummy function showing how I'm attempting it: 这是一个虚拟函数,显示我是如何尝试它的:

private void EncryptFile(string filepath, string outputPath, string password)
        {
            FileInfo fileInfo = new FileInfo(filepath);
            string filename = fileInfo.Name;

            string fullpath = outputPath + "\\" + filename;

            BinaryWriter writer = new BinaryWriter(File.OpenWrite(fullpath), Encoding.ASCII);

            /// Two methods that I've attempted here:
            /// 1.  The desired method: encrypt line by line - I assumed I'd be able to generate
            ///     multiple blocks of data and decrypt them later.  This isn't working

            //string[] lines = File.ReadAllLines(filepath);

            /// 2.  Just read the whole thing and encrypt and write it in one swoop.

            string line = File.ReadAllText(filepath);

            //foreach(string line in lines)
            {
                byte[] bytes = Encoding.ASCII.GetBytes(line);
                byte[] encoded = Encryption.Encrypt(bytes, password);

                writer.Write(encoded);
                writer.Flush();
            }

            writer.Close();
        }



        private void DecryptFile(string filepath, string outputPath, string password)
        {
            FileInfo fileInfo = new FileInfo(filepath);
            string filename = fileInfo.Name;
            string fullpath = outputPath + "\\" + filename;

            StreamWriter writer = new StreamWriter(fullpath, false, Encoding.UTF8);

            byte[] bytes = File.ReadAllBytes(filepath);

            ///  Here is the method that's working at the moment for decrypting; just
            ///  grab all the data and decrypt it on one swoop.

            byte[] decrypted = Encryption.Decrypt(bytes, password);

            string s = Encoding.ASCII.GetString(decrypted);

            writer.Write(s);
            writer.Flush();


            ///  I've tried a number of things here to decrypt line by line,
            ///  none of which work.  This crashes with an issue about the padding
            ///  being invalid.  

            /*
            int index = 0;
            int count = 32;

            while (index

I'm not entirely sure what I should be doing anymore. 我不完全确定我应该做什么了。 I've been wandering around poking at things and reading through examples online, but they all seem to be how to encrypt a whole file or just encrypt a piece of data and do nothing with it other than immediately decrypt it again. 我一直在四处闲逛,通过在线阅读示例,但它们似乎都是如何加密整个文件,或者只是加密一段数据而不对它做任何事情,除了立即再次解密。 How should I handle line-by-line writing? 我应该如何处理逐行写作?

Instead of programming this for you, I'll give you a scheme which you could implement. 我会给你一个你可以实现的方案,而不是为你编程。

If you have per line encryption, I presume you want to be able to decrypt per line as well. 如果你有每行加密,我认为你也希望能够在每行解密。 Note that a "line" is a rather inconvenient term for a computer. 注意,“线”对于计算机来说是相当不方便的术语。 It's just a bunch of characters that end with some kind of line terminator. 它只是一堆以某种行终结符结尾的字符。 The characters in themselves are encoded using a specific . 它们本身的字符使用特定的

Furthermore, I'll make the following assumptions: 此外,我将做出以下假设:

  • the encrypted text should be presented in lines, which means that the bytes need to converted from binary to characters (using an ); 加密文本应以行显示,这意味着字节需要从二进制转换为字符(使用 );
  • you want a single key to be used, while staying secure; 你想要一把钥匙使用,同时保持安全;
  • you don't need integrity protection or authentication of the cipher text, only confidentiality. 您不需要完整性保护或密文验证,只需要保密。

Now the idea is simple: 现在这个想法很简单:

  1. create a single key using a password based key derivation function; 使用基于密码的密钥派生函数创建单个密钥;
  2. open the text file for reading (using the correct ); 打开文本文件进行读取(使用正确的 );
  3. read a line and convert the line to bytes again (eg using UTF-8); 读取一行并再次将该行转换为字节(例如,使用UTF-8);
  4. create an output stream that creates a byte array underneath; 创建一个输出流,在下面创建一个字节数组;
  5. create a random IV and write it to the byte array (IV is always a single block size); 创建一个随机IV并将其写入字节数组(IV始终是单个块大小);
  6. create a crypto stream and connect it to the same output stream; 创建加密流并将其连接到同一输出流;
  7. encrypt the encoded line; 加密编码行;
  8. base 64 encode the encrypted bytes, and make sure it stays in one line; base 64对加密的字节进行编码,并确保它保持在一行中;
  9. write the encoded, encrypted line to a new text file. 将编码的加密行写入新的文本文件。

To do the opposite, reverse the process, although the IV should be retrieved from the bytes after base 64 decoding, and the key should of course be calculated using the same method as used during encryption. 相反,反过来,尽管应该在base 64解码后从字节中检索IV,并且当然应该使用加密期间使用的相同方法来计算密钥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM