我正在實現文件的加密/解密,只有一定數量的字節應該加密。 例如:我有500 MB的大文件,我想加密(和當然解密)只有2 MB的文件。如何只加密/解密一定量的字節(文件)?
我已經實現了一切,加密工作正常(沒有錯誤),但是當我運行解密它總是拋出這個錯誤:
System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count) at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at ...
然後我試圖填充設爲encryptor.Padding = PaddingMode.None;
(並嘗試PaddingMode.Zeros等)。在使用此填充模式運行加密和解密之後,解密的結果沒有錯誤/異常,但文件的加密部分仍然是加密的,但有點不同。我也檢查了密碼是否正確
現在我不再有解決方案如何處理文件的「部分」加密。有任何想法嗎?如何處理這個填充或字節?
這是我的加密和一定量的字節的解密過程的代碼(遺憾的長度,但只有你會知道:)):
static byte[] FILE_HEADER = Encoding.Default.GetBytes("header_of_file"); //this is written to the first line of encrypted file
static long limitBytes = 4096 * 8; //limit encryption to this amount of bytes
public static bool Encrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
int bytesRead = 1;
long byteWriteCounter = 0;
long encryptedByteCounter = 0;
byte[] blength = null;
byte[] intBytes = null;
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
blength = new byte[FILE_HEADER.Length];
long sumBytesRead = 0;
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
fsInput.Read(blength, 0, blength.Length);
if (!blength.SequenceEqual(FILE_HEADER)) //read the FILE_HEADER - if not equal that we can encrypt otherwise is already encrypted
{
fsInput.Position = 0;
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
try
{
while (bytesRead != 0)
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
sumBytesRead += bytesRead;
if (sumBytesRead <= limitBytes) //limit encryption
{
if (bytesRead < bufferLen)
{
cs.Write(buffer, 0, bytesRead);
encryptedByteCounter += bytesRead;
byteWriteCounter += bytesRead;
intBytes = Encoding.Default.GetBytes(encryptedByteCounter.ToString("D7"));
fsOutput.Position = 0;
fsOutput.Write(FILE_HEADER, 0, FILE_HEADER.Length); //we write our header to file, to know which is encrypted
fsOutput.Write(intBytes, 0, intBytes.Length); //we write number of encrypted bytes next to header, for decryption to know
bytesRead = 0;
}
else
{
cs.Write(buffer, 0, bytesRead);
encryptedByteCounter += bytesRead;
byteWriteCounter += bytesRead;
}
}
else //if the file is bigger than limit, we continue to write normal data (unencrypted)
{
if (bytesRead < bufferLen)
{
fsOutput.Write(buffer, 0, bytesRead);
byteWriteCounter += bytesRead;
intBytes = Encoding.Default.GetBytes(encryptedByteCounter.ToString("D7"));
fsOutput.Position = 0;
fsOutput.Write(FILE_HEADER, 0, FILE_HEADER.Length);
fsOutput.Write(intBytes, 0, intBytes.Length);
bytesRead = 0;
}
else
{
fsOutput.Write(buffer, 0, bytesRead);
byteWriteCounter += bytesRead;
}
}
}
}
catch (SystemException se)
{
Console.WriteLine("Exception ENC: " + se);
}
}
}
}
return true;
}
else
{
//file is already encrypted
return false;
}
}
}
catch (SystemException se)
{
Console.WriteLine("Main ENC exception: "+se);
return false;
}
}
......和解密功能:
public static bool Decrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
byte[] blength = null;
blength = new byte[FILE_HEADER.Length];
long byteWriteCounter = 0;
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead = 1;
long decryptedByteCounter = 0;
long sumBytesRead = 0;
byte[] bufferEncBytes = new byte[7];
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
fsInput.Read(blength, 0, blength.Length);
if (blength.SequenceEqual(FILE_HEADER))//check if is our encrypted file
{
fsInput.Read(bufferEncBytes, 0, bufferEncBytes.Length);
int numOfDecBytes = Convert.ToInt32(Encoding.Default.GetString(bufferEncBytes)); //get number of encrypted bytes
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
try
{
while (bytesRead != 0)
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
sumBytesRead += bytesRead;
if (sumBytesRead <= numOfDecBytes) //decrypt until limit
{
if (bytesRead < bufferLen)
{
cs.Write(buffer, 0, bytesRead);
decryptedByteCounter += bytesRead;
byteWriteCounter += bytesRead;
bytesRead = 0; //we are at the end of file, end everything
}
else
{
cs.Write(buffer, 0, bytesRead);
decryptedByteCounter += bytesRead;
byteWriteCounter += bytesRead;
}
}
else //if we have decrypted encrypted bytes, continue with rest of the (normal) data
{
if (bytesRead < bufferLen)
{
fsOutput.Write(buffer, 0, bytesRead);
byteWriteCounter += bytesRead;
bytesRead = 0;
}
else
{
fsOutput.Write(buffer, 0, bytesRead);
byteWriteCounter += bytesRead;
}
}
}
}
catch (SystemException se)
{
Console.WriteLine("Exception DECR: " + se);
}
}
}
}
return true;
}
else
{
//not right file for decryption
return false;
}
}
}
catch (SystemException eks)
{
Console.WriteLine("Error: " + eks); //here the exception of Invalid Padding is thrown
return false;
}
}
這基本上相當於調試文件處理。假設你的密文與純文本一樣大是錯誤的。假設你完全閱讀你想要加密的明文的結尾似乎也是錯誤的。密文也可能比明文大。總而言之,許多錯誤和加密/解密方法試圖做一切,而不是做出好的設計。 –
爲什麼你只想加密部分文件?這顯然不安全。 – CodesInChaos
@ MaartenBodewes-owlstead我知道,有很多錯誤,我正在開發階段測試,如果它符合我的邏輯。但是,你能幫助並提供解決方案如何實現加密字節的數量,在解密中可以計數和解密?或者我應該使用其他加密算法? – OnlyKing