AES / CFB8的高效解密

时间:2017-11-23 11:33:27

标签: haskell encryption cryptography aes

我目前使用此功能解密在CFB8模式下使用AES加密的数据流: https://github.com/Lazersmoke/civskell/blob/ebf4d761362ee42935faeeac0fe447abe96db0b5/src/Civskell/Tech/Encrypt.hs#L167-L175

cfb8Decrypt :: AES128 -> BS.ByteString -> BS.ByteString -> (BS.ByteString,BS.ByteString)
cfb8Decrypt c i = BS.foldl magic (BS.empty,i)
  where
    magic (ds,iv) d = (ds `BS.snoc` pt,ivFinal)
      where
        pt = BS.head (ecbEncrypt c iv) `xor` d
        -- snoc on cipher always
        ivFinal = BS.tail iv `BS.snoc` d

如果你不了解Haskell,这里有一个关于我如何相信这段代码的快速概述:(我没写过)

  • 给出IV和加密字节列表
  • 对于每个加密字节:
    • 以ECB模式加密IV。
    • 获取加密IV的第一个字节,并使用加密字节对其进行xor。这是下一个明文字节。
    • 从IV
    • 中删除第一个字节
    • 将加密的字节附加到IV
    • 下一个字符将使用此新IV
    • 解密

不是ECB模式加密由cryptonite库处理。我找不到支持CFB8的图书馆。

现在,这有效。但是,由于我需要解密的数据量,它会限制我的一个CPU内核,80%的时间只用于解密。

传入的数据甚至没有那么多,所以这是不可接受的。不幸的是,我对密码学的了解相当有限,CFB8上的资源似乎相当稀少。看起来CFB8是一种不常见的操作模式,也表现为缺乏图书馆支持。

那么,我的问题是:我将如何优化这个?

传入数据来自TCP流,但信息被分组为数据包。每个数据包调用cfb8Decrypt函数2-5次,具体取决于大小。这是必要的,因为数据包的长度在开始时传输,但是这个大小信息的长度是可变的。在1-4次解密用于解密长度之后,整个数据包将立即被解密。我想过要减少这个,但我不确定它是否会对速度有任何影响。

修改:分析结果:http://svgur.com/i/40b.svg

1 个答案:

答案 0 :(得分:1)

创建CFB8是为了在噪声通道上具有良好的误差传播特性。众所周知,它并不快;它实际上是16倍慢,因为它需要对每个字节进行块加密。目前它不是很热,因为我们倾向于将CRC用于数据层,而MAC则用于加密级别上的完整性以防止故意攻击。

你怎么加快速度?你唯一能做的就是使用快速库。您当前使用的库似乎支持AES-NI,因此请确保在您的CPU和BIOS上启用它。

但是,如果必须将其称为阻止阻塞,它很可能不会加速。你真的想使用一个本机调用来获取整个数据包并对其进行解密。 AES-NI在Atom实现TLS时速度最慢仍然达到20 MiB / s,但在服务器芯片上,AES-NI通常远远超出1 GiB / s的限制。当AES-NI不可用时,装配或优化的C应该是慢6/7倍。

像Haskell这样的函数式编程语言并不是真正为快速I / O创建的,也不是快速位操作。所以你可以打赌它会比例如更慢,更慢Java或C#,这些已经比本机代码慢得多,更不用说汇编代码或专用指令了。

现在的记忆非常快;然而,CPU要快得多。因此,应该避免避免虚假的内存分配和复制(同样,在完全功能的语言上不那么容易,在本机代码中尽可能多地做到这一点)。但请确保没有缓冲区溢出问题,否则您将在不安全的应用程序中使用快速AES / CFB。