首页 > 解决方案 > 将 RSA 密钥对导入 KeyStore

问题描述

对于我的具体情况,我必须使用以下代码生成一个 RSA 密钥对(在我的 Android 应用程序中):-

 KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA/ECB/PKCS1Padding");
 generator.initialize(1024,new SecureRandom());
 KeyPair keyPair = generator.generateKeyPair);

如何将 keyPair 导入 Android keyStore ?我有时在 Internet 上搜索,但没有得到如何为 RSA 公钥创建自签名证书以导入到 keystone。

欣赏任何提示甚至示例代码。

标签: androidcertificatersakeystore

解决方案


我假设,您明确需要在 之外生成密钥AndroidKeyStore并将它们导入到AndroidKeyStore. 在 Android 中,推荐的生成密钥的方法是将密钥生成到AndroidKeyStore.

导入密钥AndroidKeyStore非常容易。但棘手的部分是生成自签名证书,因为 Android SDK 和 Java 本身都没有内置的 X509Certificate 生成器。

您可以使用此代码段生成和导入密钥:

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, new SecureRandom());
KeyPair keyPair = generator.generateKeyPair();

Certificate selfSignedCertificate = generateSelfSignedCertificate(keyPair);
Certificate[] certificateChain = new Certificate[]{selfSignedCertificate};

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
keyStore.setKeyEntry("meaningful_key_alias", keyPair.getPrivate(), null, certificateChain);

棘手的部分,生成 X509Certificate:

由于没有提供X509Certificate在 Android 中生成证书的方法,我认为生成证书的最佳方法是使用一些值得信赖的加密库。BouncyCastle是著名的之一,bouncycastle-bcpkix支持证书生成。

在您的应用程序文件中添加依赖项build.gradle

implementation 'org.bouncycastle:bcpkix-jdk15on:1.64' // check for updated version

generateSelfSignedCertificate为您的要求实施方法,例如:

private X509Certificate generateSelfSignedCertificate(KeyPair keyPair) throws IOException, OperatorCreationException, CertificateException {
    AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256withRSA"); // don't use SHA1withRSA. It's not secure anymore.
    AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
    AsymmetricKeyParameter keyParam = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
    SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
    ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(keyParam);
    X500Name issuer = new X500Name("CN=Tolga Okur CA, L=Istanbul");
    X500Name subject = new X500Name("CN=MyBeautifulApp, L=Istanbul");
    BigInteger serial = BigInteger.valueOf(1); // Update with unique one if it will be used to identify this certificate
    Calendar notBefore = Calendar.getInstance();
    Calendar notAfter = Calendar.getInstance();
    notAfter.add(Calendar.YEAR, 20); // This certificate is valid for 20 years.

    X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(issuer,
            serial,
            notBefore.getTime(),
            notAfter.getTime(),
            subject,
            spki);
    X509CertificateHolder certificateHolder = v3CertGen.build(signer);

    return new JcaX509CertificateConverter().getCertificate(certificateHolder);
}

备择方案:

如果您将在服务器上生成密钥并希望将它们安全地导入硬件支持的密钥库,在 Android 9(API 级别 28)及更高版本(随 Keymaster 4 或更高版本提供)之前,您可以使用WrappedKeyEntry导入密钥

https://developer.android.com/training/articles/keystore#ImportingEncryptedKeys


推荐阅读