C# AESCryptServiceProvider decrypt创建损坏的文件
C# AESCryptServiceProvider decrypt创建损坏的文件,c#,encryption,salt,aescryptoserviceprovider,C#,Encryption,Salt,Aescryptoserviceprovider,我正在编写一个web应用程序,它允许用户上传和下载文件。允许使用doc或jpeg等文件。文件在上传过程中加密,在下载过程中解密。 我使用AES作为算法,对所有文件使用一个密钥,但对每个文件使用不同的salt。我还确保加密和解密方法使用相同的密钥和填充方法。 但是,当网站试图解密文件时,它会创建一个损坏的文件,该文件比原始文件大。 因此,我不确定加密或解密过程是否会弄乱文件。 以下是源代码: //Encryption method private bool SaveEnryptFi
我正在编写一个web应用程序,它允许用户上传和下载文件。允许使用doc或jpeg等文件。文件在上传过程中加密,在下载过程中解密。
我使用AES作为算法,对所有文件使用一个密钥,但对每个文件使用不同的salt。我还确保加密和解密方法使用相同的密钥和填充方法。
但是,当网站试图解密文件时,它会创建一个损坏的文件,该文件比原始文件大。
因此,我不确定加密或解密过程是否会弄乱文件。
以下是源代码:
//Encryption method
private bool SaveEnryptFile(FileUpload fileUp)
{
try
{
string fName = fileUp.PostedFile.FileName;
string outputDir = Path.Combine(ConfigurationManager.AppSettings["clientDocFolder"] + CurrentUser.Name);
DirectoryInfo di = new DirectoryInfo(outputDir);
di.Create();
string outputFile = Path.Combine(outputDir, fName);
if (File.Exists(outputFile))
{
throw new Exception("File already exists");
}
else
{
byte[] file = new byte[fileUp.PostedFile.ContentLength];
fileUp.PostedFile.InputStream.Read(file, 0, fileUp.PostedFile.ContentLength);
//get the key string from web.config
var key = ConfigurationManager.AppSettings["keyFile"];
//randomly create a salt
byte[] salt = new byte[8];
var rng = new RNGCryptoServiceProvider();
rng.GetBytes(salt);
var derivedBytes = new Rfc2898DeriveBytes(key, salt);
using (AesCryptoServiceProvider alg = new AesCryptoServiceProvider())
{
alg.Key = derivedBytes.GetBytes(alg.KeySize / 8);
alg.IV = derivedBytes.GetBytes(alg.BlockSize / 8);
alg.Padding = PaddingMode.Zeros;
// Create a decrytor to perform the stream transform.
using (ICryptoTransform encryptor = alg.CreateEncryptor())
{
using (var fs = File.Create(outputFile))
{
//store the salt in the encrypted file
fs.Write(salt, 0, 8);
//write encrypted bytes to encrypted file
using (CryptoStream cs = new CryptoStream(fs, encryptor, CryptoStreamMode.Write))
{
cs.Write(file, 0, file.Length);
cs.FlushFinalBlock();
}
}
}
}
return true;
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
//解密方法:
var path = Path.Combine(ConfigurationManager.AppSettings["clientDocFolder"] + CurrentUser.Name + "\\" + ((WebControl)sender).Attributes["DocumentID"]);
if (File.Exists(path))
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
//Get the salt from the encrypted file
byte[] salt = new byte[8];
fs.Read(salt, 0, salt.Length);
//get key string from web.config file
string key = ConfigurationManager.AppSettings["keyFile"];
var derivedBytes = new Rfc2898DeriveBytes(key, salt);
AesCryptoServiceProvider alg = new AesCryptoServiceProvider();
alg.Key = derivedBytes.GetBytes(alg.KeySize / 8);
alg.IV = derivedBytes.GetBytes(alg.BlockSize / 8);
alg.Padding = PaddingMode.Zeros;
using (ICryptoTransform decryptor = alg.CreateDecryptor())
{
//byte array to store encrypted bytes.
//I use fs.Length-8 because first 8 bytes were used to store salt
byte[] encryptedBytes = new byte[fs.Length - 8];
int encryptedByteCnt = fs.Read(encryptedBytes, 0, encryptedBytes.Length);
using (MemoryStream ms = new MemoryStream(encryptedBytes))
{
byte[] plainBytes = new byte[encryptedByteCnt];
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
//decrypt encrypted bytes into a byte array
int decryptedByteCnt = cs.Read(plainBytes, 0, plainBytes.Length);
}
//Write decrypted bytes in response stream
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment; filename=" + Path.GetFileName(path));
Response.OutputStream.Write(plainBytes, 0, plainBytes.Length);
Response.Flush();
}
}
}
}
else
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "DownloadDocument", "alert('" + String.Format("There is no file such as {0} exists. Please contact us if you face this problem.);", ((WebControl)sender).Attributes["DocumentID"]) + "'", true);
return;
}
原来问题出在http发布的文件上。这会导致未将输入字节读取到阵列。 最后,我需要在流读取到0之前设置流的位置。
因此,我在加密方法中稍微更改了代码,如下所示:
从
byte[] file = new byte[fileUp.PostedFile.ContentLength];
fileUp.PostedFile.InputStream.Read(file, 0, fileUp.PostedFile.ContentLength);
致:byte[] file = new byte[fileUp.PostedFile.ContentLength];
Stream st = fileUp.FileContent;
st.Position = 0;
st.Read(file, 0, file.Length);
st.Close();
然而,我遇到了解密的问题。它将在解密的字节数组中添加额外的字节。他们大多数是0
更新:我更改了已解密的写入,因此它不会写入尾随的零。但是现在从服务器发送的下载文件将包含页面本身的html。如果我可以问,如果您将文件保存到服务器本身,首先加密和解密文件的原因是什么?您好,我已经完成了正常的上载/下载过程。现在我只想给网站增加一点额外的安全性。调试:使用一个小的测试文件,可能是40字节。加密前后、解密前后的十六进制转储。然后看看是否可以确定问题所在。如果这还不能确定问题所在,请将十六进制转储添加到问题中。@tùngTrịnh不想在这里多管闲事,但当您发送到客户端或从客户端接收文件时,文件将被取消加密。文件保存在保存密钥的同一web服务器上。我看不出这里面有什么安全的东西,所以这似乎不是一个加密问题,而是一个http问题。