You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kotlin和Bouncy Castle读取私钥时遇PKCS8加密私钥错误

问题描述

我尝试用Bouncy Castle、Ktor和Kotlin编写函数读取私钥,代码如下:

fun readPrivateKey(filePath: String): Result<RSAPrivateKey> = runCatching {
  val pemParse = PEMParser(FileReader(filePath))
  val privateKey = PrivateKeyInfo.getInstance(pemParse.readObject())
  JcaPEMKeyConverter().getPrivateKey(privateKey) as RSAPrivateKey
}.onFailure { throw it }

测试时出现以下错误:

unknown object in getInstance: org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo
java.lang.IllegalArgumentException: unknown object in getInstance: org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo

错误发生在这一行:privateKey = PrivateKeyInfo.getInstance(pemParse.readObject())

我用这条命令生成私钥:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -aes-256-cbc -out development_erp_private.key

请问我哪里操作有误?


问题原因与解决办法

你的问题出在生成的私钥是加密过的PKCS8格式,当前代码仅能处理未加密的PrivateKeyInfo对象,无法识别加密后的PKCS8EncryptedPrivateKeyInfo类型,因此抛出异常。

解决步骤:

  1. 判断私钥对象类型:读取PEM文件时先识别对象类型,区分加密与未加密的私钥格式
  2. 添加解密逻辑:针对加密私钥,使用密码构建解密器,解密后得到可处理的PrivateKeyInfo

修改后的完整代码

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo
import org.bouncycastle.openssl.PEMParser
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
import org.bouncycastle.openssl.jcajce.JcePKCSPBEInputDecryptorProviderBuilder
import java.io.FileReader
import java.security.Security
import org.bouncycastle.jce.provider.BouncyCastleProvider

// 初始化BouncyCastle提供者,建议在应用启动时调用一次
fun initBouncyCastle() {
    Security.addProvider(BouncyCastleProvider())
}

fun readPrivateKey(filePath: String, password: CharArray): Result<RSAPrivateKey> = runCatching {
    val pemParser = PEMParser(FileReader(filePath))
    val obj = pemParser.readObject()
    
    val privateKeyInfo = when (obj) {
        is PKCS8EncryptedPrivateKeyInfo -> {
            val decryptorProvider = JcePKCSPBEInputDecryptorProviderBuilder()
                .setProvider("BC")
                .build(password)
            obj.decryptPrivateKeyInfo(decryptorProvider)
        }
        is PrivateKeyInfo -> obj
        else -> throw IllegalArgumentException("不支持的私钥格式")
    }

    JcaPEMKeyConverter()
        .setProvider("BC")
        .getPrivateKey(privateKeyInfo) as RSAPrivateKey
}.onFailure { throw it }

可选方案:生成未加密私钥

如果不需要加密私钥,可重新生成不带加密的私钥,去掉-aes-256-cbc参数即可:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out development_erp_private.key

内容的提问来源于stack exchange,提问作者Rodrigo Batista

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:30:59