.NET CryptoStream 的可替代方案?

发布于 2024-08-03 05:53:31 字数 80 浏览 15 评论 0原文

有人知道 .NET CryptoStream 的替代品吗?

如果替代方案仅支持在“读取”模式下查找或仅限于 AES256,则可以。

Does anybody know a seekable alternative to .NET's CryptoStream?

It is OK if the alternative supports Seek only in "read" mode or if it is limited to e.g. AES256.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

满天都是小星星 2024-08-10 05:53:31

分块加密是完全安全的。只是欧洲央行有问题。可以使用 OFB 或 CTR 模式编写实现。然而,我一直没能找到一个。可能会硬着头皮写下来......

更新:

所以我确实写了一个实现。由于各种原因,我现在不打算将其发布在这里(我会在某个时候尝试),但这里为任何想要执行此操作的人提供了一些提示:

在 CBC 模式下使用 RijndaelManaged 转换。您将逐块计算密码流。您可以通过在变换中初始化一个键和一个空(全零)iv 来完成此操作 - 实际的 iv 将逐块计算。

您需要一种方法,通过连接或以其他方式计算随机数加 iv 加计数器来计算当前块的输入。您可以在此处进行多项优化,包括预先计算随机数和随机数。 iv(这个方法会被调用很多次,所以它可能是值得的)。

例如 byte[] GetCurrentCounterBlock(byte[] nonce, byte[] iv, UInt32 counter)

(注:这里的“iv”是指 NIST 所说的 IV,整个块的中间部分,其他人统称为 IV )

您将在加密数据的循环中使用此方法 - 第一次调用此方法,然后在块边界处调用此方法以更新当前的密码流。此方法为变换的 TransformBlock 方法提供输入。获取转换的输出,并将结果与​​当前数据块进行异或。每个块加密后使用transform.Reset()!否则,CBC 将尝试使用转换的输出作为下一个转换的输入。 .NET 可能有更聪明的方法来做到这一点,但我无法弄清楚。我知道 BouncyCastle “原生”支持 OFB,因此这可能是一个更好的选择,但这是一种无需外部依赖即可获得高度可重用的加密流的快速方法。

不管怎样,关键是整个方法(我称之为 AesCtr256.Process - 但你可以很容易地变得更通用)适用于密码流内的任意范围的数据。您可以在自定义 Stream 类中轻松使用此方法。这将允许在读取和写入时寻找流内的任意位置,并为您提供字节对齐的数据以供使用(非常好,因为您现在可以拥有一个实际报告真实数据长度的加密流!)。

换句话说,您计算流的任意部分的密码流,然后简单地对密码或纯文本进行异或以加密/解密。

最后两件事:1.)我强烈建议在流的生命周期中重复使用转换 - 创建这些转换的成本很高。 2.) 如果您要实现此针对 NIST 向量或类似内容编写单元测试。不要假设您的理解是正确的 - 仅仅因为输出看起来是随机的,并不意味着它已正确加密:)。

如果有人对更好的方法有任何想法,或者我如何完全搞砸了一段非常关键的代码,请发帖,谢谢!

Block-wise encryption is perfectly secure. It's just ECB that's problematic. An implementation could probably be written using either OFB or CTR mode. However, I've never managed to locate one. May bite the bullet and write it...

UPDATE:

So I did write an implementation of this. For various reasons I'm not going to post it here right now (I'll try to at some point), but here are a few pointers for anyone looking to do this:

Use a RijndaelManaged transform in CBC mode. You're going to calculate the cipherstream block by block. You can do this by initializing a key and an empty (all zero) iv in the transform - the actual iv will be calculated on a block by block basis.

You'll want to have a method that calculates the input to the current block by concatenating or otherwise computing the nonce plus iv plus counter. You can do several optimizations here, including precomputing the nonce & iv (this method will get called many times, so it's probably worth it).

e.g. byte[] GetCurrentCounterBlock(byte[] nonce, byte[] iv, UInt32 counter)

(note: by "iv" here I mean what NIST calls the IV, the middle part of the whole block, which other people call the IV collectively)

You're going to use this method inside a loop that's enciphering your data - call this the first time and then subsequently at block boundaries to update the current cipher stream. This method provides the input to the TransformBlock method of the transform. Take the output from the transform and XOR the result against the current block of data. Use transform.Reset() after each block is encrypted! Otherwise, CBC will try to use the output from the transform as input to the next. There may be a more clever way to do this with .NET, but I can't figure it out. I know BouncyCastle supports OFB "natively" so that may be a better options, but this is a nice fast way to get a highly reusable cryptostream without external deps.

Anyway, the key is that this whole method (I call it AesCtr256.Process - but you could easily be more generic) works with an arbitrary range of data inside the cipher stream. You can easily use this method inside a custom Stream class. This will allow seeking to arbitrary locations inside the stream on both reads and writes, and give you byte-aligned data to work with (really nice, as you can now have a crypto stream that actually reports the true data length!).

To put it another way, you calculate the cipher stream for arbitrary portions of the stream, and then simply xor against the cipher or plain text to encrypt/decrypt.

Two last things: 1.) I highly recommend reusing the transform for the life of the stream - creating these is expensive. 2.) If you're going to implement this write unit tests against NIST vectors or similar. Don't assume you got this right - just because the output looks random, doesn't mean it's correctly enciphered :).

If anyone has any thoughts on a better approach or how I've totally mucked up a really critical piece of code, please post, thanks!

计㈡愣 2024-08-10 05:53:31

我认为这样的实现不会很有用,因为 Seek 操作只能在(相对地,取决于算法)恒定时间内使用 ECB 式链接执行,即单独加密块 - 这就是 < a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation" rel="nofollow noreferrer">非常不推荐 - 请参阅这篇维基百科文章中的图片,了解令人震惊的不安全示例。

在我看来,通过复制到 MemoryStream 或从 MemoryStream 或类似的包装技术中复制出来会更好。

I think such an implementation would not be very useful, as Seek operations can only be performed in (relatively, depending on the algorithm) constant time with ECB-style chaining, i.e. encrypting blocks separately - and that's highly unrecommended - see the image in this Wikipedia article for a startling example of insecurity.

Seems to me you would be better off by copying into / out of a MemoryStream or similar wrapping technique.

猫卆 2024-08-10 05:53:31

这是一个重复的问题。我把答案放在:
如何向 CryptoStream 添加查找和定位功能< /a>

即使它使用 ECB,但您可以使用任何其他算法。顺便说一下,它没有巴里·凯利提到的欧洲央行问题,因为它使用欧洲央行的方式不同。

It is a duplicate question. I put an answer in:
How to add seek and position capabilities to CryptoStream

Even it is using ECB but you can use any other algorithm. by the way it does not have ECB problems as Barry Kelly mentioned because it uses ECB differently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文