mogol / flutter_secure_storage

A Flutter plugin to store data in secure storage
https://pub.dartlang.org/packages/flutter_secure_storage
BSD 3-Clause "New" or "Revised" License
1.1k stars 344 forks source link

PlatformException (PlatformException(Exception encountered, read, javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT #541

Open newbieflutter opened 1 year ago

newbieflutter commented 1 year ago

Hi, I have upgraded to latest secure storage plugin flutter_secure_storage: 8.0.0. Below is the complete error.

Exception has occurred.
PlatformException (PlatformException(Exception encountered, read, javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
    at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
    at com.android.org.conscrypt.OpenSSLEvpCipher.doFinalInternal(OpenSSLEvpCipher.java:152)
    at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:374)
    at javax.crypto.Cipher.doFinal(Cipher.java:2055)
    at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.decrypt(StorageCipher18Implementation.java:93)
    at com.it_nomads.fluttersecurestorage.FlutterSecureStorage.decodeRawValue(FlutterSecureStorage.java:249)
    at com.it_nomads.fluttersecurestorage.FlutterSecureStorage.read(FlutterSecureStorage.java:69)
    at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:156)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:236)
    at android.os.HandlerThread.run(HandlerThread.java:67)
, null))

How I initialise and use the flutter secure storage is like below. I keep in in a global file like below. I call the file as authcheck.

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class AuthCheck{ static const String partnerIdKey = 'partnerIdKey';

static const storage = FlutterSecureStorage( aOptions: AndroidOptions( encryptedSharedPreferences: true, ), );

static Future<String?> getPartnerID() async { String? partnerIdKey = await storage.read(key: 'partnerIdKey'); return partnerIdKey; }

static insertDetails(String partnerID) async {

await storage.write(key: partnerIdKey, value: partnerID);

} }

So which ever page I need to insert or read the value I just insert this page example like this import 'authcheck.dart'; I have been working smoothly in most of my apps but suddenly this errors. IF you see I have also put this option encryptedSharedPreferences: true. What else I could be missing from end ?

nblum37 commented 1 year ago

I have a similar issue

baothgvinamilk commented 1 year ago

Does the author have any solutions? 😸

CatlinJiao commented 1 year ago

I have a similar issue

devswingapplicationcom commented 1 year ago

We are seeing the same issue BUT only when building release appbundle and upload to playstore

Not working: 1) Build aab locally and deploy to Playstore 2) install from Playstore 3) --> Boom bad decrypt. 4) uninstall aab. 5) download APK from playstore and install --> Boom, bad decrypt

Working: 1) build apk on dev machine 2) install apk on phone. - everything works as expected.

?

wanoghoco commented 1 year ago

have you tried

final FlutterSecureStorage storage = const FlutterSecureStorage( aOptions: AndroidOptions( encryptedSharedPreferences: true, ), );

biloshkurskyi-ss commented 1 year ago

The same issue was obtained just at the Samsung device (Galaxy S22+). Android 12. Let's look deeper...

