Save and Retrieve KeyPair in AndroidKeystore
Asked Answered
L

2

9

I need to generate a RSA 2048 Keypair, then save it, and recover it if it exists.

At this moment, I have this:

SecureRandom random = new SecureRandom();
RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4);
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SC");
generator.initialize(spec, random);
return generator.generateKeyPair();

This works perfect, but now I tried to save and take it from Android Keystore, but I'm not achieving it. I tryed:

String alias = "TESTINGKEY";
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
if (!keyStore.containsAlias(alias)) {
    SecureRandom random = new SecureRandom();
    RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(keySize, RSAKeyGenParameterSpec.F4);
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SC");
    generator.initialize(spec, random);
    return generator.generateKeyPair();
} else {
    Key key = keyStore.getKey(alias, null);
    if (key instanceof PrivateKey) {
        Certificate cert = keyStore.getCertificate(alias);
        return new KeyPair(cert.getPublicKey(), (PrivateKey) key);
    } else {
        return null;
    }
}

But is not working right, because at the second run of the app, the keystore don't contains the Keypair.

In https://developer.android.com/training/articles/keystore.html?hl=es I saw that the KeyGenParameterSpec, the builder have a "alias" value, but int the RSAKeyGenParameterSpec don't.

How can I save it?

Leighleigha answered 8/2, 2017 at 10:8 Comment(0)
S
15

With AndroidKeyStore is needed to use KeyGenParameterSpec.Builder to generate the keys. Also use AndroidKeyStore instead of SC. You can use the following code

Generate the keys (Android>=23)

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

kpg.initialize(new KeyGenParameterSpec.Builder(
                alias,
                KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                .setKeySize(keySize)
                .build());

KeyPair keyPair = kpg.generateKeyPair();

Load the keys

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.Entry entry = keyStore.getEntry(alias, null);
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey();
Seeger answered 8/2, 2017 at 11:1 Comment(11)
I tried what you post @Seeger but, now, when I try to use the keypair.getPrivateKey().getEncoded(), launch a nullPointerException, because this getEnconded() has "nothing" inside.Leighleigha
The key material of keys stored in the Android Keystore is not accessible. You can use the keys but you can not extract them. It is a security restrictionSeeger
@Leighleigha is my answer clear? If you need to extract the content of the private key you can't use AndroidKeyStore, but you can use it perfectly, and it is the recommend to way to keep it secure. Extracting a private key to store in a file means you would need additional security measuresSeeger
Yes, yes. But the problem I have know with it, is that I need to send to a server my Public Key, (in string format), so when I tried to get the encode of public, to convert to string, is null.Leighleigha
I was referring to the privateKey. The public key raw data is accesible using byte publickey[] = keyStore.getCertificate(alias).getPublicKey().getEncoded();. You will need to convert it to base64 to send it to server as StringSeeger
aaaahhh1!!!!! Perfect then! I just tryed with private one, and I supposed that will hapen with public to. I'll try again. ! Thanks a lot!Leighleigha
Shudy, Could you check it?Seeger
Does kpg.generateKeyPair() also store such generated keys to the "AndroidKeyStore" under the alias name, or the keys need to be stored by another method? If so, how? Please advise.Benoite
@Ωmega, the keys are generated inside "AndroidKeyStore" (even using hardware support if exists) and can be recovered (private key can not be extracted) using aliasSeeger
@Ωmega, kpg.generateKeyPair(); creates a new key pair, public and private, using a random number generator, and internally it stores the keys into the keystore linked to the provided alias. You must call this method to generate the key pair the first timeSeeger
What is not working? I suggest to post a new question with the detailsSeeger
H
0

additional to answer pedrofb for SDK <= 22 you can use KeyPairGeneratorSpec instead of KeyGenParameterSpec

Info: https://developer.android.com/reference/android/security/KeyPairGeneratorSpec.html

Handkerchief answered 11/5, 2019 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.