Java安全模块KeyGenerator是线程安全的吗?如果没有,那么如何修复它?

Java安全模块KeyGenerator是线程安全的吗?如果没有,那么如何修复它?,java,scala,cryptography,aes,key-generator,Java,Scala,Cryptography,Aes,Key Generator,我有一个并发加密/解密程序,在该程序中,通过调用以下代码(用scala编写,Java版本应该相当类似),同时随机生成多个AES128密钥: 每个密钥用于加密固定字节数组,然后使用AESEncrypt和AESEdecrypt函数对其进行解密: def ivParameterSpec = this.synchronized{ import com.schedule1.datapassport.view._ new IvParameterSpec("DataPassports==

我有一个并发加密/解密程序,在该程序中,通过调用以下代码(用scala编写,Java版本应该相当类似),同时随机生成多个AES128密钥:

每个密钥用于加密固定字节数组,然后使用AESEncrypt和AESEdecrypt函数对其进行解密:

  def ivParameterSpec = this.synchronized{
    import com.schedule1.datapassport.view._

    new IvParameterSpec("DataPassports===")
  }

  private def getCipher = this.synchronized {
    Cipher.getInstance("AES/CBC/PKCS5Padding")
  }

  private def nextCipher(aesKey: Key): Cipher = this.synchronized{
    val cipher = getCipher
    cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec)
    cipher
  }

  private def nextDecipher(aesKey: Key): Cipher = this.synchronized{
    val cipher = getCipher
    cipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec)
    cipher
  }

  def nullBytes = Array.fill[Byte](16)(0)

  def aesEncrypt(bytes: Array[Byte], key: Key): Array[Byte] = this.synchronized{
    val effectiveBytes = if (bytes == null) nullBytes
    else bytes
    nextCipher(key).doFinal(effectiveBytes)
  }

  def aesDecrypt(cipher: Array[Byte], key: Key): Array[Byte] = this.synchronized{
    val effectiveBytes = Utils.retry(3){
      nextDecipher(key).doFinal(cipher)
    }
    if (effectiveBytes.toList == nullBytes.toList) null
    else effectiveBytes
  }
该程序在1个核心/线程上平稳运行,但当我逐渐将并发性增加到8时。我遇到以下错误的几率逐渐增加:

javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
...

看起来至少有一个cryptocurrency组件不是线程安全的,尽管我已经将它们中的大多数标记为尽可能的同步。如何解决这个问题?(或者我应该切换到哪个库来避免它?

经过一些测试,我发现sun.misc.BASE64Encoder不是线程安全的,所有问题都在将其实例从单实例更改为动态创建后得到解决。

如果:1密钥不正确2:数据不正确或3:如果IV对小密文不正确,则会出现此错误(但您不正确地使用了静态IV,所以这不会发生)。但我猜密钥和数据混淆的可能性更高。请注意,如果您将密文错误地编码为字符串,也可能发生这种情况。另一个注释:如果您使用的是任何statefull安全类(工厂,
密码
签名
等)如果以多线程的方式,那么您就有麻烦了。但是,您可以共享许多数据容器,例如密钥,因为它们通常是不可变的。我看不到在代码的第一眼看到线程之间有任何重用,但是如果您共享工厂或算法实现,您就没有正确编码。没有必要重用例如
Cipher
,只是用相同的键实例化两个。Maarten可能想说的是,您发布的代码不会显示您描述的问题。这本质上是一个问题,直到您显示。好的一点,并发性是在Apache Spark下实现的,它有一个参数来调整可以同时运行的线程数。我将发布e MCV在主要问题帖子中很快出现。
javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
...