Adding of the AndroidOptions helped: static const storage = FlutterSecureStorage(aOptions: AndroidOptions(encryptedSharedPreferences: true,),;

llucie commented 1 year ago

I have exactly the same issue described above, in the same conditions mentionned by @devswingapplicationcom.

To temporarily solve the problem, I clear the secure storage the first time the user installs a new version. This cannot be done by everyone, but it can help on some cases. I use both Shared Preferences and Flutter Secure Storage.

I call the following code at startup:

String version = // current version of your app, e.g. 1.0.0
if (sharedPreferences.getString("secureStorageCleared") != version) {
    await flutterSecureStorage.deleteAll();
    await sharedPreferences.setString("secureStorageCleared", version);
}

This will be called only once per new version.

nick92 commented 1 year ago

Also had this issue, only got this error when built release and installed via play store, not an issue debugging locally, and issue only on Android, not iOS

Clearing the data fixed the issue for me but not a great work-around

AlexDochioiu commented 1 year ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed.

However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted.

When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException.

My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

jttuboi commented 11 months ago

I'm using flutter_secure_storage 8.0.0. Flutter version: 3.10.5. The line is throwing this error is flutterSecureStorage.read(key: 'key').

I don't know if it can help:

image

Samsung SM-A032M, android 11

image

motorola one vision, android 11

image

moto e22, android 12

image

This is the max I can share about the problem.

frankmer commented 9 months ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed.

However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted.

When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException.

My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

This problem seems to occur only on SM-G991B (S21) and SM-G996B (S21+).

LHaanappel commented 8 months ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed.

However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted.

When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException.

My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

I tried this, but the users encounter this exception EVERY time the app is terminated and reopened, not just with a reinstall or a update. As @frankmer stated it only occurs on the S21 and S21+, and seems to occur since the latest android software update for those devices that was released this october.

lberaldodev commented 8 months ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed. However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted. When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException. My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

This problem seems to occur only on SM-G991B (S21) and SM-G996B (S21+).

Hey @frankmer, how can i test it? I tried a lot of times but never get success, can't found any log or reference using browser Stack. But a lot of user have been sending a bad review about this issue.

lberaldodev commented 8 months ago

Has anyone tested using the resetOnError flag (AndroidOptions )? Maybe it can be an internal solution that we don't need to do the try catch in flutter side.

frankmer commented 8 months ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed. However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted. When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException. My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

This problem seems to occur only on SM-G991B (S21) and SM-G996B (S21+).

Hey @frankmer, how can i test it? I tried a lot of times but never get success, can't found any log or reference using browser Stack. But a lot of user have been sending a bad review about this issue.

I never tested it on a real device, but I was able to simulate this error by adding an old FlutterSecureStorage.xml to shared_prefs after deleting the appdata. Our customer report only came from these devices, and there were a lot of them. SM-G998B (S21 Ultra) is now also on the list.

frankmer commented 8 months ago

I tried this, but the users encounter this exception EVERY time the app is terminated and reopened, not just with a reinstall or a update. As @frankmer stated it only occurs on the S21 and S21+, and seems to occur since the latest android software update for those devices that was released this october.

The real question is whether the error has occurred since or because of the software update. Even if deleting the old data is not a good option. It would be nice to know if this is actually an option or if the error still occurs.

lberaldodev commented 8 months ago

Had the same issue previously. I am fairly certain that at least some Samsung devices sometimes ignore the following Android flags:

android:allowBackup="false"
android:fullBackupContent="false"

What this means is that some Samsung phones store (locally / or on some google/samsung server) app data when the app is deleted ; and it restores it when the app is re-installed. However, the padding encryption key DOES NOT leave the device and is deleted when the app is initially deleted. When the user re-installs the app, a new encryption key is generated/returned. The app will attempt to decrypt the old restored data with the new encryption key, leading to the BadPaddingException. My recommendation (and what I am doing) is to clear all encrypted data when encountering this exception and start fresh. If you encounter this, the existing encrypted data is almost certainly permanently lost anyways, since the decryption key does not exist anymore.

This problem seems to occur only on SM-G991B (S21) and SM-G996B (S21+).

Hey @frankmer, how can i test it? I tried a lot of times but never get success, can't found any log or reference using browser Stack. But a lot of user have been sending a bad review about this issue.

I never tested it on a real device, but I was able to simulate this error by adding an old FlutterSecureStorage.xml to shared_prefs after deleting the appdata. Our customer report only came from these devices, and there were a lot of them. SM-G998B (S21 Ultra) is now also on the list.

How can I do it? (change the flutterSecureStorage.xml) ? Can you provide a short guide or share any reference? :) Will be very important simulate it here.

LHaanappel commented 8 months ago

I tried this, but the users encounter this exception EVERY time the app is terminated and reopened, not just with a reinstall or a update. As @frankmer stated it only occurs on the S21 and S21+, and seems to occur since the latest android software update for those devices that was released this october.

The real question is whether the error has occurred since or because of the software update. Even if deleting the old data is not a good option. It would be nice to know if this is actually an option or if the error still occurs.

Using deleteAll and writing something to the secure storage again causes the Exception to be thrown again when our Users are terminating the app and reopening it after. So it seems that the corruption of the data is not a one-time event after the update, but it is completely broken since.

frankmer commented 8 months ago

How can I do it? (change the flutterSecureStorage.xml) ? Can you provide a short guide or share any reference? :) Will be very important simulate it here.

I did it via Android Studio. Device Manager > Run Device > Folder Button under Actions. Then use "Save As..." and "Upload..."

Files found in data/data/{appid}/shared_prefs

lberaldodev commented 8 months ago

How can I do it? (change the flutterSecureStorage.xml) ? Can you provide a short guide or share any reference? :) Will be very important simulate it here.

I did it via Android Studio. Device Manager > Run Device > Folder Button under Actions. Then use "Save As..." and "Upload..."

Files found in data/data/{appid}/shared_prefs

@frankmer thanks for your guide. I did simulate and get the same log error, but the application on device emulator keeps working fine. I saw in the last threads that it crash only in release mode... So its difficult to prevent anything from our side.

