我正在我的应用程序中实现AES256加密,这是通过自定义FilterOutputStream
完成的,其中我用加密的流包装了提供的输出流。目标加密为AES/CTR/NoPadding
。
首先,我开始使用标准Java的javax.crypto.CipherOutputStream
,因此代码如下所示:
...
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, sessionKey, new IvParameterSpec(ivBytes));
this.out = new CipherOutputStream(out, cipher);
但是我注意到使用这种方法加密100 MB文件大约需要10分钟(是的,分钟!),这显然是不合适的吞吐量。
所以我开始动手,我的第一个猜测是将Bouncy Castle用作Cipher
提供程序(因为在SO上的某处建议使用它)。因此,代码变成了:
...
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", BouncyCastleProvider.PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, sessionKey, new IvParameterSpec(ivBytes));
this.out = new CipherOutputStream(out, cipher);
通过这种更改,加密时间缩短到了约45秒,比原来提高了10倍以上,但仍然不合适。
所以我接下来要做的是用Apache Commons Crypto提供的CipherOutputStream
替换标准的CryptoOutputStream
,所以代码看起来像这样:
...
this.out = new CryptoOutputStream("AES/CTR/NoPadding", new Properties(), out, sessionKey, new IvParameterSpec(ivBytes));
而且-瞧-现在同一文件的加密只需约2秒,因此它的速度比BC快15倍,比原始方法快150倍!
所以,我的问题是...背后的原因是什么?仅仅是Java中的默认CipherOutputStream
太糟糕而Apache的CryptoOutputStream
太好吗?但是,Bouncy Castle如何提高标准CipherOutputStream
?我在这里想念什么?
UPD:我相信它不是Java I/O classes and performance的重复,因为该问题明确地涉及纯数据流的性能,但是这个问题与加密流的性能有关,答案并不那么明显。
答案 0 :(得分:1)
您需要将流包装在BufferedOutputStream
中,这可以提高IO的效率,因为使用了一个较大的写入来代替许多小的写入。
根据确切的用法,缓冲CipherOutputStream
可能比out
更好。有时可能有助于将两者包装在一起。 YMMV,我建议测试哪种方法最有效。