Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 356
AndyB Avatar asked Nov 08 '22 08:11

AndyB


1 Answers

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
like image 77
Daniel Avatar answered Nov 11 '22 12:11

Daniel