gpt4 book ai didi

c# - 将 CryptoStream 解密为 MemoryStream

转载 作者:行者123 更新时间:2023-12-03 19:55:54 24 4
gpt4 key购买 nike

我写了一个过程,其中文件被加密并上传到 Azure,然后下载过程必须被解密,这是失败的“填充无效且无法删除”错误,或“要解密的数据长度是无效的。”错误。

我在网上尝试了很多解决方案,包括 C# Decrypting mp3 file using RijndaelManaged and CryptoStream ,但它们似乎都不起作用,我最终只是在这两个错误之间来回跳动。加密过程使用与解密相同的 key /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();
}
}

评论之一提到想知道什么 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();
}
}

代码永远不会达到这一点 - 它在我达到这一点之前就死了。

最佳答案

在从各种博客来回反复之后,我发现我实际上在上面的代码中有几个错误让我感到困扰。首先,加密过程错误地写入了数组——它被 CryptoStream 包裹起来。实例,但实际上并没有使用它,所以我将未加密的数据写入 Azure。这是处理此问题的正确途径( fileKey 是我创建的用于生成 Key/IV 对的自定义类的一部分,因此可以将引用的任何地方更改为来自 RijndaelManaged 的内置进程或其他任何内容'd 用于提出 key /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;
}
}

其次,由于我的加密过程涉及多个步骤(每个文件总共三个 key - 容器、文件名和文件本身),当我尝试解密时,我使用了错误的 key (当我引用 blobKey 进行解密时,可以在上面看到,这实际上是用于加密文件名而不是文件本身的 key 。正确的解密方法是:
//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();
}
}

我研究了 Azure 加密扩展 ( http://www.stefangordon.com/introducing-azure-encryption-extensions/),但它比我感兴趣的更以本地文件为中心 - 我的一切都只是流/内存中,并且改造该实用程序将更多工作比它值得。

希望这可以帮助任何希望在零依赖底层文件系统的情况下加密 Azure blob 的人!

关于c# - 将 CryptoStream 解密为 MemoryStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31486028/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com