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.12k stars 366 forks source link

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

Closed JAICHANGPARK closed 2 years ago

JAICHANGPARK commented 3 years ago

How to fix this problem?

E/flutter (29195): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: PlatformException(Exception encountered, read, javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
E/flutter (29195):  at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
E/flutter (29195):  at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:570)
E/flutter (29195):  at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:351)
E/flutter (29195):  at javax.crypto.Cipher.doFinal(Cipher.java:1741)
E/flutter (29195):  at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.decrypt(StorageCipher18Implementation.java:91)
E/flutter (29195):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.decodeRawValue(FlutterSecureStoragePlugin.java:163)
E/flutter (29195):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.read(FlutterSecureStoragePlugin.java:144)
E/flutter (29195):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access$300(FlutterSecureStoragePlugin.java:29)
E/flutter (29195):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:197)
E/flutter (29195):  at java.lang.Thread.run(Thread.java:764)
E/flutter (29195): , null)
bettdouglas commented 3 years ago

I'm also experiencing the same problem

message_codecs.dart in StandardMethodCodec.decodeEnvelope at line 572 platform_channel.dart in MethodChannel._invokeMethod at line 161 Called from: <asynchronous suspension> flutter_secure_storage.dart in FlutterSecureStorage.read at line 30

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.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:596) at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:363) at javax.crypto.Cipher.doFinal(Cipher.java:2055) at c.c.a.a.b.b(:8) at c.c.a.a.b(:9) at c.c.a.a.d(:2) at c.c.a.a.onMethodCall(:11) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(:2) at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(:5) at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(:2) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(Unknown Source:19) at android.os.Looper.loop(Unknown Source:64) at android.app.ActivityThread.main(Unknown Source:107) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(Unknown Source:11) at com.android.internal.os.ZygoteInit.main(Unknown Source:274) )

bettdouglas commented 3 years ago

I used this workaround by adding <application ... android:allowBackup="false" android:fullBackupContent="false">

to AndroidManifest.xml

sheychan31 commented 3 years ago

I used this workaround by adding <application ... android:allowBackup="false" android:fullBackupContent="false">

to AndroidManifest.xml

@bettdouglas this doesnt seem to work anymore.

sheychan31 commented 3 years ago

I encounter this too when running the app for the 2nd time.

dara1chan commented 3 years ago

I got the same problem.

HemilTheRebel commented 3 years ago

I have the same problem. But the bug only triggers some of the time. I always reproduce it This is my stacktrace:

PlatformException(Exception encountered, read, javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
I/flutter (30164):  at com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_ex(Native Method)
I/flutter (30164):  at com.android.org.conscrypt.OpenSSLCipher$EVP_CIPHER.doFinalInternal(OpenSSLCipher.java:602)
I/flutter (30164):  at com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:365)
I/flutter (30164):  at javax.crypto.Cipher.doFinal(Cipher.java:2055)
I/flutter (30164):  at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.decrypt(StorageCipher18Implementation.java:91)
I/flutter (30164):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.decodeRawValue(FlutterSecureStoragePlugin.java:163)
I/flutter (30164):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.read(FlutterSecureStoragePlugin.java:144)
I/flutter (30164):  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access$300(FlutterSecureStoragePlugin.java:29)
I/flutter (30164):  at com.it_nomads.fl
HemilTheRebel commented 3 years ago

I downgraded to 3.3.3 and the issue disappeared. Change pubspec.yaml to flutter_secure_storage: 3.3.3

rodrigo-martins-ifood commented 3 years ago

I'm having the same problem on 3.3.3

Repost: Version 3.3.4 with

<application ... android:allowBackup="false" android:fullBackupContent="false">

Seem to solve the problem for me.

iNima commented 3 years ago

I added <application ... android:allowBackup="false" android:fullBackupContent="false"> with 3.3.4 but the same error is still there. I had to change back to 3.3.2 and the problem solved.

Andrew-Bekhiet commented 3 years ago

I got the same problem with 3.3.3 and 3.3.4, but when downgraded to 3.3.2 it works fine for me

sydneyagcaoili commented 3 years ago

Used 3.3.2 then 3.3.1+1 it's still a problem..

