我正在使用 Rijndael
算法加密 pdf 文件。加密和解密工作正常。加密会将 pdf 文件转换为具有 .key
扩展名的文件。
问题是我可以在记事本
中打开这个文件(它显示一些 Unicode 字符)并损坏它。考虑以下场景:
我已打开文件并删除一些字符/添加一些字符 并保存记事本文件
。如果我将这个文件传递给解密方法,我将得到损坏的文件作为输出。我知道这是因为在文件中添加或删除字符时 byteStream 发生变化(填充更改)。
这是我的问题:
有什么办法可以解决这个问题吗?换句话说,禁用对加密文件的编辑?**
以下是我使用的加密方法,
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 中都尝试过了,所以我将我的问题标记为两者。
最佳答案
答案是做两件事,
- 加密,
- 在加密数据上向其添加一个 HMAC(如使用相同 key 的 SHA256),并将其附加到密码流的末尾
https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256%28v=vs.110%29.aspx
然后当你解密的时候,你
- 验证 HMAC 是否有效,
- IFF#1 验证,然后才解密
此外,如果这不是本地文件而是某种网络流,那么您必须在恒定时间内进行验证 - 您不能使用正常的字节比较功能。这是因为定时攻击。但是对于本地文件,你可以做任何你喜欢的比较,因为没有时间攻击。
关于c# - 解密前如何保护加密文件不被破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32409753/