【问题标题】:C# attempting to decrypt a file to only process memoryC# 尝试解密文件以仅处理内存
【发布时间】:2019-04-07 02:48:04
【问题描述】:

我正在尝试仅将文件解密到进程内存。我不希望将实际文件发送为纯文本,因为它将存储敏感数据。我根本不希望原始文本出现在系统上。

我目前正在使用 C:\ 中的 eula 文件进行测试,但无论我使用什么文件都会遇到相同的问题。

我正在使用 AES 加盐。解密文件确实有效,因为现在我正在将解密的数据转储到文本文档中,但是当我尝试将 decrpytedBytes 编译为字符串时,它只输出 3 个在文档中的任何位置按该顺序不存在的字符。

https://i.imgur.com/WAQ2njB.png

这 2 个字符在使用 System.Text.Encoding.UTF8.GetString(bytesDecrypted, 0, bytesDecrypted.Length) 将字节数组编译为字符串时出现。

我只尝试了一个基本的.ToString(),但返回了System.Byte[],仅此而已

https://i.imgur.com/Gg5Et72.png

在使用var str = System.Text.Encoding.Default.GetString(bytesDecrypted) 时,它只输出 ÿþ*

https://i.imgur.com/94hMuB3.png

这是我用于加密和解密的代码

 public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
 {
     byte[] encryptedBytes = null;
     byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

     using (MemoryStream ms = new MemoryStream())
     {
          using (RijndaelManaged AES = new RijndaelManaged())
          {
              AES.KeySize = 256;
              AES.BlockSize = 128;

              var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
              AES.Key = key.GetBytes(AES.KeySize / 8);
              AES.IV = key.GetBytes(AES.BlockSize / 8);
              AES.Mode = CipherMode.CBC;

              using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
              {
                   cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                   cs.Close();
              }

              encryptedBytes = ms.ToArray();
          }
     }

     return encryptedBytes;
 }

 public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
 {
     byte[] decryptedBytes = null;
     byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

     using (MemoryStream ms = new MemoryStream())
     {
          using (RijndaelManaged AES = new RijndaelManaged())
          {
              AES.KeySize = 256;
              AES.BlockSize = 128;

              var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
              AES.Key = key.GetBytes(AES.KeySize / 8);
              AES.IV = key.GetBytes(AES.BlockSize / 8);
              AES.Mode = CipherMode.CBC;

              using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
              {
                   cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                   cs.Close();
              }

              decryptedBytes = ms.ToArray();
          }
     }

     return decryptedBytes;
 }

 public void EncryptFile(string file, string fileEncrypted, string password)
 {
     byte[] bytesToBeEncrypted = File.ReadAllBytes(file);
     byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

     passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

     byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

     File.WriteAllBytes(fileEncrypted, bytesEncrypted);
     listBox1.Items.Add("Enrypted the file");
 }

 public void DecryptFile(string fileEncrypted, string file, string password)
 {
     byte[] bytesToBeDecrypted = File.ReadAllBytes(fileEncrypted);
     byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

     passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

     byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);

     listBox1.Items.Add("Attempting Decryption");
     File.WriteAllBytes(file, bytesDecrypted);

     var str = System.Text.Encoding.Default.GetString(bytesDecrypted);

     richTextBox1.Text = str;
 }

如果您对我如何设法使这项工作有任何想法/线索,我将不胜感激!

【问题讨论】:

  • 我刚刚复制了您的代码并对其进行了测试,对我来说很好......
  • ÿþ* 看起来像一个 UTF-16 LE BOM(两个字节 0xFE 0xFF),这意味着原始文件是 UTF-16/UCS 2 Unicode。我真的不知道你用解密的字节数组在你的代码中做了什么,但是尝试使用 UNICODE 编码来解码你的字节 blob...
  • @elgonzo 将其更改为 unicode 工作!非常感谢!
  • @MarkusSafar,我正在写一个答案。我目前正在观看 Starcraft2 WCS Stats vs. Special。我会在比赛之间的休息时间写下我的答案,所以这需要一些时间;-)
  • @elgonzo,哈哈哈 - 我明白了,享受 ;-)

标签: c# arrays encryption memory


【解决方案1】:

找到了我认为适用于您的问题的答案。特别注意“encryptedData = output.ToArray();”

Reading from a cryptostream to the end of the stream

byte[] encryptedData;
rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126;
rijCrypto.KeySize = 256;

using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData)))
using (var output = new MemoryStream())
{
    var encryptor = rijCrypto.CreateEncryptor();

    using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
    {
        var buffer = new byte[1024];
        var read = input.Read(buffer, 0, buffer.Length);
        while (read > 0)
        {
            cryptStream.Write(buffer, 0, read);
            read = input.Read(buffer, 0, buffer.Length);
        }
        cryptStream.FlushFinalBlock();
        encryptedData = output.ToArray();
    }
}

【讨论】:

  • 原来我使用了错误的数据类型来加载它。将 UTF8 更改为 Unicode 确实对我有用。谢谢你的意见
【解决方案2】:

您使用了不正确的编码来解码解密的字节数组。原始文本文件的编码很可能是 Unicode/UTF-16。因此,使用Encoding.Unicode 编码将解密后的字节数组解码回文本:

var str = System.Text.Encoding.Unicode.GetString(bytesDecrypted);



一些背景资料

那么,是什么让我认为原始文本文件的编码是 UTF-16/Unicode? 问题中的这些信息给出了一个重要的提示:

虽然使用 var str = System.Text.Encoding.Default.GetString(bytesDecrypted) 它只输出 ÿþ*

注意ÿþ。如果使用 ISO/IEC 8859-1(或 CP-1252)代码页解码/显示具有此 BOM 的文本数据,这就是 UTF-16 LE BOM (*) 的显示方式,这通常是许多使用的默认代码页(英语/非本地化)Windows 安装。

(*) UTF-16 LE BOM(UTF-16 Little-Endian Byte Order Mark)是两个字节 0xFF,0xFE。要了解更多关于 BOM 是什么以及它们的目的是什么,我推荐这篇维基百科文章:https://en.wikipedia.org/wiki/Byte_order_mark

【讨论】:

    猜你喜欢
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 2012-05-19
    相关资源
    最近更新 更多