Andrew-Bekhiet commented 3 years ago

@sydneyagcaoili Double check if the version also changed in the pubspec.lock file

sandeeppatel1986 commented 3 years ago

@Andrew-Bekhiet I have same issue also tried with deleting pubspec.lock file. Any further solution. Flutter 1.20.2 flutter_secure_storage: ^3.3.2

Device Samsung S10+(Android 10)

iNima commented 3 years ago

@sandeeppatel1986 Just for double-checking, go to your .pub_cache/hosted/pub.dartlang.org/ folder and check the version number of flutter_secure_storage. Make sure that the folder name is flutter_secure_storage-3.3.2

mogol commented 3 years ago

If anyone has consistent failures, could you please provide a steps to reproduce from scratch?

If you change manifest, I believe you have to delete and then reinstall the app with new manifest, simple relaunch shouldn't help.

HemilTheRebel commented 3 years ago

@mogol I haven't tried to reproduce this problem due to my schedule currently. I will try to do it today. I haven't changed the manifest in the file since a long time. I had flutter_secure_storage v3.3.3 and it worked. It was when I upgraded to v3.3.4 that I started seeing this error message. I fixed the error by reverting to v3.3.3. My pubspec.yaml has: flutter_secure_storage: 3.3.3 The fix was removing the caret symbol to select an exact version

ldemyanenko commented 3 years ago

I'm having this issue on 3.3.4- 3.3.1 versions with Flutter 1.22. I didn't find any solution. I had to remove this lib from the project

mrevoir commented 3 years ago

Roughly 1% of my users are having this problem -- I'm currently using Flutter 1.20.4 and Dart 2.9.2. I haven't found a direct correlation amongst them. I added code at the same time I went from 3.3.3 to 3.3.4 to allow them to report this particular error so it may have been happening before.

@mogol I'll let you know if I'm able to replicate in a demo project.

For those moving to another library, what did you choose?

koskimas commented 3 years ago

This is randomly happening for me too. The payload that causes it for me is a largeish json string that I unfortunately cannot share here.

I appreciate this great library, and thank you for all the work you've done for it. But unfortunately, this kind of bug is a no-go for this kind of a library that we must be able to trust. I realize that you are probably developing this library on your spare time, but I hope you find time to fix this soon.

koskimas commented 3 years ago

Here's a reproduction.

Create a new app using flutter create

Replace the content of main.dart with this:

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Secure storage bug',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Secure storage bug'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final secureStorage1 = FlutterSecureStorage();

  Future<void> write() async {
    for (int i = 0; i < 100; ++i) {
      secureStorage1.write(key: 'TEST1', value: 'a');
      secureStorage1.write(key: 'TEST2', value: 'a');
    }
  }

  Future<void> read() async {
    for (int i = 0; i < 100; ++i) {
      secureStorage1.read(key: 'TEST1');
      secureStorage1.read(key: 'TEST2');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text('write'),
              onPressed: write,
            ),
            RaisedButton(
              child: Text('read'),
              onPressed: read,
            ),
          ],
        ),
      ),
    );
  }
}

Click write and then read (may need to do that couple of times) and you'll get the error.

So this seems to happen when I run multiple read/write operations in parallel.

koskimas commented 3 years ago

A temporary workaround would be to serialize all calls to this library and to only use one FlutterSecureStorage instance per app. Something like this:

class AsyncMutex {
  Completer<void> _completer;

  Future<void> lock() async {
    while (_completer != null) {
      await _completer.future;
    }

    _completer = Completer<void>();
  }

  void unlock() {
    assert(_completer != null);
    final completer = _completer;
    _completer = null;
    completer.complete();
  }
}

class SecureStorage {
  static const _secureStorage = FlutterSecureStorage();
  static final _mutex = AsyncMutex();

  Future<String> read({String key}) async {
    try {
      await _mutex.lock();
      return await _secureStorage.read(key: key);
    } finally {
      _mutex.unlock();
    }
  }

  Future<void> write({String key, String value}) async {
    try {
      await _mutex.lock();
      await _secureStorage.write(key: key, value: value);
    } finally {
      _mutex.unlock();
    }
  }
}
koskimas commented 3 years ago

