CryptoStream:为什么要使用CryptoStreamMode.Write进行加密,而使用CryptoStreamMode.Read进行解密?

4

让e='password',我将其在CryptoStream中转换为'as9kio0736'。

让d='as9kio0736',我将其在CryptoStream中转换为'password'。

当我将d转换回'password'时,为什么它不被视为在CryptoStream中写入?

using (MemoryStream msEncrypt = new MemoryStream()) {
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
            swEncrypt.Write(plainText);
        }
    }
}

using (MemoryStream msDecrypt = new MemoryStream(cipherText)) {
    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
        using (StreamReader srDecrypt = new StreamReader(csDecrypt)) {
            plaintext = srDecrypt.ReadToEnd();
        }
    }
}

因为你要向底层流写入或者读取数据? - CodeCaster
你向加密流写入数据,它会将加密后的结果写入到MemoryStream中(在你的示例中)。你从加密流中读取数据 - 它从MemoryStream读取数据,解密并将结果返回给你。 - Evk
3个回答

12
CryptoStream旨在仅将一个流转换为另一个流,并允许转换链接。例如,您可以加密数据流,然后对加密输出进行Base 64编码。
根据您想要写入转换输入流还是从转换输出流读取来选择模式。
CryptoStream文档具有误导性。第一个CryptoStream构造函数参数的描述如下:
“执行加密转换的流”
如果构造函数的第三个参数值为CryptoStreamMode.Read,则此描述正确。
但是,如果第三个参数值为CryptoStreamMode.Write,则第一个构造函数参数的描述应为:
“将加密转换结果写入的流”。
此外,文档没有明确说明,如果使用CryptoStreamMode.Write,则必须在写入完成后调用FlushFinalBlock来刷新CryptoStream对象。
总结一下:
向转换输入流编写:
CryptoStream构造函数参数:
参数1:目标流
参数3:CryptoStreamMode.Write CryptoStream对象用途:
将数据写入CryptoStream对象
在完成写入后调用CryptoStream对象上的FlushFinalBlock
从转换输出流读取:
CryptoStream构造函数参数:
参数1:源流
参数3:CryptoStreamMode.Read
CryptoStream对象用途:
从CryptoStream对象读取数据,直到达到流末尾

4
看起来其他人也花了不少时间费脑筋研究这个问题 ;) - Ben
需要 cs.FlushFinalBlock(); 谢谢 - Pierre

10
您可以在任意方向上使用CryptoStream进行任何操作;只需要知道您的数据在哪里以及您想要对其进行什么操作即可。
如果要处理的数据已经在流中(且您允许该流被耗尽并处置),请在读取模式下使用CryptoStream并将数据读出(包括使用cryptoStream.CopyTo(someOtherStream))。如果数据在byte[]中并且您想要将其写入流中,请使用CryptoStream.Write。
在.NET Core测试中,您可以找到两种方式的示例。
使用Read进行加密和解密:https://github.com/dotnet/corefx/blob/61fb32299a276f1aa4103c85dcec215dfddc252d/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs#L466-L480 使用Write进行加密和解密:https://github.com/dotnet/corefx/blob/61fb32299a276f1aa4103c85dcec215dfddc252d/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs#L609-L631 这些甚至在同一文件中。这只是个人喜好的问题。

0

CryptoStream提供了同时进行加密和解密的读写灵活性。对于方向固定的情况,可以通过更改实现来在任何方向上移动。

以下是一种方法:

https://github.com/djpai/StreamConduit


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接