static void RsaEncDecFile()
{
//建立RSA公私鑰
var rsaEnc = new RSACryptoServiceProvider(2048);
//匯出金鑰
var pubKey = rsaEnc.ToXmlString(false);
var rsaKeys = rsaEnc.ToXmlString(true);
//建立AES Managed時產生隨機Key及IV,不用另行指定
var aes = new AesManaged();
var encAesKeyIV = aes.Key.Concat(aes.IV).ToArray();
var aesKeyEncrypted = rsaEnc.Encrypt(encAesKeyIV, true);
byte[] signature;
Stopwatch sw = new Stopwatch();
sw.Start();
//準備加密Stream
using (var encFile =
new FileStream("D:\\Encrypted.bin", FileMode.Create))
{
using (var outStream = new
CryptoStream(
encFile, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
//讀取約500MB檔案寫入加密Stream
using (var fs = new FileStream("D:\\Source.zip",
FileMode.Open))
{
//REF: Buffer Size 64K CPU clock 較少
//https://goo.gl/UAuPyt
var buff = new byte[65536];
int bytesRead = 0;
while ((bytesRead = fs.Read(buff, 0, buff.Length)) > 0)
{
outStream.Write(buff, 0, bytesRead);
}
}
}
}
sw.Stop();
Console.WriteLine($"加密耗時: {sw.ElapsedMilliseconds}ms");
byte[] srcHash = SHA1.Create().ComputeHash(
new FileStream("D:\\Source.zip", FileMode.Open));
signature = rsaEnc.SignHash(srcHash, CryptoConfig.MapNameToOID("SHA1"));
var rsaDec = new RSACryptoServiceProvider();
//從XML還原公私鑰
rsaDec.FromXmlString(rsaKeys);
//解密出AES Key
var aesKeyIV = rsaDec.Decrypt(aesKeyEncrypted, true);
aes = new AesManaged()
{
KeySize = 256,
Key = aesKeyIV.Take(32).ToArray(),
IV = aesKeyIV.Skip(32).Take(16).ToArray(),
BlockSize = 128
};
sw.Restart();
//準備解密Stream
using (var decFile = new FileStream("D:\\Decrypted.zip", FileMode.Create))
{
using (var encFile = new FileStream("D:\\Encrypted.bin", FileMode.Open))
{
using (var decStream = new CryptoStream(encFile,
aes.CreateDecryptor(), CryptoStreamMode.Read))
{
var buff = new byte[65536];
int bytesRead = 0;
while ((bytesRead = decStream.Read(buff, 0, buff.Length)) > 0)
{
decFile.Write(buff, 0, bytesRead);
}
}
}
}
sw.Stop();
Console.WriteLine($"解密耗時: {sw.ElapsedMilliseconds}ms");
//印出解密檔案Hash與原始檔比對是否相同
byte[] decHash = SHA1.Create().ComputeHash(
new FileStream("D:\\Decrypted.zip", FileMode.Open));
Console.WriteLine($"Source SHA1={BitConverter.ToString(srcHash)}");
Console.WriteLine($"Decrypted SHA1={BitConverter.ToString(decHash)}");
//檢驗數位簽章
var valid =
rsaDec.VerifyHash(decHash, CryptoConfig.MapNameToOID("SHA1"), signature);
Console.WriteLine($"數位簽章: {(valid ? "PASS" : "FAILED")}");
}