AES 分块解密在末尾添加随机字节
AES decrypt in chunks adds random bytes at the end
我有一个使用 AES 加密的非常大的 csv 文件。加密的代码
using var aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
aes.IV = initializationVector;
using var memoryStream = new MemoryStream();
var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.Flush();
稍后保存到文件中。在解密端,我试图以块的形式解密它,例如
using var sourceStream = File.OpenRead(path_to_encrypted_file);
using var aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
aes.IV = iv;
using (var fs = File.Create(path_to_decrypted_file))
using (var cryptoStream = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Write)
{
var dataBuffer = new byte[81290];
int read;
while ((read = await sourceStream.ReadAsync(dataBuffer)) != 0)
{
ReadOnlyMemory<byte> buffer = dataBuffer.AsMemory().Slice(0, read);
await cryptoStream.WriteAsync(buffer);
await cryptoStream.FlushAsync();
}
}
文件已解密,但是,我在文件末尾看到一些随机字节和空行
我解密的方式有问题吗?
我首先要调查几个潜在问题,至少在现有提供的代码中是这样。可能还有更多取决于您如何生成初始数据字节数组、如何生成密钥、如何将加密流写入磁盘等。
您正在使用 ECB,而您几乎肯定不应该。它对你的静脉注射也没有任何作用。根据应用考虑 CBC 或 GCM。
您没有使用填充模式。除非您的数据完全包含在块大小内,否则您可能会丢失一些数据,这可能会导致最后出现乱码。
你不显示原始加密流处理,你只显示Flush()
。根据其处理方式,它可能不会调用 CryptoStream 的 FlushFinalBlock()
方法,这很重要。鉴于缺少填充模式,如果你添加它,你可能会突然看到自己在这里有一个例外提醒你 The input data is not a complete block.
由于 #2 直到你换掉它。
感谢 我根据答案和评论中的建议重新实现了 encrypt/decrypt。
一点背景知识——我需要一个解决方案,在客户端机器上进行加密(与互联网断开连接),一旦加密的文件上传到 blob 存储,稍后在云中进行解密。
我想要混合加密,其中密钥是 RSA 加密的,数据是 AES。
所以客户端上的文件内容:
- RSA 加密密钥
- RSA 加密 IV(IV 的 RSA 加密不是必需的 AFAIK)
- AES 加密数据
这是最终实现:
// Local
var localRsa = RSA.Create();
localRsa.ImportRSAPublicKey(
Convert.FromBase64String(public_key),
out var _);
var localAes = Aes.Create();
localAes.GenerateKey();
localAes.GenerateIV();
localAes.Mode = CipherMode.CBC;
localAes.Padding = PaddingMode.PKCS7;
using (var dataStream = File.OpenRead(file_to_encrypt))
using (var secretFileStream = File.Create(encrypted_file))
{
await secretFileStream.WriteAsync(localRsa.Encrypt(localAes.Key, RSAEncryptionPadding.OaepSHA256));
await secretFileStream.WriteAsync(localRsa.Encrypt(localAes.IV, RSAEncryptionPadding.OaepSHA256));
using (var cryptoStream = new CryptoStream(secretFileStream, localAes.CreateEncryptor(localAes.Key, localAes.IV), CryptoStreamMode.Write))
{
await dataStream.CopyToAsync(cryptoStream);
}
}
以及解密片:
// Cloud
var cloudRsa = RSA.Create();
cloudRsa.ImportRSAPrivateKey(
Convert.FromBase64String(private_key),
out var _);
var cloudAes = Aes.Create();
cloudAes.Mode = CipherMode.CBC;
cloudAes.Padding = PaddingMode.PKCS7;
using (var secretFileStream = File.OpenRead(encrypted_file))
{
var keyBuffer = new byte[256];
await secretFileStream.ReadAsync(keyBuffer, 0, keyBuffer.Length);
cloudAes.Key = cloudRsa.Decrypt(keyBuffer, RSAEncryptionPadding.OaepSHA256);
var ivBuffer = new byte[256];
await secretFileStream.ReadAsync(ivBuffer, 0, keyBuffer.Length);
cloudAes.IV = cloudRsa.Decrypt(ivBuffer, RSAEncryptionPadding.OaepSHA256);
secretFileStream.Position = 512;
using (var plainTextStream = File.Create(decrypted_file))
{
using (var cryptoStream = new CryptoStream(secretFileStream, cloudAes.CreateDecryptor(cloudAes.Key, cloudAes.IV), CryptoStreamMode.Read))
{
await cryptoStream.CopyToAsync(plainTextStream);
}
}
}
我有一个使用 AES 加密的非常大的 csv 文件。加密的代码
using var aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
aes.IV = initializationVector;
using var memoryStream = new MemoryStream();
var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.Flush();
稍后保存到文件中。在解密端,我试图以块的形式解密它,例如
using var sourceStream = File.OpenRead(path_to_encrypted_file);
using var aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
aes.IV = iv;
using (var fs = File.Create(path_to_decrypted_file))
using (var cryptoStream = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Write)
{
var dataBuffer = new byte[81290];
int read;
while ((read = await sourceStream.ReadAsync(dataBuffer)) != 0)
{
ReadOnlyMemory<byte> buffer = dataBuffer.AsMemory().Slice(0, read);
await cryptoStream.WriteAsync(buffer);
await cryptoStream.FlushAsync();
}
}
文件已解密,但是,我在文件末尾看到一些随机字节和空行
我解密的方式有问题吗?
我首先要调查几个潜在问题,至少在现有提供的代码中是这样。可能还有更多取决于您如何生成初始数据字节数组、如何生成密钥、如何将加密流写入磁盘等。
您正在使用 ECB,而您几乎肯定不应该。它对你的静脉注射也没有任何作用。根据应用考虑 CBC 或 GCM。
您没有使用填充模式。除非您的数据完全包含在块大小内,否则您可能会丢失一些数据,这可能会导致最后出现乱码。
你不显示原始加密流处理,你只显示
Flush()
。根据其处理方式,它可能不会调用 CryptoStream 的FlushFinalBlock()
方法,这很重要。鉴于缺少填充模式,如果你添加它,你可能会突然看到自己在这里有一个例外提醒你The input data is not a complete block.
由于 #2 直到你换掉它。
感谢
一点背景知识——我需要一个解决方案,在客户端机器上进行加密(与互联网断开连接),一旦加密的文件上传到 blob 存储,稍后在云中进行解密。
我想要混合加密,其中密钥是 RSA 加密的,数据是 AES。 所以客户端上的文件内容:
- RSA 加密密钥
- RSA 加密 IV(IV 的 RSA 加密不是必需的 AFAIK)
- AES 加密数据
这是最终实现:
// Local
var localRsa = RSA.Create();
localRsa.ImportRSAPublicKey(
Convert.FromBase64String(public_key),
out var _);
var localAes = Aes.Create();
localAes.GenerateKey();
localAes.GenerateIV();
localAes.Mode = CipherMode.CBC;
localAes.Padding = PaddingMode.PKCS7;
using (var dataStream = File.OpenRead(file_to_encrypt))
using (var secretFileStream = File.Create(encrypted_file))
{
await secretFileStream.WriteAsync(localRsa.Encrypt(localAes.Key, RSAEncryptionPadding.OaepSHA256));
await secretFileStream.WriteAsync(localRsa.Encrypt(localAes.IV, RSAEncryptionPadding.OaepSHA256));
using (var cryptoStream = new CryptoStream(secretFileStream, localAes.CreateEncryptor(localAes.Key, localAes.IV), CryptoStreamMode.Write))
{
await dataStream.CopyToAsync(cryptoStream);
}
}
以及解密片:
// Cloud
var cloudRsa = RSA.Create();
cloudRsa.ImportRSAPrivateKey(
Convert.FromBase64String(private_key),
out var _);
var cloudAes = Aes.Create();
cloudAes.Mode = CipherMode.CBC;
cloudAes.Padding = PaddingMode.PKCS7;
using (var secretFileStream = File.OpenRead(encrypted_file))
{
var keyBuffer = new byte[256];
await secretFileStream.ReadAsync(keyBuffer, 0, keyBuffer.Length);
cloudAes.Key = cloudRsa.Decrypt(keyBuffer, RSAEncryptionPadding.OaepSHA256);
var ivBuffer = new byte[256];
await secretFileStream.ReadAsync(ivBuffer, 0, keyBuffer.Length);
cloudAes.IV = cloudRsa.Decrypt(ivBuffer, RSAEncryptionPadding.OaepSHA256);
secretFileStream.Position = 512;
using (var plainTextStream = File.Create(decrypted_file))
{
using (var cryptoStream = new CryptoStream(secretFileStream, cloudAes.CreateDecryptor(cloudAes.Key, cloudAes.IV), CryptoStreamMode.Read))
{
await cryptoStream.CopyToAsync(plainTextStream);
}
}
}