解密前如何保护加密文件不被破坏

How Can I Protect Encrypted Files From Being Corrupted Before Decryption

我正在使用 Rijndael 算法加密 pdf 文件。加密和解密工作正常。加密会将 pdf 文件转换为扩展名为 .key 的文件。

问题是我能够在 notepad(它显示一些 Unicode 字符)中打开此文件并损坏它。考虑以下场景:

我打开了文件并删除了一些characters/add一些字符save the notepad file。如果我将这个文件传递给解密方法,我将得到损坏的文件作为输出。我知道发生这种情况是因为字节流在添加或删除文件中的字符时发生变化(填充更改)。

这是我的问题:

有什么办法可以解决这个问题吗?也就是说,禁用对加密文件的编辑?**

以下是我用于加密的方法,

VB代码

   Dim plainFile As String = basePath & "\cryptoText.pdf"
   Dim password As String = "somePass"
   Dim UE As New UnicodeEncoding()
   Dim key As Byte() = UE.GetBytes(password)
   Dim cryptFile As String = basePath & "\cryptoText.key"
   Dim fsCrypt As New FileStream(cryptFile, FileMode.Create)
   Dim RMCrypto As New RijndaelManaged()
   Using csKey As New CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write)
         Dim FsIn As New FileStream(plainFile, FileMode.Open)
         Dim data As Integer
         While (data = FsIn.ReadByte()) <> -1
                csKey.WriteByte(CByte(data))
         End While
         FsIn.Close()
    End Using
    fsCrypt.Close()

C#代码

    string plainFile = basePath + "\cryptoText.pdf";
    string password = "somePass";
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(password);
    string cryptFile = basePath + "\cryptoText.key";
    FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
    RijndaelManaged RMCrypto = new RijndaelManaged();
    using (CryptoStream csKey = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write)) {
        FileStream FsIn = new FileStream(plainFile, FileMode.Open);
        int data = 0;
        while ((data == FsIn.ReadByte()) != -1) {
            csKey.WriteByte(Convert.ToByte(data));
        }
        FsIn.Close();
    }
    fsCrypt.Close();

注意: 我在 c# 和 vb.net 中都尝试过,因此我将我的问题标记为两者。

您无法真正阻止任何人在他们喜欢的任何编辑器中打开文件并对其进行修改。将文件标记为只读可能会有所帮助,但不能解决问题。

您应该做的是生成加密文件的散列,然后在解密之前检查以确保文件仍然生成相同的散列。如果没有,则说明该文件已被篡改。

答案是做两件事,

  1. 加密,
  2. 在加密数据上向其添加 HMAC(如使用相同密钥的 SHA256),并将其附加到密码流的末尾

https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256%28v=vs.110%29.aspx

那么当你解密的时候,你

  1. 验证 HMAC 是否有效,
  2. IFF #1 验证,然后才解密

此外,如果这不是本地文件而是某种网络流,那么你必须在常数时间内进行验证——你不能使用正常的字节比较函数。这是因为定时攻击。但是对于本地文件,你可以做任何你喜欢的比较,因为没有时间攻击。