Kotlin 使用RSA解密时出现BadPaddingException

Kotlin 使用RSA解密时出现BadPaddingException,kotlin,encryption,cryptography,rsa,Kotlin,Encryption,Cryptography,Rsa,我在尝试解密一些加密数据时遇到了BadPaddingException。当数据被加密时(转换为base64之前),字节数组是128字节,当从base64转换加密数据时,字节数组也是128字节,所以这部分看起来是正确的 fun encryptWithRSA(dataToEncrypt: String): String { val modulus = BigInteger("F70F9BC271DD6ED93EE9...F29901", 16) val pubExp = BigIn

我在尝试解密一些加密数据时遇到了BadPaddingException。当数据被加密时(转换为base64之前),字节数组是128字节,当从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$1.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)

Encrpyt和Decrypt中的填充参数不匹配:

encryptWithRSA()方法中,它是:

val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
decryptWithRSA()方法中,它是:

val cipher = Cipher.getInstance("RSA/ECB/NoPadding")
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
选择一种用于加密和解密的填充类型,它应该可以工作


注意:正如Dave指出的,没有pad是一个严重的安全缺陷,因此最好将其包含在密码中。

我用它来处理这个问题:

fun encryptWithRSA(dataToEncrypt: String): String {
    // See: https://stackoverflow.com/questions/5789685/rsa-encryption-with-given-public-key-in-java

    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
}
这里最重要的是,加密/解密时,必须使用相同的初始化:

val keyFactory = KeyFactory.getInstance("RSA")

你能分享BadPaddingException日志吗?你确定它是Java吗?@AymanArif在我的帖子中添加了该异常的详细信息。同意,但对于加密,不要选择NoPadding,因为尽管它在解密(encrypt(x))=x的意义上“有效”,但它几乎总是很容易被对手破坏,而且不安全,人们通常在需要安全性时使用加密。在crypto.SX和security.SX上搜索“教科书RSA”。此外,128字节=1024位,RSA-1024虽然还没有作为原语实际断开,但不再被认为为任何值非常低的数据提供了可接受的安全裕度加密和解密都有效。即使我的解决方案有效,我也会让你的解决方案成为公认的解决方案。