我很难使用与加密文件相同的机制来解密文件。每当我试图解密时,我都会收到一个错误,说明输入数据不是一个完整的文档。下面我要放两个文件,服务提供商和使用它的内容。如果有人知道它为什么会做出这种行为,请告诉我。我没有处理过这个,那么多,我正在采用另一个非常大量使用它的项目。我主要想弄清楚这是否是配置问题,不过我在加密方面没有问题,也在下面。我花了几个小时试图弄清楚这一点。
这是我用来加密和解密的服务。
using System;
using System.Security;
using System.Security.Cryptography;
namespace Shared
{
// AES (Advanced Encryption Standard) 256-bit Cryptography
public class CryptoProvider
{
RijndaelManaged aes;
byte[] defaultKey = { 8, 190, 2, 33, 68, 88, 11, 200, 211, 35, 68, 23, 60, 24, 223, 67, 11, 190, 165, 33, 68, 88, 11, 200, 245, 35, 68, 23, 60, 24, 223, 67 };
byte[] defaultIv = { 11, 190, 165, 33, 68, 88, 11, 200, 245, 35, 68, 23, 60, 24, 223, 67 };
public CryptoProvider(byte[] key = null, CipherMode mode = CipherMode.CBC) {
aes = new RijndaelManaged();
aes.Mode = mode;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key ?? defaultKey;
aes.IV = defaultIv;
}
public static byte[] GenerateKey() {
var e = new RijndaelManaged();
e.GenerateKey();
return e.Key;
}
public byte[] IV {
get { return aes.IV; }
}
public ICryptoTransform CreateEncrypter() {
return aes.CreateEncryptor(aes.Key, aes.IV);
}
public ICryptoTransform CreateDecrypter() {
return aes.CreateDecryptor(aes.Key, aes.IV);
}
}
}
这是使用上述服务的文件。
public static void DecryptFile(string file, byte[] encryptionKey, bool clientEcbEnabled) {
var newFileName = file + ".tmp";
var ext = Path.GetExtension(file).ToLower();
using (var fin = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) {
using (var fout = new FileStream(newFileName, FileMode.OpenOrCreate, FileAccess.Write)) {
fout.SetLength(0);
var mode = Cryptographer.GetCipherMode(file, clientEcbEnabled);
var cp = new CryptoProvider(encryptionKey, mode);
var buffer = new byte[1048576];
if (mode == CipherMode.CBC) {
// write the original length of the file
fout.Write(BitConverter.GetBytes((int)fin.Length), 0, 4);
}
using (var cs = new CryptoStream(fout, cp.CreateDecrypter(), CryptoStreamMode.Write)) {
int bytesRead = 0;
while ((bytesRead = fin.Read(buffer, 0, 1048576)) != 0) {
cs.Write(buffer, 0, bytesRead);
// report progress to event if wired up
if (EncryptProgress != null) EncryptProgress(bytesRead);
}
cs.FlushFinalBlock();
}
}
}
File.Delete(file);
File.Move(newFileName, file);
}
这是有效的加密方法。
public static void EncryptFile(string file, byte[] encryptionKey, bool clientEcbEnabled) {
var newFileName = file + ".tmp";
var ext = Path.GetExtension(file).ToLower();
using (var fin = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) {
using (var fout = new FileStream(newFileName, FileMode.OpenOrCreate, FileAccess.Write)) {
fout.SetLength(0);
var mode = Cryptographer.GetCipherMode(file, clientEcbEnabled);
var cp = new CryptoProvider(encryptionKey, mode);
var buffer = new byte[4096];
if (mode == CipherMode.CBC) {
// write the original length of the file
fout.Write(BitConverter.GetBytes((int)fin.Length), 0, 4);
}
using (var cs = new CryptoStream(fout, cp.CreateEncrypter(), CryptoStreamMode.Write)) {
int bytesRead = 0;
while ((bytesRead = fin.Read(buffer, 0, 4096)) != 0) {
cs.Write(buffer, 0, bytesRead);
// report progress to event if wired up
if (EncryptProgress != null) EncryptProgress(bytesRead);
}
cs.FlushFinalBlock();
}
}
}
File.Delete(file);
File.Move(newFileName, file);
}
在加密和解密时,将输入文件的大小写入(在CBC模式的情况下(创建文件的前4个字节。因此,在解密时,必须忽略前4个字节,例如使用
public static void DecryptFile(string file, byte[] encryptionKey, bool clientEcbEnabled)
{
...
using (var fin = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)
{
fin.seek(4, SeekOrigin.Begin);
...
否则,这4个字节被解释为密文,从而导致解密错误。但有了这个改变,解密就可以在我的机器上工作了。
由于解密时也会在开始时写入文件大小,尤其是二进制文件可能无法再由其各自的应用程序读取(例如Word中的文档文件(。
加密/解密过程不需要写入文件大小(CBC模式也不需要(,并且可以省略(代码中也不使用数据(。但也许你还有其他原因。
此外,关于您的静态IV,请注意,出于安全原因,AES/CBC只使用一次密钥/IV对是很重要的。