无法使用Scala解密OpenSSL生成的私钥

问题描述

我已经在终端/命令中使用以下命令使用openssl生成了私钥:

openssl genrsa -aes256 -out private_key.pem 2048

现在,我正在尝试使用Scala解密密钥,但我不断收到以下错误消息:

线程“主”中的异常javax.crypto.BadPaddingException:给定 最后一块未正确填充 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989)位于 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845)在 com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) 在javax.crypto.Cipher.doFinal(Cipher.java:2165)在 com.kewmann.utilities.security.DecryptRSAKeys.decrypt(DecryptRSAKeys.scala:46) 在 TestRSAKeyDecrypt $ .delayedEndpoint $ TestRSAKeyDecrypt $ 1(TestRSAKeyDecrypt.scala:20) 在 TestRSAKeyDecrypt $ delayedInit $ body.apply(TestRSAKeyDecrypt.scala:18) 在scala.Function0 $ class.apply $ mcV $ sp(Function0.scala:34)在 scala.runtime.AbstractFunction0.apply $ mcV $ sp(AbstractFunction0.scala:12) 在scala.App $$ anonfun $ main $ 1.apply(App.scala:76)在 scala.App $$ anonfun $ main $ 1.apply(App.scala:76)在 scala.collection.immutable.List.foreach(List.scala:381)在 scala.collection.generic.TraversableForwarder $ class.foreach(TraversableForwarder.scala:35) 在scala.App $ class.main(App.scala:76)在 TestRSAKeyDecrypt $ .main(TestRSAKeyDecrypt.scala:18)在 TestRSAKeyDecrypt.main(TestRSAKeyDecrypt.scala)

我尝试了以下操作:

  1. 更改各种密码算法填充。
  2. 由于我一度收到非法密钥大小错误,因此更改为Unlimited JCE Policy。
  3. 更改各种解码器。
  4. 使用OpenSSL将密钥转换为PCKS8(可行),但我想以编程方式进行解密。

所有这些都无法解密我的密钥。下面是我根据此帖子[https://stackoverflow.com/questions/35276820/decrypting-an-openssl-pem-encoded-rsa-private-key-with-java]编写的课程:

private val random = new SecureRandom()

@throws(classOf[GeneralSecurityException])
def decrypt(keyDataStr: String,ivHex: String,password: String)
{
    val pw = password.getBytes(StandardCharsets.UTF_8)
    val iv = h2b(ivHex)
    val secret = opensslKDF(pw,iv)
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.DECRYPT_MODE,secret,new IvParameterSpec(iv))
    val keyBytes = Base64.getMimeDecoder.decode(keyDataStr)
    val pkcs1 = cipher.doFinal(keyBytes)
    /* See note for deFinition of "decodeRSAPrivatePKCS1" */
    val spec = decodeRSAPrivatePKCS1(pkcs1)
    val rsa = KeyFactory.getInstance("RSA")
    rsa.generatePrivate(spec).asInstanceOf[RSAPrivateKeySpec]
}

@throws(classOf[NoSuchAlgorithmException])
private def opensslKDF(pw: Array[Byte],iv: Array[Byte]): SecretKeySpec = {
    val md5 = MessageDigest.getInstance("MD5")
    md5.update(pw)
    md5.update(iv)
    val d0 = md5.digest()
    md5.update(d0)
    md5.update(pw)
    md5.update(iv)
    val d1 = md5.digest()
    val key = new Array[Byte](24)
    System.arraycopy(d0,key,16)
    System.arraycopy(d1,16,8)
    new SecretKeySpec(key,"AES")
}

private def h2b(s: CharSequence): Array[Byte] = {
  val len = s.length();
  val b = new Array[Byte](len / 2)
  var src = 0
  var dst = 0
  while ( {
    src < len
  }) {
    val hi = Character.digit(s.charat({
      src += 1; src - 1
    }),16)
    val lo = Character.digit(s.charat({
      src += 1; src - 1
    }),16)
    b(dst) = (hi << 4 | lo).toByte

    dst += 1
  }
  b
}

def decodeRSAPrivatePKCS1(encoded: Array[Byte]) = {
  val input = ByteBuffer.wrap(encoded)
  if (der(input,0x30) != input.remaining()) {
    throw new IllegalArgumentException("Excess data")
  }
  if (!BigInteger.ZERO.equals(derint(input))) {
    throw new IllegalArgumentException("Unsupported version")
  }
  val n = derint(input)
  val e = derint(input)
  val d = derint(input)
  val p = derint(input)
  val q = derint(input)
  val ep = derint(input)
  val eq = derint(input)
  val c = derint(input)
  new RSAPrivateCrtKeySpec(n,e,d,p,q,ep,eq,c)
}

private def derint(input: ByteBuffer): BigInteger = {
  val len = der(input,0x02)
  val value = new Array[Byte](len)
  input.get(value)
  new BigInteger(+1,value)
}

private def der(input: ByteBuffer,exp: Int): Int = {
  val tag = input.get() & 0xFF
  if (tag != exp) {
    throw new IllegalArgumentException("Unexpected tag")
  }
  var n = input.get() & 0xFF
  if (n < 128) {
    n
  }
  else {
    n &= 0x7F
    if ((n < 1) || (n > 2)) {
      throw new IllegalArgumentException("Invalid length")
    }
    var len = 0
    for (i <- 0 to n) {
      len <<= 8
      len |= input.get() & 0xFF
    }
    len
  }
}

def alphanumeric(nrChars: Int = 24): String = {
  new BigInteger(nrChars * 5,random).toString(32)
}

我对安全性一无所知,因此在这方面我需要一些帮助。预先感谢。

解决方法

决定放弃我发布并使用BouncyCastle的方法。示例代码here

像我这样无知的冰冻术要容易得多。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...