android - 将 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。
欣赏任何提示甚至示例代码。
解决方案
我假设,您明确需要在 之外生成密钥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
推荐阅读
- rxjs - 如何使用 rxjs 从后端 api 获取标头属性?
- java - 如何为包含错误/绑定结果的控制器编写测试?
- scala - 火花处理 VAR 中的 OOM
- mysql - 数到一个数字 x - sql
- eclipse - 如何使用 Eclipse IDE 方法将 some.jar 文件添加到 libs 和 WebContent/WEB-INF/lib 文件夹中?
- wifi - 与信标的 Wifi 连接
- node.js - 如何创建我的数据库以与 sequelize-typescript 一起使用?
- ssas - SSAS/MDX:除以 COUNT 覆盖 FORMAT_STRING?
- r - 为 tint 包安装缺少的 *.sty
- c - 具有交错模式的 STM32 ADC 上的奇怪问题