我假设,您明确需要在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