Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java crypto,重置IV是否可以提高性能?_Java_Performance_Scala_Encryption - Fatal编程技术网

Java crypto,重置IV是否可以提高性能?

Java crypto,重置IV是否可以提高性能?,java,performance,scala,encryption,Java,Performance,Scala,Encryption,我使用bouncy castle在Scala中创建了一个加密密码,如下所示 def encryptCipher(secret:SecretKeySpec, iv:IvParameterSpec):Cipher = { val e = Cipher.getInstance("AES/GCM/NoPadding") e.init(Cipher.ENCRYPT_MODE, secret, iv) } 您可以看到,生成密钥规范的缓慢操作已经得到处理。但是,为每条消息调用init

我使用bouncy castle在Scala中创建了一个加密密码,如下所示

  def encryptCipher(secret:SecretKeySpec, iv:IvParameterSpec):Cipher = {
    val e = Cipher.getInstance("AES/GCM/NoPadding")
    e.init(Cipher.ENCRYPT_MODE, secret, iv)
  }
您可以看到,生成密钥规范的缓慢操作已经得到处理。但是,为每条消息调用init本身太慢。 我目前正在处理50K条消息,调用init方法会增加将近4秒的时间


有没有一种方法可以用不太耗时的新IV重新初始化?

在标准库中没有标准的方法, 但是如果您使用AES,有一个很好的解决方法:

IV的目的是消除相同明文加密为相同密文的可能性

您只需在加密前使用随机块大小字节数组更新Cipher.updatebyte[],在解密时使用相同的块即可。这与使用与IV相同的随机块几乎完全相同

要了解这一点,请运行此代码段,它使用上述方法生成完全相同的密码文本-但这只是为了与其他平台兼容,不需要计算特定的IV以确保其安全

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom secureRandom = new SecureRandom();

byte[] keyBytes = new byte[16];
secureRandom.nextBytes(keyBytes);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

byte[] plain = new byte[256];
secureRandom.nextBytes(plain);

// first init using random IV (save it for later)
cipher.init(Cipher.ENCRYPT_MODE, key, secureRandom);
byte[] realIv = cipher.getIV();
byte[] expected = cipher.doFinal(plain);

// now init using dummy IV and encrypt with real IV prefix
IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.ENCRYPT_MODE, key, nullIv);
// calculate equivalent iv
Cipher equivalentIvAsFirstBlock = Cipher.getInstance("AES/CBC/NoPadding");
equivalentIvAsFirstBlock.init(Cipher.DECRYPT_MODE, key, nullIv);
byte[] equivalentIv = equivalentIvAsFirstBlock.doFinal(realIv);

cipher.update(equivalentIv);
byte[] result = cipher.doFinal(plain);
System.out.println(Arrays.equals(expected, result));
解密部分更容易,因为块解密的结果与前面的密文是异或的。请参见,您只需将实IV附加到密文中,然后抛出它:

// Encrypt as before

IvParameterSpec nullIv = new IvParameterSpec(new byte[16]);
cipher.init(Cipher.DECRYPT_MODE, key, nullIv);

cipher.update(realIv);
byte[] result = cipher.doFinal(encrypted);
// result.length == plain.length + 16
// just throw away the first block

政府对此有何评论?他们似乎完全回答了你的问题。当然,我想知道是否有更好的方法。顺便说一句,我发现从Bouncy Castle AES/GCM迁移到Java AES/CBCAlso获得了JDK 7的最新版本,该版本在IntelliJ芯片上带有本机AES处理。您的Iv在所有消息中都是一样的吗?如果是,您可以使用ThreadLocal注意,这个答案只适用于CBC模式,而最初的询问者询问的是GCM模式。