Android KeyStore private exponent cannot be extracted
android, java, keystore, rsa, security
Solution
According to the code, I think that the OpenSSL provider prevents the private exponent to be exported when the key has been generated into the device.
@Override
public final BigInteger getPrivateExponent() {
if (key.isEngineBased()) {
throw new UnsupportedOperationException("private exponent cannot be extracted");
}
ensureReadParams();
return privateExponent;
}
Thus, you probably need to specify that you want to use the same crypto provider when retrieving the cipher instance. This provider supports these RSA ciphers:
- RSA/ECB/NoPadding
- RSA/ECB/PKCS1Padding
You should create an instance of the cipher this way:
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
Problem
I want to generate a RSA keypair in the Android Keystore. Since Android 4.3 is should be possible to generate RSA keys in the Android system Keystore. I generate my RSA key by (works fine) ``` Calendar notBefore = Calendar.getInstance(); Calendar notAfter = Calendar.getInstance(); notAfter.add(1, Calendar.YEAR); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(ctx) .setAlias("key") .setSubject( new X500Principal(String.format("CN=%s, OU=%s", "key", ctx.getPackageName()))) .setSerialNumber(BigInteger.ONE) .setStartDate(notBefore.getTime()) .setEndDate(notAfter.getTime()).build(); KeyPairGenerator kpg; kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); kpg.initialize(spec); KeyPair kp = kpg.genKeyPair(); publicKey = kp.getPublic(); privateKey = kp.getPrivate(); ``` my RSA encryption looks like (works also): ``` public static byte[] RSAEncrypt(final byte[] plain) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA"); System.out.println("RSA Encryption key: " + publicKey.getAlgorithm()); System.out.println("RSA Encryption key: " + publicKey.getEncoded()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(plain); return encryptedBytes; } ``` decryption: ``` public static byte[] RSADecrypt(final byte[] encryptedBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher1 = Cipher.getInstance("RSA"); System.out.println("RSA Encryption key: " + privateKey.getAlgorithm()); System.out.println("RSA Encryption key: " + privateKey.getEncoded()); cipher1.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = cipher1.doFinal(encryptedBytes); return decryptedBytes; } ``` In the decryption function i get the following error message(when the privateKey is encoded, and in cipher1.init()): ``` 12-12 21:49:40.338: E/AndroidRuntime(20423): FATAL EXCEPTION: main 12-12 21:49:40.338: E/AndroidRuntime(20423): java.lang.UnsupportedOperationException: private exponent cannot be extracted 12-12 21:49:40.338: E/AndroidRuntime(20423): at org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey.getPrivateExponent(OpenSSLRSAPrivateKey.java:143) ``` I don't get it. Is it not possible to generate a RSA key in the Android KeyStore? Can anyone provide me with an example of generating a RSA key in the Android KeyStore and decrypt with the private Key. Many Thanks in advance!