Java 的 CipherOutputStream 与 Apache 的 CryptoOutputStream 性能对比
Java's CipherOutputStream vs. Apache's CryptoOutputStream performance
我正在我的应用程序中实施 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 提供的 CryptoOutputStream
替换标准 CipherOutputStream
,所以代码开始看起来像这样:
...
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,我建议测试一下什么最有效。
我正在我的应用程序中实施 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 提供的 CryptoOutputStream
替换标准 CipherOutputStream
,所以代码开始看起来像这样:
...
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,我建议测试一下什么最有效。