Rub*_*aus 0 c# encryption aes cryptostream azure-storage-blobs
我已经编写了一个过程,在该过程中,将文件加密并上传到Azure,然后必须对下载过程进行解密,否则将失败,并显示“填充无效且无法删除”错误,或者“要解密的数据长度为无效。” 错误。
我已经尝试了许多在线解决方案,包括使用RijndaelManaged和CryptoStream解密C#mp3文件,但是它们似乎都不起作用,我最终只是在这两个错误之间来回跳动。加密过程使用的是解密使用的相同密钥/ IV对,并且由于它将解密一部分流,因此我感觉工作正常-最终会死于上述错误。
这是我的代码,有什么想法吗?请注意,三个变种(cryptoStream.CopyTo(decryptedStream),do {}和while)不跑起来-他们在这里展示我已经尝试过的选项,所有这一切的失败。
byte[] encryptedBytes = null;
using (var encryptedStream = new MemoryStream())
{
//download from Azure
cloudBlockBlob.DownloadToStream(encryptedStream);
//reset positioning for reading it back out
encryptedStream.Position = 0;
encryptedBytes = encryptedStream.ConvertToByteArray();
}
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
//fails here with "Length of the data to decrypt is invalid." error
cryptoStream.CopyTo(decryptedStream);
int data;
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
do
{
data = cryptoStream.ReadByte();
decryptedStream.WriteByte((byte)cryptoStream.ReadByte());
} while (!cryptoStream.HasFlushedFinalBlock);
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
while ((data = cryptoStream.ReadByte()) != -1)
{
decryptedStream.WriteByte((byte)data);
}
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
Run Code Online (Sandbox Code Playgroud)
提到的其中一项想知道是什么的注释ConvertToByteArray,这只是一个简单的扩展方法:
/// <summary>
/// Converts a Stream into a byte array.
/// </summary>
/// <param name="stream">The stream to convert.</param>
/// <returns>A byte[] array representing the current stream.</returns>
public static byte[] ConvertToByteArray(this Stream stream)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,代码从未达到这一点-它在我到达这一点之前就死了。
经过各种博客的来回反复讨论后,我发现上面的代码中确实存在一些错误,这些错误使我感到困惑。首先,加密过程错误地写入了数组-它被CryptoStream实例包裹,但实际上并没有利用它,因此我将未加密的数据写入了Azure。这是进行此操作的正确方法(这fileKey是我创建的用于生成Key / IV对的自定义类的一部分,因此可以将引用的任何位置更改为内置过程,RijndaelManaged也可以将其用作其他用途(带有密钥/ IV对):
using (var aes = new RijndaelManaged { KeySize = 256, Key = fileKey.Key, IV = fileKey.IV })
{
using (var encryptedStream = new MemoryStream())
{
using (ICryptoTransform encryptor = aes.CreateEncryptor())
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
{
using (var originalByteStream = new MemoryStream(file.File.Data))
{
int data;
while ((data = originalByteStream.ReadByte()) != -1)
cryptoStream.WriteByte((byte)data);
}
}
}
var encryptedBytes = encryptedStream.ToArray();
return encryptedBytes;
}
}
Run Code Online (Sandbox Code Playgroud)
其次,由于我的加密过程涉及多个步骤(每个文件共三个密钥-容器,文件名和文件本身),所以当我尝试解密时,我使用的是错误的密钥(上面提到blobKey解密时可以看到该密钥,实际上是用于加密文件名而不是文件本身的密钥正确的解密方法是:
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
int data;
while ((data = cryptoStream.ReadByte()) != -1)
decryptedStream.WriteByte((byte)data);
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
Run Code Online (Sandbox Code Playgroud)
我已经研究过Azure加密扩展(http://www.stefangordon.com/introducing-azure-encryption-extensions/),但它比本地文件中心要多,比我感兴趣的多-我的一切都是流/ in-memory,并且对该实用程序进行改造将比其值得的工作更多。
希望这可以帮助希望以零依赖底层文件系统加密Azure Blob的任何人!
| 归档时间: |
|
| 查看次数: |
8830 次 |
| 最近记录: |