frankmer commented 8 months ago

I tried this, but the users encounter this exception EVERY time the app is terminated and reopened, not just with a reinstall or a update. As @frankmer stated it only occurs on the S21 and S21+, and seems to occur since the latest android software update for those devices that was released this october.

Can anyone test if this error still occurs when the application is uninstalled and then reinstalled? Some customers say this fixes the problem.

LHaanappel commented 8 months ago

I tried this, but the users encounter this exception EVERY time the app is terminated and reopened, not just with a reinstall or a update. As @frankmer stated it only occurs on the S21 and S21+, and seems to occur since the latest android software update for those devices that was released this october.

Can anyone test if this error still occurs when the application is uninstalled and then reinstalled? Some customers say this fixes the problem.

That is interesting, the first thing we recommended to our customers was to reinstall the app but that didn't seem to help them.. Could it have something to do with android:allowBackup="false" being deprecated from Android 12 and higher?

This is how we have it in our app:

android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules"`

With in the backup_rules:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

This was the solution when we encountered this problem a few years back, see: https://github.com/mogol/flutter_secure_storage/issues/43#issuecomment-674412687

frankmer commented 8 months ago

That is interesting, the first thing we recommended to our customers was to reinstall the app but that didn't seem to help them.. Could it have something to do with android:allowBackup="false" being deprecated from Android 12 and higher?

This is how we have it in our app:

android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules"`

With in the backup_rules:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

This was the solution when we encountered this problem a few years back, see: #43 (comment)

The current problem has nothing to do with the old problem from a few years ago. If reinstalling really fixes it, then my guess is that the link between the key and the application itself is broken, and reinstalling the application will reestablish that link. Although reinstalling may cause the other problem if backup is enabled.

lberaldodev commented 8 months ago

android:allowBackup="false"

I dont think that the changes on android 12 will impact on this error because they are for the d2d backup.

reference

lberaldodev commented 8 months ago

That is interesting, the first thing we recommended to our customers was to reinstall the app but that didn't seem to help them.. Could it have something to do with android:allowBackup="false" being deprecated from Android 12 and higher? This is how we have it in our app:

android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules"`

With in the backup_rules:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

This was the solution when we encountered this problem a few years back, see: #43 (comment)

The current problem has nothing to do with the old problem from a few years ago. If reinstalling really fixes it, then my guess is that the link between the key and the application itself is broken, and reinstalling the application will reestablish that link. Although reinstalling may cause the other problem if backup is enabled.

I really think that this is the point. Because here the backup is enabled and the reinstall isnt working. So we are changing to false and we will check in the next release. :)

LHaanappel commented 8 months ago

That is interesting, the first thing we recommended to our customers was to reinstall the app but that didn't seem to help them.. Could it have something to do with android:allowBackup="false" being deprecated from Android 12 and higher? This is how we have it in our app:

android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules"`

With in the backup_rules:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

This was the solution when we encountered this problem a few years back, see: #43 (comment)

The current problem has nothing to do with the old problem from a few years ago. If reinstalling really fixes it, then my guess is that the link between the key and the application itself is broken, and reinstalling the application will reestablish that link. Although reinstalling may cause the other problem if backup is enabled.

android:fullBackupContent="false" indeed fixed all our problems, thanks! 😄

lberaldodev commented 8 months ago

That is interesting, the first thing we recommended to our customers was to reinstall the app but that didn't seem to help them.. Could it have something to do with android:allowBackup="false" being deprecated from Android 12 and higher? This is how we have it in our app:

