问题
For my specific situation, I have to generate a RSA key pair (in my Android application) using the following codes :-
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA/ECB/PKCS1Padding");
generator.initialize(1024,new SecureRandom());
KeyPair keyPair = generator.generateKeyPair);
How can I import the keyPair into the Android keyStore ? I have been searching on the Internet for sometimes and did not get how can I create the self-signed certificate for the RSA public key for import to the keystone.
Appreciate any hints or even sample code.
回答1:
I'm assuming, you explicitly need to generate keys outside of the AndroidKeyStore
and import them into the AndroidKeyStore
. In Android, recommended way to generate keys is generating keys into the AndroidKeyStore
.
Importing keys to the AndroidKeyStore
is quite easy. But the tricky part is generating self-signed certificate because there is no built-in X509Certificate generator neither in Android SDK nor in Java itself.
You can generate and import keys with this code snippet:
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);
Tricky part, generating X509Certificate:
Because of there is no provided way to generate X509Certificate
in an Android, I think the best way to generate certificate is using some trustworthy crypto libraries. BouncyCastle
is one of the famous one and bouncycastle-bcpkix
supports certificate generation.
Add dependency in your app's build.gradle
file:
implementation 'org.bouncycastle:bcpkix-jdk15on:1.64' // check for updated version
implement generateSelfSignedCertificate
method for your requirement something like:
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);
}
Alternatives:
If you will generate keys on the server and want to import them securely into the hardware backed keystore, prior to Android 9 (API level 28) and higher which shipped with Keymaster 4 or higher, you can import keys using WrappedKeyEntry
https://developer.android.com/training/articles/keystore#ImportingEncryptedKeys
来源:https://stackoverflow.com/questions/59029712/import-rsa-keypair-to-keystore