2009-08-23 35 views

回答

2

我认为这样的实现并不会很有用,因为Seek操作只能在(相对于算法而言)ECB式链接(即分开加密块)的恒定时间内执行,并且这是highly unrecommended - see the image in this Wikipedia article for a startling example of insecurity

对我来说,你最好是复制进/出MemoryStream或类似的包装技术。

+0

我看到了问题。但是,似乎有几种方法可以实现安全的逐块加密,例如TrueCrypt使用的http://en.wikipedia.org/wiki/Disk_encryption_theory#XTS。 – 2009-08-23 11:53:52

+1

磁盘加密独立加密每个块,这就是它如何获得其随机搜索。 – 2009-08-23 13:58:23

4

块式加密非常安全。这只是欧洲央行的问题。实现可能可以使用OFB或CTR模式编写。但是,我从来没有找到一个。可以硬着头皮写吧......

UPDATE:

所以,我没有写这方面的一个实现。由于各种原因,我现在不会在这里发布它(我会尽力在某个时刻),但是对于任何想要这样做的人来说,这里有几点提示:

在CBC模式下使用RijndaelManaged变换。您将逐块计算cipherstream。您可以通过在变换中初始化一个键和一个空的(全零)iv来实现 - 实际的iv将在逐个块的基础上进行计算。

您需要一种方法,通过连接或计算nonce plus iv plus计数器来计算当前块的输入。你可以在这里做几次优化,包括预先计算现在的临时数(这个方法会被多次调用,所以它可能是值得的)。

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

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

您将在循环内使用此方法来加密您的数据 - 首次调用此方法,然后在块边界调用以更新当前密码流。此方法将输入提供给变换的TransformBlock方法。从变换中获取输出并将结果与​​当前数据块进行异或运算。在每个块被加密后使用transform.Reset()!否则,CBC将尝试使用变换的输出作为下一个的输入。有可能有一个更聪明的方式来与.NET做到这一点,但我无法弄清楚。我知道BouncyCastle支持OFB“本地”,所以这可能是一个更好的选择,但这是获得高度可重用的加密码而不需要外部代码的好方法。

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

换一种说法,您可以计算流的任意部分的密码流,然后简单地与密码或纯文本进行异或以进行加密/解密。

最后两件事:1。)我强烈建议在流的生命中重用转换 - 创建这些代价很高。 2.)如果你打算实施这个写单元测试NIST向量或类似的。不要以为你有这个权利 - 只是因为输出看起来是随机的,并不意味着它被正确加密:)。

如果任何人有一个更好的方法或如何我已经完全打乱了的代码真正重要的一块有什么想法,请留言,谢谢!