我正在应用程序中实现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的重复,因为该问题明确地涉及纯数据流的性能,但是该问题与加密流的性能有关,答案并不那么明显。
最佳答案
您需要将流包装在BufferedOutputStream
中,这可以提高IO的效率,因为使用了一个较大的写入来代替许多小的写入。
根据实际用途,缓冲CipherOutputStream
可能比out
更好。有时可能有助于将两者包装在一起。 YMMV,我建议您测试最有效的方法。