AndroidKeyStore导入密钥后遇公钥获取异常及证书添加失败求助
AndroidKeyStore导入私钥后无法获取条目的解决方案
问题原因
AndroidKeyStore要求私钥条目必须关联对应的X.509证书链,你导入Wrapped私钥时仅导入了私钥材料,未关联公钥证书,导致调用getEntry时抛出UnrecoverableKeyException;而setCertificateEntry失败是因为该别名已绑定为私钥条目,无法直接覆盖为可信证书条目。
解决步骤
导入私钥后,生成对应公钥的自签名证书,通过KeyStore.PrivateKeyEntry将私钥与证书绑定,覆盖原Keystore条目即可,无需使用setCertificateEntry。
1. 添加自签名证书生成方法
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder import java.math.BigInteger import java.security.KeyPair import java.security.cert.X509Certificate import java.util.* fun generateSelfSignedCertificate(keyPair: KeyPair): X509Certificate { val issuer = X500Name("CN=ImportedKeySelfSigned") val subject = issuer // 自签名证书签发者与主体一致 val serial = BigInteger.valueOf(System.currentTimeMillis()) val startDate = Date(System.currentTimeMillis() - 86400000) // 提前1天生效 val endDate = Date(System.currentTimeMillis() + 365L * 86400000) // 有效期1年 val certBuilder = JcaX509v3CertificateBuilder( issuer, serial, startDate, endDate, subject, keyPair.public ) // 使用SHA256withRSA签名算法 val signer = JcaContentSignerBuilder("SHA256withRSA") .setProvider("BC") .build(keyPair.private) return certBuilder.build(signer) as X509Certificate }
2. 修改导入逻辑,绑定证书
在minimumWorkingExample方法中,导入WrappedKeyEntry后添加证书绑定代码:
fun minimumWorkingExample(isStrongBox: Boolean) { // ... 保留原有的密钥生成、导入逻辑 ... androidKeyStore.setEntry(importedKeyAlias, wrappedKeyEntry, null); System.out.println("Key available: ${androidKeyStore.containsAlias(importedKeyAlias)}") // 新增:绑定自签名证书到私钥条目 val selfSignedCert = generateSelfSignedCertificate(keyPairToBeImported) val importedPrivateKey = androidKeyStore.getKey(importedKeyAlias, null) as PrivateKey val privateKeyEntry = KeyStore.PrivateKeyEntry(importedPrivateKey, arrayOf(selfSignedCert)) androidKeyStore.setEntry(importedKeyAlias, privateKeyEntry, null) // 现在可正常获取条目 val importedKey = androidKeyStore.getEntry(importedKeyAlias, null) System.out.println("isPrivateKey: ${importedKey is PrivateKey}") System.out.println("isPrivateKeyEntry: ${importedKey is KeyStore.PrivateKeyEntry}") }
3. 额外注意事项
- 确保BouncyCastle Provider已注册,可在代码初始化阶段添加:
import java.security.Security import org.bouncycastle.jce.provider.BouncyCastleProvider // 注册BC Provider Security.addProvider(BouncyCastleProvider())
- 你的
wrappedKeyAuthorizationList中未配置签名所需的摘要算法,会导致后续签名操作失败,建议补充:
private fun wrappedKeyAuthorizationList(size: Int): DERSequence { // ... 原代码 ... val allDigests: ASN1EncodableVector = ASN1EncodableVector() allDigests.add(ASN1Integer(KeyProperties.DIGEST_SHA256.toLong())) // 添加SHA256摘要 val digestSet: DERSet = DERSet(allDigests) // ... 原代码 ... }
内容的提问来源于stack exchange,提问作者Gamer2015
相关产品推荐
相关产品推荐

