flutter_secure_storage: 3.1.0: Failed to unwrap key

I did the upgrade to 3.1.0 from 3.0.0. Execution worked just fine, however after cleaning the app data and reinstalling the app this error showed up - which strikes me as odd.

E/FlutterSecureStoragePl(10643): Registration failed
E/FlutterSecureStoragePl(10643): java.security.InvalidKeyException: Failed to unwrap key
E/FlutterSecureStoragePl(10643): 	at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:682)
E/FlutterSecureStoragePl(10643): 	at javax.crypto.Cipher.unwrap(Cipher.java:2121)
E/FlutterSecureStoragePl(10643): 	at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.unwrap(RSACipher18Implementation.java:46)
E/FlutterSecureStoragePl(10643): 	at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:48)
E/FlutterSecureStoragePl(10643): 	at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.<init>(FlutterSecureStoragePlugin.java:46)
E/FlutterSecureStoragePl(10643): 	at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.registerWith(FlutterSecureStoragePlugin.java:33)
E/FlutterSecureStoragePl(10643): 	at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:33)
E/FlutterSecureStoragePl(10643): 	at de.ffuf.uffl2.MainActivity.onCreate(MainActivity.kt:11)
E/FlutterSecureStoragePl(10643): 	at android.app.Activity.performCreate(Activity.java:6998)
E/FlutterSecureStoragePl(10643): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1230)
E/FlutterSecureStoragePl(10643): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2899)
E/FlutterSecureStoragePl(10643): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3046)
E/FlutterSecureStoragePl(10643): 	at android.app.ActivityThread.-wrap11(Unknown Source:0)
E/FlutterSecureStoragePl(10643): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1688)
E/FlutterSecureStoragePl(10643): 	at android.os.Handler.dispatchMessage(Handler.java:105)
E/FlutterSecureStoragePl(10643): 	at android.os.Looper.loop(Looper.java:164)
E/FlutterSecureStoragePl(10643): 	at android.app.ActivityThread.main(ActivityThread.java:6798)
E/FlutterSecureStoragePl(10643): 	at java.lang.reflect.Method.invoke(Native Method)
E/FlutterSecureStoragePl(10643): 	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
E/FlutterSecureStoragePl(10643): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
E/FlutterSecureStoragePl(10643): Caused by: javax.crypto.IllegalBlockSizeException
E/FlutterSecureStoragePl(10643): 	at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:519)
E/FlutterSecureStoragePl(10643): 	at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:680)
E/FlutterSecureStoragePl(10643): 	... 19 more
E/FlutterSecureStoragePl(10643): Caused by: android.security.KeyStoreException: Unknown error
E/FlutterSecureStoragePl(10643): 	at android.security.KeyStore.getKeyStoreException(KeyStore.java:695)
E/FlutterSecureStoragePl(10643): 	at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
E/FlutterSecureStoragePl(10643): 	at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)
E/FlutterSecureStoragePl(10643): 	... 20 more
I/FlutterActivityDelegate(10643): onResume setting current activity to this
Syncing files to device ONEPLUS A3003...
E/flutter (10643): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (10643): MissingPluginException(No implementation found for method read on channel plugins.it_nomads.com/flutter_secure_storage)
E/flutter (10643): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:278:7)
E/flutter (10643): <asynchronous suspension>
E/flutter (10643): #1      FlutterSecureStorage.read (package:flutter_secure_storage/flutter_secure_storage.dart:16:24)
E/flutter (10643): <asynchronous suspension>
E/flutter (10643): #2      AuthService.getAccessToken (package:uffl/network/auth_service.dart:107:37)
E/flutter (10643): <asynchronous suspension>
E/flutter (10643): #3      _RegisterPageState.initState (package:uffl/feature/intro/RegisterPage.dart:42:17)
E/flutter (10643): #4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3751:58)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 19 (5 by maintainers)

Commits related to this issue

Most upvoted comments

As I Understand the issue: Data is stored encrypted in shared prefs. Private key to decrypt the key — in keystore. Shared prefs are restored from backup, but keystore isn’t. So it’s technically impossible to decrypt data , if the key is lost. Another way to handle this — throw exception and let the app delete old data.

I know this issue is closed but after reading both the read.me and this issue it’s not clear to me if my intended use case will work with this package;

Goal

  • Store encrypted items in the keychain so that IF the user loses their device they can access these items on a new device

Disabling automatic backup would clearly not be a good idea in this case.

This still happens on v3.1.2 and only in release mode

@ernestomar workaround worked for me. Setting android:allowBackup="false" application attribute on android/app/src/main/AndroidManifest.xml.

09-26 11:05:24.584 26696-26696/? E/StorageCipher18Impl: unwrap key failed
    java.security.InvalidKeyException: Failed to unwrap key
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:618)
        at javax.crypto.Cipher.unwrap(Cipher.java:1707)
        at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.unwrap(RSACipher18Implementation.java:46)
        at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:44)
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.<init>(FlutterSecureStoragePlugin.java:46)
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.registerWith(FlutterSecureStoragePlugin.java:33)
        at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:20)
        at com.xxxx.xxxxxx.MainActivity.onCreate(MainActivity.java:12)
        at android.app.Activity.performCreate(Activity.java:6259)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2382)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5459)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
     Caused by: javax.crypto.IllegalBlockSizeException
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:486)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:616)
        at javax.crypto.Cipher.unwrap(Cipher.java:1707) 
        at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.unwrap(RSACipher18Implementation.java:46) 
        at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:44) 
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.<init>(FlutterSecureStoragePlugin.java:46) 
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.registerWith(FlutterSecureStoragePlugin.java:33) 
        at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:20) 
        at com.xxxx.xxxxxx.MainActivity.onCreate(MainActivity.java:12) 
        at android.app.Activity.performCreate(Activity.java:6259) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2382) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493) 
        at android.app.ActivityThread.-wrap11(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5459) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
     Caused by: android.security.KeyStoreException: Unknown error
        at android.security.KeyStore.getKeyStoreException(KeyStore.java:632)
        at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:473)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineUnwrap(AndroidKeyStoreCipherSpiBase.java:616) 
        at javax.crypto.Cipher.unwrap(Cipher.java:1707) 
        at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.unwrap(RSACipher18Implementation.java:46) 
        at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:44) 
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.<init>(FlutterSecureStoragePlugin.java:46) 
        at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.registerWith(FlutterSecureStoragePlugin.java:33) 
        at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:20) 
        at com.xxxx.xxxxxx.MainActivity.onCreate(MainActivity.java:12) 
        at android.app.Activity.performCreate(Activity.java:6259) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2382) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493) 
        at android.app.ActivityThread.-wrap11(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5459) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.7.3, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] Android Studio (version 3.2)
[✓] Connected devices (1 available)

• No issues found!

Ok thanks for the clarification. Catching the exception and then deleting shared prefs data is exactly what we implemented atm.

@geeky-dawood How did you able to solve it, only by disabling backup?

As I Understand the issue: Data is stored encrypted in shared prefs. Private key to decrypt the key — in keystore. Shared prefs are restored from backup, but keystore isn’t. So it’s technically impossible to decrypt data , if the key is lost. Another way to handle this — throw exception and let the app delete old data.

Lol, how dare I call myself a developer.

Disabling the backup for android will prevent the crash, but I was wondering if there is a more suitable approach we can take for when we want to keep the ‘allow backup’ option for Android enabled while also using this plugin?