【问题标题】:import RSA keyPair to KeyStore将 RSA 密钥对导入 KeyStore
【发布时间】:2020-03-20 14:52:19
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: android certificate rsa keystore


    【解决方案1】:

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

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

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

    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:

    由于没有提供在 Android 中生成 X509Certificate 的方法,我认为生成证书的最佳方法是使用一些值得信赖的加密库。 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

    【讨论】:

      猜你喜欢
      • 2017-10-18
      • 1970-01-01
      • 2010-10-21
      • 2023-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多