Java 9:AES-GCM 性能

2024-05-13

我进行了一个简单的测试来测量AES-GCM https://en.wikipedia.org/wiki/Galois/Counter_Mode表现在Java 9,通过在循环中加密字节缓冲区。结果有些令人困惑。本机(硬件)加速似乎有效 - 但并非总是有效。进一步来说,

  1. 在循环中加密 1MB 缓冲区时,前 50 秒的速度约为 60 MB/秒。然后它跳到 1100 MB/秒,并保持在那里。 JVM 是否决定在 50 秒(或 3GB 数据)后激活硬件加速?可以配置吗? 我在哪里可以阅读有关新内容的信息AES-GCM执行 (除了这里 http://openjdk.java.net/jeps/246).
  2. 当加密 100MB 缓冲区时,硬件加速根本不会启动。速度稳定为 60 MB/秒。

我的测试代码如下所示:

int plen = 1024*1024;
byte[] input = new byte[plen];
for (int i=0; i < input.length; i++) { input[i] = (byte)i;}
byte[] nonce = new byte[12];
...
// Uses SunJCE provider
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] key_code = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
SecretKey key = new SecretKeySpec(key_code, "AES");
SecureRandom random = new SecureRandom();

long total = 0;
while (true) {
  random.nextBytes(nonce);
  GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce);
  cipher.init(Cipher.ENCRYPT_MODE, key, spec);
  byte[] cipherText = cipher.doFinal(input);
  total += plen;
  // print delta_total/delta_time, once in a while
}

2019 年 2 月更新:HotSpot 已被修改以解决此问题。该修复适用于 Java 13,并且还向后移植到 Java 11 和 12。

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8201633 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8201633, https://hg.openjdk.java.net/jdk/jdk/rev/f35a8aaabcb9 https://hg.openjdk.java.net/jdk/jdk/rev/f35a8aaabcb9

2019 年 7 月 16 日更新:新发布的Java版本(Java 11.0.4)修复了这个问题。


感谢@Holger 指出了正确的方向。前置cipher.doFinal与多个cipher.update调用几乎会立即触发硬件加速。

基于此参考,气相色谱法分析 https://bugs.openjdk.java.net/secure/attachment/25422/GCM%20Analysis.pdf, 我在用着4KB每次更新中的块。现在两者1MB and 100MB缓冲区被加密1100MB/秒 speed (几十毫秒后) .

解决办法是更换

byte[] cipherText = cipher.doFinal(input);

with

int clen = plen + GCM_TAG_LENGTH;
byte[] cipherText = new byte[clen];

int chunkLen = 4 * 1024;
int left = plen;
int inputOffset = 0;
int outputOffset = 0;

while (left > chunkLen) {
  int written = cipher.update(input, inputOffset, chunkLen, cipherText, outputOffset);
  inputOffset += chunkLen;
  outputOffset += written;
  left -= chunkLen;
}

cipher.doFinal(input, inputOffset, left, cipherText, outputOffset);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 9:AES-GCM 性能 的相关文章

随机推荐