AndyB
AndyB

Reputation: 588

android.security.KeyStoreException: Unknown error On a rare number of devices

I'm getting android.security.KeyStoreException: Unknown error On a rare number of devices with different Android Versions (6 - 8)

This is my key generation code:

final KeyPairGenerator keyGenerator = KeyPairGenerator
                        .getInstance(KeyProperties.KEY_ALGORITHM_RSA, 

ANDROID_KEY_STORE);

keyGenerator.initialize(new KeyGenParameterSpec.Builder(ALIAS,
                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                    .setKeySize(2048)
                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                    .build());

return keyGenerator.generateKeyPair();

This is how I load the keyPair:

if (keyStore.containsAlias(ALIAS))
            {
                KeyStore.Entry entry = keyStore.getEntry(ALIAS, null);
                if (entry != null)
                {
                    if (entry instanceof KeyStore.PrivateKeyEntry)
                    {
                        Log.i(TAG, "KeyPair found.");
                        KeyStore.PrivateKeyEntry pke = (KeyStore.PrivateKeyEntry) entry;
                        Certificate cert = pke.getCertificate();

                        if (cert != null)
                        {
                            return new KeyPair(cert.getPublicKey(), pke.getPrivateKey());
                        }

                        Log.w(TAG, "Cert / Public Key is null");
                    }
                }
            }

This is my decryption code:

Cipher RSACipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");          

RSACipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(RSACipher.doFinal(base64.decode(textToDecrypt)), "UTF-8");

Here is a sample stracktrace of a failing decryption process:

Caused by javax.crypto.IllegalBlockSizeException
       at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
       at javax.crypto.Cipher.doFinal(Cipher.java:1736)
       at com.examplecompany.security.EncryptionController.decryptAsymmetric(EncryptionController.java:297)
       at com.example.crypto.android2.services.CryptoClass.decryptMessage(CryptoClass.java:684)
       at com.example.crypto.android2.services.CryptoClass.handleDecryption(CryptoClass.java:619)
       at com.example.crypto.android2.services.CryptoClass.doInBackgroundInternal(CryptoClass.java:450)
       at com.example.crypto.android2.services.CryptoClass.doInBackground(CryptoClass.java:165)
       at com.example.crypto.android2.services.CryptoClass.doInBackground(CryptoClass.java:84)
       at android.os.AsyncTask$2.call(AsyncTask.java:333)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
       at java.lang.Thread.run(Thread.java:764)

Caused by android.security.KeyStoreException: Unknown error
       at android.security.KeyStore.getKeyStoreException(KeyStore.java:1137)
       at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
       at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
       at javax.crypto.Cipher.doFinal(Cipher.java:1736)
       at com.examplecompany.security.EncryptionController.decryptAsymmetric(EncryptionController.java:297)
       at com.example.crypto.android2.services.CryptoClass.decryptMessage(CryptoClass.java:684)
       at com.example.crypto.android2.services.CryptoClass.handleDecryption(CryptoClass.java:619)
       at com.example.crypto.android2.services.CryptoClass.doInBackgroundInternal(CryptoClass.java:450)
       at com.example.crypto.android2.services.CryptoClass.doInBackground(CryptoClass.java:165)
       at com.example.crypto.android2.services.CryptoClass.doInBackground(CryptoClass.java:84)
       at android.os.AsyncTask$2.call(AsyncTask.java:333)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
       at java.lang.Thread.run(Thread.java:764)

It works well in 99.999% of all messages to be encrypted on thousands of devices, but sometimes it fails. Can you help me?

Upvotes: 5

Views: 3542

Answers (1)

Daniel
Daniel

Reputation: 37051

Just found a solution for a similar issue on other question here in SO

I found my answer on the Android Issue Tracker, from what I understand, the unrestricted PublicKey, created to work around another known issue, becomes incompatible with the current Cipher. The work around for this is to specify an OAEPParameterSpec when the Cipher is initialized:

You need the following as a third argument to your Cipher init code

OAEPParameterSpec spec = new OAEPParameterSpec(
        "SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);


RSACipher.init(Cipher.DECRYPT_MODE, privateKey, spec); // I added the same to the init in Cipher.ENCRYPT_MODE too

Upvotes: 1

Related Questions