在 Android (Java/Kotlin) 上获取 X.509 证书 ECDH 私有和 public 密钥

Get X.509 Certificate ECDH private and public key on Android (Java/Kotlin)

我目前正在尝试在我的 android 应用程序中实施 ECDH 算法。 但我遇到了一个问题,我想将私钥和 public 密钥存储在 Android KeyStore 中。但是,为了实现这一点,我需要为我的密钥对获取证书。这就是我被困的地方。

我无法获得 Android KeyStore 允许使用的正确证书。

这是我生成密钥的方式(精简版)

    val ecParamSpec = ECGenParameterSpec("secp521r1")
    val keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "SC")
    keyPairGenerator.initialize(ecParamSpec, SecureRandom())

    val keyPair = keyPairGenerator.generateKeyPair()

    val privateKey = keyPair.private
    val publicKey = keyPair.public

对于证书,我尝试了这个(使用 SHA256WithECDSA)

    val startDate = Calendar.getInstance()
    val endDate = Calendar.getInstance().apply {
        add(Calendar.YEAR, 20)
    }
    val certBuilder = X509v3CertificateBuilder(
        X500Name("CN=MASTERKEY CA Certificate"),
        BigInteger.valueOf(System.currentTimeMillis()),
        startDate.time,
        endDate.time,
        X500Name("DN=MASTERKEY CA Certificate"),
        SubjectPublicKeyInfo.getInstance(keyPair.public.encoded)
    )
    val builder = JcaContentSignerBuilder("SHA256WithECDSA")
    val signer = builder.build(keyPair.private)
    val certBytes = certBuilder.build(signer).encoded
    val certificateFactory = CertificateFactory.getInstance("X.509")

    val certificate = certificateFactory.generateCertificate(ByteArrayInputStream(certBytes)) as X509Certificate

这很容易理解,这是行不通的,因为 JcaContentSignerBuilder 算法与 KeyPairGenerator 不同。这就是 Android KeyStore 开始告诉我有问题的地方。

java.lang.IllegalArgumentException: private key algorithm does not match algorithm of public key in end entity certificate (at index 0)

我使用此代码尝试将密钥存储在 Android KeyStore

keyStore.setEntry("MASTERKEY", KeyStore.PrivateKeyEntry(key[DH.PRIVATE_KEY] as PrivateKey, arrayOf(key[DH.CERTIFICATE] as Certificate)),
                        KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_SIGN).setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                            .build())

我正在使用 spongycastle 以防你问。

如果有人能帮助我,我将不胜感激! 谢谢大家

好的,我解决这个问题的方法是将加密的私钥保存在 sharedpref 中。我知道它不是最好的,但我已经使用由 Android 密钥库处理的 AES 密钥对其进行了加密。除非 AES 被破解,否则没有密钥是无法解密的。