0

I am getting the below exception. But the KeyStoreException is not caught. And I can read ProviderException. Can I first understand, why two exceptions are thrown and also, why I cannot catch KeyStoreException.

In my code -

try{
 generateKeyApi()
}catch(e: Exception){
 when(e){
 is KeyStoreException -> Log.i("Key store exception")
 else -> Log.i("Its not a keystore exception")
 }
}


05-26 12:33:20.104  3153  3153 E  : Exception occurred in the application's task.
05-26 12:33:20.104  3153  3153 E  : java.security.ProviderException: Keystore 
operation failed
05-26 12:33:20.104  3153  3153 E  : at 
 .engineGenerateKey(AndroidKeyStoreKeyGeneratorSpi.java:322)
05-26 12:33:20.104  3153  3153 E  : at javax.crypto.KeyGenerator.generateKey 
(KeyGenerator.java:604)
05-26 12:33:20.104  3153  3153 E  :     .....
05-26 12:33:20.104  3153  3153 E  : at java.util.concurrent.FutureTask.run 
  (FutureTask.java:266)
05-26 12:33:20.104  3153  3153 E  :     at android.os.Handler.handleCallback 
(Handler.java:789)
05-26 12:33:20.104  3153  3153 E  :     at android.os.Handler.dispatchMessage 
(Handler.java:98)
05-26 12:33:20.104  3153  3153 E  :     at android.os.Looper.loop(Looper.java:164)
05-26 12:33:20.104  3153  3153 E  :     at android.os.HandlerThread.run 
(HandlerThread.java:65)
 05-26 12:33:20.104  3153  3153 E  : Caused by: android.security.KeyStoreException: 
 User authentication required
 05-26 12:33:20.104  3153  3153 E  :    at 
  android.security.KeyStore.getKeyStoreException(KeyStore.java:1112)
 05-26 12:33:20.104  3153  3153 E  :    at 
 android.security.keystore.AndroidKeyStoreKeyGeneratorSpi 
.engineGenerateKey(AndroidKeyStoreKeyGeneratorSpi.java:323)
 05-26 12:33:20.104  3153  3153 E  :    ... 32 more
Aada
  • 1,591
  • 7
  • 30
  • 57
  • 2
    This doesn't look like java. – Federico klez Culloca Aug 25 '22 at 08:09
  • 1
    you'll have to check the code where the exception is thrown. if somewhere in that method call there is another try-catch, in which the stacktrace is printed, but the exception not re-thrown, you can't, unless you alter that code – Stultuske Aug 25 '22 at 08:14
  • The code from where it's thrown is not in my control. As its from Android OS. – Aada Aug 25 '22 at 08:16
  • @Aada if the code where the stacktrace is being logged or the exception is being handled, I don't think you can change that – Stultuske Aug 25 '22 at 08:17
  • take a look here https://stackoverflow.com/questions/50116276/key-user-not-authenticated-understanding-the-android-keystore – Gireada Aug 25 '22 at 08:39

3 Answers3

1

Since you have tagged this question with [java] I am answering it from a Java perspective.

Can I first understand, why two exceptions are thrown

What has happened is that the first exception has been caught and then wrapped in a second exception. Something like this:

try {
    // do something that may throw KeyStoreException
} catch (android.security.KeyStoreException e) {
    // The e argument in the constructor makes the existing
    // KeyStoreException the "cause" for the new ProviderException
    throw new java.security.ProviderException("Keystore operation failed", e);  
}

This is all happening in Android library code.


and also, why I cannot catch KeyStoreException.

Because it has been wrapped. At the point in your code where you are attempting to catch the exception, the exception that is being propagated is ProviderException. Only the exception that is being propagated can be caught.

In order to deal with the inner exception, you would need to do something like this:

 try {
     // do something that may throw ProviderException
 } catch (java.security.ProviderException e) {
     if (e.getCause() instanceof android.security.KeyStoreException) {
         Log.i("This is a keystore exception: ", e.getCause())
     } else {
         // You can reraise the wrapper exception if you want to ...
         throw e;
     }
 }

Java doesn't provide a way to directly catch a nested exception. (And neither does Kotlin.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

You can't catch that nested exception itself, but you can access it the way you do in your code using getCause():

try{
 generateKeyApi()
}catch(e: ProviderException){ // that's the exception being thrown
 when(e.getCause()){ // that's what you're trying to access
 is KeyStoreException -> Log.i("Key store exception")
 else -> Log.i("Its not a keystore exception")
 }
}
daniu
  • 14,137
  • 4
  • 32
  • 53
-1

Just add multiple catch for your try method

try{
    generateKeyApi()
}
catch(e: KeyStoreException){
    Log.i("Key store exception")
}
catch (e: Exception) {
    Log.i("Its not a keystore exception")
}
Gireada
  • 255
  • 1
  • 2
  • 9
  • And how would that help? You think KeyStoreException is not covered by Exception? – Stultuske Aug 25 '22 at 08:31
  • Clearly, the problem seems to come from the generateKeyApi() function, but it also says "why can't I catch the KeyStoreException". – Gireada Aug 25 '22 at 08:37
  • java.security.ProviderException is the exception being thrown here – Evil Washing Machine Aug 25 '22 at 08:40
  • 1
    @Gireada no, the problem seems to come from: engineGenerateKey(). Most likely issue: the Exception is thrown and handled in that method. – Stultuske Aug 25 '22 at 08:40
  • but, either way, if the Exception were propagated to the generateKeyApi(), and it threw it, it would have been caught by: catch ( Exception ), since Exception is a parent to the one thrown – Stultuske Aug 25 '22 at 08:43
  • The main problem is the above stacktrace is thrown which is first 1. Catched by Exception. But on checking the type , it checks for as ProviderException. My goal is to check its nested exception - which is KeystoreExceptio under Provider Exception. That will help me to know why it failed. Kindly let me know. – Aada Aug 25 '22 at 08:52