Mlui
Mlui

Reputation: 149

import RSA keyPair to KeyStore

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.

Upvotes: 2

Views: 2407

Answers (1)

Tolga Okur
Tolga Okur

Reputation: 7113

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

Upvotes: 3

Related Questions