无法使用scala解密OpenSSL生成的私钥
Unable to decrypt OpenSSL generated private key using scala
我在 terminal/command 中通过以下命令使用 openssl 生成了私钥:
openssl genrsa -aes256 -out private_key.pem 2048
现在我正尝试用 Scala 解密密钥,但我不断收到以下错误:
Exception in thread "main" javax.crypto.BadPaddingException: Given
final block not properly padded at
com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989) at
com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845) at
com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2165) at
com.kewmann.utilities.security.DecryptRSAKeys.decrypt(DecryptRSAKeys.scala:46)
at
TestRSAKeyDecrypt$.delayedEndpoint$TestRSAKeyDecrypt(TestRSAKeyDecrypt.scala:20)
at
TestRSAKeyDecrypt$delayedInit$body.apply(TestRSAKeyDecrypt.scala:18)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34) at
scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main.apply(App.scala:76) at
scala.App$$anonfun$main.apply(App.scala:76) at
scala.collection.immutable.List.foreach(List.scala:381) at
scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76) at
TestRSAKeyDecrypt$.main(TestRSAKeyDecrypt.scala:18) at
TestRSAKeyDecrypt.main(TestRSAKeyDecrypt.scala)
我试过以下方法:
- 更改各种密码算法填充。
- 更改为无限制 JCE 策略,因为我曾一度遇到非法密钥大小错误。
- 换各种解码器。
- 正在使用 OpenSSL 将密钥转换为 PCKS8(可行),但我想以编程方式解密。
所有这些都无法解密我的密钥。下面是我的class,我是基于这个post,[
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, 0, key, 0, 16)
System.arraycopy(d1, 0, key, 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.
对于像我这样的密码学一窍不通的人来说容易多了。
我在 terminal/command 中通过以下命令使用 openssl 生成了私钥:
openssl genrsa -aes256 -out private_key.pem 2048
现在我正尝试用 Scala 解密密钥,但我不断收到以下错误:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at javax.crypto.Cipher.doFinal(Cipher.java:2165) at com.kewmann.utilities.security.DecryptRSAKeys.decrypt(DecryptRSAKeys.scala:46) at TestRSAKeyDecrypt$.delayedEndpoint$TestRSAKeyDecrypt(TestRSAKeyDecrypt.scala:20) at TestRSAKeyDecrypt$delayedInit$body.apply(TestRSAKeyDecrypt.scala:18) at scala.Function0$class.apply$mcV$sp(Function0.scala:34) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main.apply(App.scala:76) at scala.App$$anonfun$main.apply(App.scala:76) at scala.collection.immutable.List.foreach(List.scala:381) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35) at scala.App$class.main(App.scala:76) at TestRSAKeyDecrypt$.main(TestRSAKeyDecrypt.scala:18) at TestRSAKeyDecrypt.main(TestRSAKeyDecrypt.scala)
我试过以下方法:
- 更改各种密码算法填充。
- 更改为无限制 JCE 策略,因为我曾一度遇到非法密钥大小错误。
- 换各种解码器。
- 正在使用 OpenSSL 将密钥转换为 PCKS8(可行),但我想以编程方式解密。
所有这些都无法解密我的密钥。下面是我的class,我是基于这个post,[ 我对安全问题一无所知,所以我需要这方面的帮助。提前致谢。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, 0, key, 0, 16)
System.arraycopy(d1, 0, key, 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.
对于像我这样的密码学一窍不通的人来说容易多了。