使用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类型,因此抛出异常。
解决步骤:
- 判断私钥对象类型:读取PEM文件时先识别对象类型,区分加密与未加密的私钥格式
- 添加解密逻辑:针对加密私钥,使用密码构建解密器,解密后得到可处理的
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
相关产品推荐
相关产品推荐

