Java的CipherOutputStream与Apache的CryptoOutputStream性能

时间:2018-07-13 10:49:45

标签: java apache encryption aes bouncycastle

我正在我的应用程序中实现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的重复,因为该问题明确地涉及纯数据流的性能,但是这个问题与加密流的性能有关,答案并不那么明显。

1 个答案:

答案 0 :(得分:1)

您需要将流包装在BufferedOutputStream中,这可以提高IO的效率,因为使用了一个较大的写入来代替许多小的写入。

根据确切的用法,缓冲CipherOutputStream可能比out更好。有时可能有助于将两者包装在一起。 YMMV,我建议测试哪种方法最有效。