Looking at the android code, it seems that it's all completely thread-unsafe. this method is run in a separate thread for each call, and there's no synchronization whatsoever for any method calls except for the ensureInitStorageCipher method.

Thread safety was destroyed in this commit

Tommimon commented 3 years ago

I'm developing two very similar apps, both using secure storage.

Somehow I encountered this problem in only one of those two apps. I tried all the fixes in this issue but none of those worked for me. I tried reinstalling secure storage and now both my apps have this issue :(

I really need this package for my project, any alternative?

mogol commented 3 years ago

@koskimas thanks for repro case 🎉 , I was looking for it quite a while. Let me try it :+1:

koskimas commented 3 years ago

@mogol No problem! Took me a good while too :sweat_smile:

I think many of the other issues here in github are caused by the thread safety issues too. The cipher classes are not thread safe, but they are called from different threads for each flutter call. Every time two calls run in parallel, things can easily go wrong.

The correct solution, I think, would be to have only one worker thread in android native code, in which all operations are run. That way the code doesn't lock the android main thread, and the code is thread safe. HandlerThread could be a good solution.

koskimas commented 3 years ago

@mogol I'd be happy to provide a PR for fixing the thread safety issues. Are you already working on the fix or should I start?

mogol commented 3 years ago

Hey Sami, I was planning to check on the weekends. So if you can do it early :+1: it’s fine.

Sent from ProtonMail Mobile

On Thu, Oct 8, 2020 at 10:21, Sami Koskimäki notifications@github.com wrote:

@mogol I'd be happy to provide a PR for fixing the thread safety issues. Are you already working on the fix or should I start?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

Sorunome commented 3 years ago

A temporary workaround would be to serialize all calls to this library and to only use one FlutterSecureStorage instance per app. Something like this:

class AsyncMutex {
  Completer<void> _completer;

  Future<void> lock() async {
    while (_completer != null) {
      await _completer.future;
    }

    _completer = Completer<void>();
  }

  void unlock() {
    assert(_completer != null);
    final completer = _completer;
    _completer = null;
    completer.complete();
  }
}

class SecureStorage {
  static const _secureStorage = FlutterSecureStorage();
  final _mutex = AsyncMutex();

  Future<String> read({String key}) async {
    try {
      await _mutex.lock();
      return await _secureStorage.read(key: key);
    } finally {
      _mutex.unlock();
    }
  }

  Future<void> write({String key, String value}) async {
    try {
      await _mutex.lock();
      await _secureStorage.write(key: key, value: value);
    } finally {
      _mutex.unlock();
    }
  }
}

If you make the mutex global you can also use multiple instances, in case it is non-trivial to adapt your app to have a single instance for now and you need a quick fix. Of course not having global variables is cleaner code.

koskimas commented 3 years ago

@Sorunome I updated the example :+1:

koskimas commented 3 years ago

Here's a fix https://github.com/mogol/flutter_secure_storage/pull/165

Philipus13 commented 3 years ago

Here's a fix #165

Please merge this PR immediately

mogol commented 3 years ago

Hey guys, Please try 3.3.5, it has been published. Kudos to @koskimas

XinyueZ commented 3 years ago

The issue causes a great user lost, sorry, had to remove the library and replace it with other stable ones.

JAICHANGPARK commented 3 years ago

@koskimas @mogol and Thanks All

vdmitrovskiy-lohika commented 3 years ago

Hi @mogol! With 3.3.5 got this error. I got this error only when deploying app to a phone from Google play. On simulator or uploading apk directly, this error doesn't fire.

Kacppian commented 3 years ago

I'm having an issue with the newer version as well. We're using 3.3.5 and it happens randomly.

Rebloom commented 3 years ago

I wonder if the switch isStrongBox support caused this, It happened when use Google Device with TitanM chip. Wanna know the bug device models.

Rebloom commented 3 years ago

Here are the associate links: https://stackoverflow.com/questions/59552385/aes-key-with-setisstrongboxbacked-failed-decryption https://stackoverflow.com/questions/62639755/android-strongbox-backed-keys-cannot-be-used-for-rsa-encryption https://alexbakker.me/post/mysterious-google-titan-m-bug-cve-2019-9465.html

julianzur commented 3 years ago

@Rebloom: I just ran into the issue this weekend again with 3.3.5 on a Pixel 4a with latest security updates from Nov 2020. According to your sources, the TitanM problem "was fixed in the Android security update of December 2019 for the Pixel 3 and newer.". Do you have any news if the problem could've re-appeared?

Rebloom commented 3 years ago

@Rebloom: I just ran into the issue this weekend again with 3.3.5 on a Pixel 4a with latest security updates from Nov 2020. According to your sources, the TitanM problem "was fixed in the Android security update of December 2019 for the Pixel 3 and newer.". Do you have any news if the problem could've re-appeared?

We meet this issue randomly, but both 2 devices are google 3a+ device, I wonder there is still unfixed problem with google secure chip, cause other Samsung/Xiao Mi devices would never occurs this.Especially the sync code about google soft secure zone to physical chip like TitanM, too hard to catch. You can check up Google Android isStrongBox related code for reference. I am hoping people that all ran into this issue could reveal the device Model so we can check up some common meet.

Rebloom commented 3 years ago

@Rebloom: I just ran into the issue this weekend again with 3.3.5 on a Pixel 4a with latest security updates from Nov 2020. According to your sources, the TitanM problem "was fixed in the Android security update of December 2019 for the Pixel 3 and newer.". Do you have any news if the problem could've re-appeared?

TitanM chip could not be upgrade until a certain authentication, I think If remove isStrongBox feature would solve this question,We can happily use This secure_storage,rather than without Android's trust zone.Just in my opinion. Hope this issue fixed soon.

Soda-Flavour commented 3 years ago

After updating to 3.3.5 for this problem, 2 of the 3 devices that failed have been fixed, but 1 still has errors. Therefore, version 3.3.5 still has an error.

koskimas commented 3 years ago

@Soda-Flavour Did you delete the app and reinstall it? Because the problem is that the old version corrupted the data. No amount of updates will fix the data if it's corrupted. Does 3.3.5 work if you start from a clean slate with no data in the storage?

koskimas commented 3 years ago

People that are getting this error in production but not in development: Are you absolutely sure you have the correct version in the lock file and the CI, or whatever you use for building the production package, actually picks up the correct version?

Soda-Flavour commented 3 years ago

People that are getting this error in production but not in development: Are you absolutely sure you have the correct version in the lock file and the CI, or whatever you use for building the production package, actually picks up the correct version?

  1. Situation The production app has identified the error code. So we updated the version to 3.3.5 and confirmed it in the .lock file. The device that has an error is LG v50. After the update, we deleted the app, installed it, and restarted the device.

2.doctor [✓] Flutter (Channel table, 1.20.2 on Mac OS X 10.15.5 19F101, locale ko-KR) • Flutter version 1.20.2 at /Users/amoskim/flutter • Framework revision bbfbf1770c (4 months ago), 2020-08-13 08:33:09 -0700 • Engine revision 9d5b21729f • Dart version 2.9.1

Do I have to check or do I miss anything?

narritt commented 3 years ago

Got the same problem with Samsung S10 (Android 10). [√] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.19042.631], locale ru-RU) • Flutter version 1.22.5 at C:\flutter • Framework revision 7891006299 (6 weeks ago), 2020-12-10 11:54:40 -0800 • Engine revision ae90085a84 • Dart version 2.10.4

pubspeck.yaml and pubspec.lock also have version 3.3.5. I added this package to my project on version 3.3.5 so I think it contains only the last plugin version

andreasmpet commented 3 years ago

Getting this error now on an app in production which makes the whole app freeze on launch for a portion of our users. Works on Pixel 1 (Android 10), Pixel 2 (Android 11), but fails on my Pixel 5(Android 11). This issue should probably be re-opened.

gabdsg commented 3 years ago

I still have this problem too

julianzur commented 3 years ago

We fixed it by forking the project and removing the strongbox feature. So far we don't see any problems anymore.

chitgoks commented 3 years ago

This was solved with

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

in AndroidManifest.xml