android:allowBackup="false"
android:fullBackupContent="@xml/backup_rules"`

With in the backup_rules:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

This was the solution when we encountered this problem a few years back, see: #43 (comment)

The current problem has nothing to do with the old problem from a few years ago. If reinstalling really fixes it, then my guess is that the link between the key and the application itself is broken, and reinstalling the application will reestablish that link. Although reinstalling may cause the other problem if backup is enabled.

android:fullBackupContent="false" indeed fixed all our problems, thanks! 😄

the try catch suggestion was not necessary? :)

PieterAelse commented 7 months ago

Instead of doing

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

Shouldn't it be:

For Android up to 11:

<full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureKeyStorage"/>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
</full-backup-content>

For Android 12 and up:

<data-extraction-rules>
    <cloud-backup >
        <exclude domain="sharedpref" path="FlutterSecureStorage"/>
        <exclude domain="sharedpref" path="FlutterSecureKeyStorage"/>
    </cloud-backup>
    <device-transfer>
        <exclude domain="sharedpref" path="FlutterSecureStorage"/>
        <exclude domain="sharedpref" path="FlutterSecureKeyStorage"/>
    </device-transfer>
</data-extraction-rules>

As I see that:

bqubique commented 7 months ago

What worked for me was this:

AndroidManifest.xml

    <application
        ...
        android:fullBackupContent="false"
        android:allowBackup="false"
        android:dataExtractionRules="@xml/data_extraction_rules"
...

And as @PieterAelse pointed out:

<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
    <cloud-backup>
        <exclude domain="root" />
        <exclude domain="file" />
        <exclude domain="database" />
        <exclude domain="sharedpref" />
        <exclude domain="external" />
        <exclude domain="sharedpref" path="FlutterSecureStorage"/>
        <exclude domain="sharedpref" path="FlutterSecureKeyStorage"/>
    </cloud-backup>
    <device-transfer>
        <exclude domain="root" />
        <exclude domain="file" />
        <exclude domain="database" />
        <exclude domain="sharedpref" />
        <exclude domain="external" />
        <exclude domain="sharedpref" path="FlutterSecureStorage"/>
        <exclude domain="sharedpref" path="FlutterSecureKeyStorage"/>
    </device-transfer>
</data-extraction-rules>

I'm on flutter_secure_storage: ^9.0.0 and Flutter 3.16.4 if that makes a difference.

vodemn commented 5 months ago

@bqubique Do we need to include data-extraction-rules if android:allowBackup="false"? Seems like if backup is not allowed, then these rules won't be even applied.

bqubique commented 5 months ago

@vodemn I just had a read of this [https://developer.android.com/guide/topics/data/autobackup](Back up user data with Auto Backup), and seems like there's no need for the separate data-extraction-rules file. I can't recall if I tried that, but that should've been the very first thing I would try so I'm guessing I already tried that but it did not work. Our issue wasn't evident on every type of device, my Pixel would work just fine i.e. delete the data after an uninstall, but for some reason Samsung devices had a different way of handling this issue, and in the end what I posted above worked perfectly.

Right now though I have completely replaced flutter_secure_storage with shared_preferenced and encrypt/decrypt data on the fly. I'm sure this is not as safe as flutter_secure_storage but I wanted to have a single point of failure/repository.

orailnoor commented 5 months ago

resolved flutter_secure_storage: ^9.0.0 const secureStorage = FlutterSecureStorage( aOptions: AndroidOptions( encryptedSharedPreferences: true, ));

echap1 commented 4 months ago

resolved flutter_secure_storage: ^9.0.0 const secureStorage = FlutterSecureStorage( aOptions: AndroidOptions( encryptedSharedPreferences: true, ));

Still experiencing this issue and doing this does not resolve...

LuuNgocLan commented 3 months ago

Hope it can helps you!

I am using flutter_secure_storage: ^8.0.0 and upgrading to ^9.0.0 is not a priority, I have added to all method read, write,...

aOptions: AndroidOptions(
encryptedSharedPreferences: true,
)

and it works fine until the deleteAll function, it can't completely delete the data, so I force reset the data by flag resetOnError = true this helps the app's data to be consistent and works well with new aOptions settings.

image

image

image

PlatformException(Exception encountered, deleteAll, java.lang.SecurityException: Could not decrypt key. decryption failed at androidx.security.crypto.a.c(Unknown Source:58) at androidx.security.crypto.a.getAll(Unknown Source:49) at androidx.security.crypto.a$b.a(Unknown Source:11) at androidx.security.crypto.a$b.apply(Unknown Source:0) at jd.a.e(Unknown Source:23) at jd.e$b.run(Unknown Source:135) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: java.security.GeneralSecurityException: decryption failed at la.c$a.b(Unknown Source:136) at androidx.security.crypto.a.c(Unknown Source:13) ... 10 more , null)
moha-b commented 2 weeks ago

Has this been resolved yet? 🥹

renenucci commented 1 week ago

Still hapening.. any news?

moha-b commented 1 week ago

okay that's works for me not sure it works on all devices

1 - clear the cache in the first run

// main.dart
  if (!CachingHelper.instance!.readBoolean(CachingKey.ONBOARDING)) {
    CachingHelper.instance!.clearSecrets();  // <- Here I remove everything at the beginning (there is nothing stored yet)
  }

2 - add this to the mainfist.xml file

 <application
        android:label="Tasker"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:allowBackup="false"
        android:fullBackupContent="false"
    >

3 - Used version

  flutter_secure_storage: ^9.2.2