public
static
void
DecryptFile(
string
inputFilePath,
string
outputFilePath)
{
using
(FileStream inputFileStream =
new
FileStream(inputFilePath, FileMode.Open, FileAccess.Read))
{
// 检查文件长度是否足够包含元数据
long
totalLength = inputFileStream.Length;
if
(totalLength < 56)
{
throw
new
InvalidOperationException(
"文件已损坏或格式不正确。"
);
}
// 读取末尾的56字节元数据(密钥 + IV + 标识符)
byte
[] metadata =
new
byte
[56];
inputFileStream.Seek(-56, SeekOrigin.End);
// 定位到元数据起始位置
inputFileStream.Read(metadata, 0, 56);
// 分解元数据
byte
[] key = metadata.Take(32).ToArray();
// 前32字节为密钥
byte
[] iv = metadata.Skip(32).Take(16).ToArray();
// 接下来16字节为IV
byte
[] identifierBytes = metadata.Skip(48).ToArray();
// 最后8字节为标识符
// 验证标识符
string
actualIdentifier = Encoding.UTF8.GetString(identifierBytes);
if
(actualIdentifier != identifier)
{
throw
new
InvalidOperationException(
"文件标识符不匹配,可能已被篡改。"
);
}
// 准备解密
using
(Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = iv;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Mode = CipherMode.CBC;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// 计算加密数据部分的长度(总长度 - 元数据长度)
long
encryptedDataLength = totalLength - 56;
// 回到文件开头读取加密数据
inputFileStream.Seek(0, SeekOrigin.Begin);
// 写入解密后的数据到输出文件
using
(FileStream outputFileStream =
new
FileStream(outputFilePath, FileMode.Create, FileAccess.Write))
using
(CryptoStream cryptoStream =
new
CryptoStream(outputFileStream, decryptor, CryptoStreamMode.Write))
{
byte
[] buffer =
new
byte
[4096];
int
bytesRead;
long
bytesLeft = encryptedDataLength;
while
(bytesLeft > 0)
{
int
readSize = (
int
)Math.Min(buffer.Length, bytesLeft);
bytesRead = inputFileStream.Read(buffer, 0, readSize);
if
(bytesRead == 0)
break
;
cryptoStream.Write(buffer, 0, bytesRead);
bytesLeft -= bytesRead;
}
cryptoStream.FlushFinalBlock();
// 确保处理最后一块数据
}
}
}
Console.WriteLine($
"文件 '{inputFilePath}' 已解密到 '{outputFilePath}'。"
);
}