使用 RSA 解密时出现 BadPaddingException
BadPaddingException when decrypting using RSA
我在尝试解密某些加密数据时收到 BadPaddingException。数据加密时字节数组是128字节(在转换为base64之前),并且从base64转换加密数据时也是128字节,所以这部分似乎是正确的。
fun encryptWithRSA(dataToEncrypt: String): String {
val modulus = BigInteger("F70F9BC271DD6ED93EE9...F29901", 16)
val pubExp = BigInteger("010001", 16)
val keyFactory = KeyFactory.getInstance("RSA")
val pubKeySpec = RSAPublicKeySpec(modulus, pubExp)
val key: RSAPublicKey = keyFactory.generatePublic(pubKeySpec) as RSAPublicKey
val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val encryptedBytes = cipher.doFinal(dataToEncrypt.toByteArray())
val encryptedData = Base64.getEncoder().encodeToString(encryptedBytes)
return encryptedData
}
fun decryptWithRSA(dataToDecrypt: String): String {
val PRIVATE_RSA_KEY_PKCS8 =
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPcPm8Jx3W7ZPulQ\n" +
"..." +
"g4Ba8WBhgQ7D/tCAww4l8VhyGJm5/88O+xq2Kr69RIHcWTvhck76n08CQQDSPVB6\n" +
"+MhX/txtOjY8Y+FOFXOeb0EIMhaMQR02+3+wIbN/IMJUyz2Eq/mDX8oX8BwMGlah\n" +
"WSWouLwHaZFcDn7Q"
val keySpec = PKCS8EncodedKeySpec(parseBase64Binary(PRIVATE_RSA_KEY_PKCS8))
val keyFactory = KeyFactory.getInstance("RSA")
val privateKey = keyFactory.generatePrivate(keySpec)
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val bytes = Base64.getDecoder().decode(dataToDecrypt)
val decryptedBytes = cipher.doFinal(bytes)
val decryptedData = Base64.getEncoder().encodeToString(decryptedBytes)
return decryptedData
}
这是完整的异常日志:
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadOAEP(RSAPadding.java:502)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:296)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at dev.wirespec.security.Encryption.decryptWithRSA(Encryption.kt:162)
at dev.wirespec.services.accounts.AccountsServlet$doGet.invokeSuspend(AccountsServlet.kt:31)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
加密和解密中的填充参数不匹配:
在encryptWithRSA()
方法中是:
val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
在decryptWithRSA()
方法中是:
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
选择一种padding进行加解密,应该可以。
注意:正如 Dave 所指出的,没有 pad 是一个严重的安全漏洞,因此最好将它包含在您的密码中。
我得到它来处理这个:
fun encryptWithRSA(dataToEncrypt: String): String {
// See:
val modulus = BigInteger("F70F9B...0F29901", 16)
val pubExp = BigInteger("010001", 16)
val keyFactory = KeyFactory.getInstance("RSA")
val pubKeySpec = RSAPublicKeySpec(modulus, pubExp)
val key: RSAPublicKey = keyFactory.generatePublic(pubKeySpec) as RSAPublicKey
val cipher = Cipher.getInstance("RSA")
cipher.init(Cipher.ENCRYPT_MODE, key)
val encryptedBytes = cipher.doFinal(dataToEncrypt.toByteArray())
val encryptedData = Base64.getEncoder().encodeToString(encryptedBytes)
return encryptedData
}
fun decryptWithRSA(dataToDecrypt: String): String {
val PRIVATE_RSA_KEY_PKCS8 =
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPcPm8Jx3W7ZPulQ\n" +
"..." +
"+MhX/txtOjY8Y+FOFXOeb0EIMhaMQR02+3+wIbN/IMJUyz2Eq/mDX8oX8BwMGlah\n" +
"WSWouLwHaZFcDn7Q"
val keySpec = PKCS8EncodedKeySpec(parseBase64Binary(PRIVATE_RSA_KEY_PKCS8))
val keyFactory = KeyFactory.getInstance("RSA")
val privateKey = keyFactory.generatePrivate(keySpec)
val cipher = Cipher.getInstance("RSA")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val bytes = Base64.getDecoder().decode(dataToDecrypt)
val decryptedBytes = cipher.doFinal(bytes)
val d = decryptedBytes.toString(Charsets.UTF_8)
val decryptedData = Base64.getEncoder().encodeToString(decryptedBytes)
return decryptedData
}
这里最重要的是,当encrypting/decrypting时,你必须使用相同的初始化:
val keyFactory = KeyFactory.getInstance("RSA")
我在尝试解密某些加密数据时收到 BadPaddingException。数据加密时字节数组是128字节(在转换为base64之前),并且从base64转换加密数据时也是128字节,所以这部分似乎是正确的。
fun encryptWithRSA(dataToEncrypt: String): String {
val modulus = BigInteger("F70F9BC271DD6ED93EE9...F29901", 16)
val pubExp = BigInteger("010001", 16)
val keyFactory = KeyFactory.getInstance("RSA")
val pubKeySpec = RSAPublicKeySpec(modulus, pubExp)
val key: RSAPublicKey = keyFactory.generatePublic(pubKeySpec) as RSAPublicKey
val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, key)
val encryptedBytes = cipher.doFinal(dataToEncrypt.toByteArray())
val encryptedData = Base64.getEncoder().encodeToString(encryptedBytes)
return encryptedData
}
fun decryptWithRSA(dataToDecrypt: String): String {
val PRIVATE_RSA_KEY_PKCS8 =
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPcPm8Jx3W7ZPulQ\n" +
"..." +
"g4Ba8WBhgQ7D/tCAww4l8VhyGJm5/88O+xq2Kr69RIHcWTvhck76n08CQQDSPVB6\n" +
"+MhX/txtOjY8Y+FOFXOeb0EIMhaMQR02+3+wIbN/IMJUyz2Eq/mDX8oX8BwMGlah\n" +
"WSWouLwHaZFcDn7Q"
val keySpec = PKCS8EncodedKeySpec(parseBase64Binary(PRIVATE_RSA_KEY_PKCS8))
val keyFactory = KeyFactory.getInstance("RSA")
val privateKey = keyFactory.generatePrivate(keySpec)
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val bytes = Base64.getDecoder().decode(dataToDecrypt)
val decryptedBytes = cipher.doFinal(bytes)
val decryptedData = Base64.getEncoder().encodeToString(decryptedBytes)
return decryptedData
}
这是完整的异常日志:
javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadOAEP(RSAPadding.java:502)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:296)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at dev.wirespec.security.Encryption.decryptWithRSA(Encryption.kt:162)
at dev.wirespec.services.accounts.AccountsServlet$doGet.invokeSuspend(AccountsServlet.kt:31)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
加密和解密中的填充参数不匹配:
在encryptWithRSA()
方法中是:
val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
在decryptWithRSA()
方法中是:
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
选择一种padding进行加解密,应该可以。
注意:正如 Dave 所指出的,没有 pad 是一个严重的安全漏洞,因此最好将它包含在您的密码中。
我得到它来处理这个:
fun encryptWithRSA(dataToEncrypt: String): String {
// See:
val modulus = BigInteger("F70F9B...0F29901", 16)
val pubExp = BigInteger("010001", 16)
val keyFactory = KeyFactory.getInstance("RSA")
val pubKeySpec = RSAPublicKeySpec(modulus, pubExp)
val key: RSAPublicKey = keyFactory.generatePublic(pubKeySpec) as RSAPublicKey
val cipher = Cipher.getInstance("RSA")
cipher.init(Cipher.ENCRYPT_MODE, key)
val encryptedBytes = cipher.doFinal(dataToEncrypt.toByteArray())
val encryptedData = Base64.getEncoder().encodeToString(encryptedBytes)
return encryptedData
}
fun decryptWithRSA(dataToDecrypt: String): String {
val PRIVATE_RSA_KEY_PKCS8 =
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPcPm8Jx3W7ZPulQ\n" +
"..." +
"+MhX/txtOjY8Y+FOFXOeb0EIMhaMQR02+3+wIbN/IMJUyz2Eq/mDX8oX8BwMGlah\n" +
"WSWouLwHaZFcDn7Q"
val keySpec = PKCS8EncodedKeySpec(parseBase64Binary(PRIVATE_RSA_KEY_PKCS8))
val keyFactory = KeyFactory.getInstance("RSA")
val privateKey = keyFactory.generatePrivate(keySpec)
val cipher = Cipher.getInstance("RSA")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val bytes = Base64.getDecoder().decode(dataToDecrypt)
val decryptedBytes = cipher.doFinal(bytes)
val d = decryptedBytes.toString(Charsets.UTF_8)
val decryptedData = Base64.getEncoder().encodeToString(decryptedBytes)
return decryptedData
}
这里最重要的是,当encrypting/decrypting时,你必须使用相同的初始化:
val keyFactory = KeyFactory.getInstance("RSA")