Viewing version 11.2.0. Open the latest package page.

flutter_secure_storage

11.2.0

A Flutter plugin for securely storing sensitive data using encrypted storage.

Download archive

Readme

flutter_secure_storage

Pub Version Pub Version Prerelease Build Status Code Quality: Very Good Analysis Codecov GitHub Sponsors

A Flutter plugin to securely store sensitive data in a key-value pair format using platform-specific secure storage solutions. It supports Android, iOS, macOS, Windows, and Linux.

Features

  • Secure Data Storage: Uses Keychain for iOS/macOS, custom secure ciphers with optional biometric authentication for Android, and platform-specific secure mechanisms for Windows, Linux, and Web.
  • Encryption: Encrypts data before storing it using platform-specific encryption (RSA OAEP + AES-GCM on Android by default).
  • Cross-Platform: Works seamlessly across Android, iOS, macOS, Windows, Linux, and Web.
  • Biometric Authentication: Optional biometric authentication support on Android (API 23+) and iOS/macOS.
  • Customizable Options: Configure encryption algorithms, accessibility attributes, biometric requirements, and more.

Important notice for Android

Version 10.0.0 introduces a major security update with custom cipher implementations. The deprecated Jetpack Security library's encryptedSharedPreferences is no longer recommended.

Key Changes:

  • New default ciphers: RSA OAEP (key cipher) + AES-GCM (storage cipher)
  • New AndroidOptions() and AndroidOptions.biometric() constructors
  • Automatic migration from old ciphers via migrateOnAlgorithmChange (enabled by default)
  • Minimum Android SDK is now 23 (Android 6.0+)
  • Enhanced biometric authentication with graceful degradation

Important notice for Web

flutter_secure_storage only works on HTTPS or localhost environments. Please see this issue for more information.

Installation

If not present already, please call WidgetsFlutterBinding.ensureInitialized() in your main before you do anything with the MethodChannel. Please see this issue for more info.

Add the dependency in your pubspec.yaml file:

dependencies:
flutter_secure_storage: ^<latest_version>

Then run:

flutter pub get

Usage

Import the Package

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

Create an Instance

// Default secure storage - Uses RSA OAEP + AES-GCM (recommended)
final storage = FlutterSecureStorage();

// Or with explicit Android options
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions(),
);

// Biometric storage with graceful degradation
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    enforceBiometrics: false, // Works without biometrics
    biometricPromptTitle: 'Authenticate to access data',
  ),
);

// Strict biometric enforcement (requires device security)
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    enforceBiometrics: true, // Requires biometric/PIN/pattern
    biometricPromptTitle: 'Authentication Required',
  ),
);

Write Data

await storage.write(key: 'username', value: 'flutter_user');

Read Data

String? username = await storage.read(key: 'username');

Delete Data

await storage.delete(key: 'username');

Delete All Data

await storage.deleteAll();

Check for Key Existence

bool containsKey = await storage.containsKey(key: 'username');

Configuration

Each platform provides its own set of configuration options to tailor secure storage behavior. For example, on iOS, the IOSOptions class includes an accessibility option that determines when the app can access secure values stored in the Keychain.

The accessibility option allows you to specify conditions under which secure values are accessible. For instance:

  • first_unlock: Enables access to secure values after the device is unlocked for the first time after a reboot.
  • first_unlock_this_device: Allows access to secure values only after the device is unlocked for the first time since installation on this device.
  • unlocked (default): Values are accessible only when the device is unlocked.

Here’s an example of configuring the accessibility option on iOS:

final options = IOSOptions(accessibility: KeychainAccessibility.first_unlock);
await storage.write(key: key, value: value, iOptions: options);

By setting accessibility, you can control when secure values are accessible, enhancing security and usability for your app on iOS. Similar platform-specific options are available for other platforms as well.

Android

Disabling Auto Backup

Note By default Android backups data on Google Drive. It can cause exception java.security.InvalidKeyException: Failed to unwrap key. You need to:

Add the following to your android/app/src/main/AndroidManifest.xml:

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

Encryption Options (Version 10.0.0+)

Version 10 introduces new cipher options and biometric support. Choose the configuration that fits your security requirements:

Constructor Key Cipher Storage Cipher Biometric Support Description
AndroidOptions() RSA/ECB/OAEPWithSHA-256AndMGF1Padding AES/GCM/NoPadding No Default. Standard secure storage with RSA OAEP key wrapping. Strong authenticated encryption without biometrics. Recommended for most use cases.
AndroidOptions.biometric(enforceBiometrics: false) AES/GCM/NoPadding AES/GCM/NoPadding Optional KeyStore-based with optional biometric authentication. Gracefully degrades if biometrics unavailable.
AndroidOptions.biometric(enforceBiometrics: true) AES/GCM/NoPadding AES/GCM/NoPadding Required KeyStore-based requiring biometric/PIN authentication. Throws error if device security not available. Requires API 28+ for biometric enforcement.
AndroidOptions.biometric(enforceBiometrics: true, biometricType: AndroidBiometricType.strongBiometricOnly) AES/GCM/NoPadding AES/GCM/NoPadding Required (strong) Same as above but restricts authentication to Class 3 (strong) biometrics only. Device credentials (PIN/pattern/password) are rejected.

Custom Cipher Combinations (Advanced)

For advanced users, all combinations below are supported using the AndroidOptions() constructor with custom parameters:

Key Cipher Algorithm Storage Cipher Algorithm Implementation Biometric Support
RSA_ECB_PKCS1Padding AES_CBC_PKCS7Padding RSA-wrapped AES No
RSA_ECB_PKCS1Padding AES_GCM_NoPadding RSA-wrapped AES No
RSA_ECB_OAEPwithSHA_256andMGF1Padding AES_CBC_PKCS7Padding RSA-wrapped AES No
RSA_ECB_OAEPwithSHA_256andMGF1Padding AES_GCM_NoPadding RSA-wrapped AES No
AES_GCM_NoPadding AES_CBC_PKCS7Padding KeyStore AES Optional (via enforceBiometrics)
AES_GCM_NoPadding AES_GCM_NoPadding KeyStore AES Optional (via enforceBiometrics)

Notes:

  • RSA key ciphers wrap the AES encryption key with RSA. No biometric support.
  • AES key cipher stores the key directly in Android KeyStore. Supports optional biometric authentication.
  • enforceBiometrics parameter (default: false):
    • false: Gracefully degrades if biometrics unavailable
    • true: Strictly requires device security (PIN/pattern/biometric), throws exception if unavailable

Migration with Backup Protection

When upgrading between versions that use different encryption algorithms, flutter_secure_storage can automatically migrate your data. To protect against data loss during migration (e.g., app crashes), enable backup protection:

final storage = FlutterSecureStorage(
  aOptions: AndroidOptions(
    migrateWithBackup: true, // Enable crash-resistant migration
  ),
);

How it works:

  1. Before migration: Creates backup copies of encrypted data with _BACKUP suffix
  2. During migration: Tracks progress per-key using _MIGRATED markers
  3. After migration: Automatically cleans up backup and progress markers
  4. On crash: Resumes from last checkpoint without data loss

When to use:

  • Recommended for production apps storing critical data (wallet seeds, credentials, etc.)
  • Protects against data loss if migration crashes mid-process
  • Enables safe recovery to pre-migration state if needed

Default behavior:

  • migrateWithBackup: false (default for backward compatibility)
  • When disabled, automatic migration is turned off to prevent unsafe data loss
  • Enable this option if you want crash-resistant migrations

Example migration scenarios:

// Migrating from old to new algorithm with backup protection
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions(
    migrateWithBackup: true,
    keyCipherAlgorithm: KeyCipherAlgorithm.RSA_ECB_OAEPwithSHA_256andMGF1Padding,
    storageCipherAlgorithm: StorageCipherAlgorithm.AES_GCM_NoPadding,
  ),
);

// Migrating to biometric storage with backup
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    migrateWithBackup: true,
    enforceBiometrics: false,
  ),
);

Technical details:

  • Backup data stored alongside original data in SharedPreferences
  • Per-key progress tracking prevents re-processing already-migrated keys
  • Idempotent: safe to run multiple times
  • Supports all migration paths (non-biometric ↔ biometric, algorithm changes)
  • Automatic cleanup after successful migration

iOS

Biometric Authentication

Flutter Secure Storage supports biometric authentication (fingerprint, face recognition, etc.) on Android API 23+.

Required Permissions

To use biometric authentication, add the following permission to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.USE_BIOMETRIC"/>

For devices running Android 9.0 (API 28) and above, USE_BIOMETRIC is the recommended permission.

For backward compatibility with devices running Android 6.0 - 8.1 (API 23-27), you may also need:

<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
Using Biometric Authentication

You can enable biometric authentication using the AndroidOptions.biometric() constructor:

// Optional biometric authentication (graceful degradation)
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    enforceBiometrics: false, // Default - works without biometrics
    biometricPromptTitle: 'Unlock to access your data',
    biometricPromptSubtitle: 'Use fingerprint or face unlock',
  ),
);

// Strict biometric enforcement (requires device security)
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    enforceBiometrics: true, // Requires biometric/PIN/pattern
    biometricPromptTitle: 'Biometric authentication required',
  ),
);

// Strong biometric only — device credentials (PIN/pattern/password) rejected
final storage = FlutterSecureStorage(
  aOptions: AndroidOptions.biometric(
    enforceBiometrics: true,
    biometricType: AndroidBiometricType.strongBiometricOnly,
    biometricPromptTitle: 'Fingerprint required',
  ),
);

Note: When enforceBiometrics: true, the app will throw an exception if the device has no PIN, pattern, password, or biometric enrolled.

biometricType controls which authentication methods satisfy the biometric prompt (only applies when using AES_GCM_NoPadding key cipher):

Value Accepted methods
AndroidBiometricType.biometricOrDeviceCredential Class 3 biometrics or PIN / pattern / password (default)
AndroidBiometricType.strongBiometricOnly Class 3 (strong) biometrics only — credentials rejected

Note: On Android 10 (API level 29) and lower, setAllowedAuthenticators is unavailable. Device credentials (PIN/pattern/password) are not accepted on these versions — only Class 3 (strong) biometrics work, regardless of the biometricType setting.

Requirements
  • API Level: Android 6.0 (API 23) minimum for basic encryption
  • API Level: Android 9.0 (API 28) minimum for enforced biometric authentication
  • API Level: Android 11.0 (API 30) minimum for AndroidBiometricType.strongBiometricOnly to be fully enforced
  • Device Security: Device must have a PIN, pattern, password, or biometric enrolled (when using enforceBiometrics: true)
  • Permissions: USE_BIOMETRIC permission in AndroidManifest.xml

Migration from Version 9.x

Version 10 automatically migrates data from older cipher algorithms when migrateOnAlgorithmChange: true (enabled by default). If you were using encryptedSharedPreferences in version 9, the data will be automatically migrated to the new cipher implementation.

To disable automatic migration:

final storage = FlutterSecureStorage(
  aOptions: AndroidOptions(
    migrateOnAlgorithmChange: false,
  ),
);

macOS & iOS

You also need to add Keychain Sharing as capability to your macOS runner. To achieve this, please add the following in both your macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements for macOS or for iOS ios/Runner/DebugProfile.entitlements and ios/Runner/Release.entitlements.

<key>keychain-access-groups</key>
<array/>

If you have set your application up to use App Groups then you will need to add the name of the App Group to the keychain-access-groups argument above. Failure to do so will result in values appearing to be written successfully but never actually being written at all. For example if your app has an App Group named "aoeu" then your value for above would instead read:

<key>keychain-access-groups</key>
<array>
	<string>$(AppIdentifierPrefix)aoeu</string>
</array>

If you are configuring this value through XCode then the string you set in the Keychain Sharing section would simply read "aoeu" with XCode appending the $(AppIdentifierPrefix) when it saves the configuration.

macOS: Keychain Sharing requires provisioning

Adding keychain-access-groups enables Keychain Sharing, which requires a provisioning profile. On a free (non-Program) Apple Developer account, Xcode responds by embedding a machine-specific development provisioning profile, so the built app will only launch on the Mac that built it, and can't be distributed to other Macs (for example as a signed .app/.dmg outside the App Store).

If your app doesn't actually need Keychain Sharing (no App Group, no sharing items with another app of yours), you can avoid the entitlement entirely by disabling the data protection keychain on macOS instead:

final storage = Platform.isMacOS
    ? const FlutterSecureStorage(
        mOptions: MacOsOptions(usesDataProtectionKeychain: false),
      )
    : const FlutterSecureStorage();

This falls back to the legacy (non-data-protection) Keychain, which doesn't require keychain-access-groups or a provisioning profile.

Web

Flutter Secure Storage uses an experimental implementation using WebCrypto. Use at your own risk at this time. Feedback welcome to improve it. The intent is that the browser is creating the private key, and as a result, the encrypted strings in local_storage are not portable to other browsers or other machines and will only work on the same domain.

It is VERY important that you have HTTP Strict Forward Secrecy enabled and the proper headers applied to your responses or you could be subject to a javascript hijack.

Please see:

application-specific key option

On the web, all keys are stored in LocalStorage. flutter_secure_storage has an option for the web to wrap this stored key with an application-specific key to make it more difficult to analyze.

final _storage = const FlutterSecureStorage(
  webOptions: WebOptions(
    wrapKey: '${your_application_specific_key}',
    wrapKeyIv: '${your_application_specific_iv}',
  ),
);

Windows

You need the C++ ATL libraries installed along with the rest of Visual Studio Build Tools. Download them from here and make sure the C++ ATL under optional is installed as well.

Linux

You need to install Libsecret packages:

  1. development package: on your machine to build the project
  2. runtime package: to run the application (add it as a dependency after packaging your app).

For Ubuntu / Debian-based distros (e.g., Linux Mint, PopOS):

sudo apt install libsecret-1-0 libsecret-1-dev

For Fedora / RHEL / CentOS distros:

sudo dnf install libsecret libsecret-devel

For Arch based distros (a single package containing both development and runtime modules):

sudo pacman -S libsecret

Libsecret supports both org.freedesktop.Secret and org.freedesktop.portal.Secret and is compatible with Flatpak or sandboxed apps.

Freedesktop runtime version 25.08 (also GNOME runtime 49, KDE runtime 6.10 and 5.15-25.08) provides libsecret; therefore, it no longer needs to be compiled (flathub/shared-modules/#424) in your app manifest:

runtime: org.freedesktop.Platform
runtime-version: '25.08' # Should be at least 25.08 (or newer)

However, if you are still using an older runtime, you may use Flathub Shared Modules and add shared-modules/libsecret/libsecret.json (no longer recommend and will be removed).

If you using snapcraft to build the project, use the following:

parts:
  your-app:
    plugin: flutter
    flutter-target: lib/main.dart
    build-packages:
      - libsecret-1-dev
    stage-packages:
      - libsecret-1-0

Apart from libsecret, you also need a keyring service. This is typically already installed by the desktop environment:

For more details, including known issues and CI setup, see the flutter_secure_storage_linux README.

Alternative implementations

These are unofficial, non-endorsed plugin implementations of flutter_secure_storage:

  • flutter_secure_storage_linux_secret_service: a pure-Dart Linux implementation that communicates with the standard Secret Service API over D-Bus, without additional system packages (such as libsecret) to build or run the application.
    • When flutter_secure_storage_linux is using the Secret Service API through the org.freedesktop.secrets D-Bus, existing secrets remain interoperable with this implementation. This is not an official interoperability guarantee.
  • flutter_secure_storage_linux_portal: a pure-Dart Linux implementation that uses the Secret Portal API to obtain a master secret and encrypts the secrets in a local file, without additional system packages (such as libsecret) to build or run the application.
    • Secrets stored by this implementation are not interoperable with flutter_secure_storage_linux.

Integration Tests

To run the integration tests, navigate to the example directory and execute the following command:

flutter drive --target=test_driver/app.dart

This will launch the integration tests specified in the test_driver directory.

Contributing

We welcome contributions to this project! To set up your workspace after cloning the repository, follow these steps:

  1. Fetch the Flutter dependencies: flutter pub get

  2. Activate melos: dart pub global activate melos

  3. (Optional) Add pub executables to your path: export PATH="$PATH":"$HOME/.pub-cache/bin"

  4. Bootstrap the workspace with melos: melos bootstrap

This will prepare the project for development by linking and configuring all required dependencies.

API Reference

For a complete list of available methods and configuration options, refer to the API documentation.

License

This project is licensed under the BSD 3 License. See the LICENSE file for details.

Changelog

Changelog

11.2.0 (2026-09-16)

Features

  • android: requireBiometricsPerOperation flag (#1264) (321cf97)

Bug Fixes

  • android: don't hang when biometric negative button is tapped (#1267) (405c6e6)
  • android: fix fresh biometric install crash on non-namespaced stores (120bdf4)
  • android: port the shared-key multi-instance fixes to v11.x (6cc9ddc)
  • android: recover biometric-protected storage on post-auth cipher failure (#1271) (77eed59)
  • android: recover the biometric app key on a namespace switch (31f6eeb)
  • android: scope deleteAll to the key prefix instead of clearing the file (#1266) (34170b2)
  • darwin: find keychain items across accessibility levels (#1269) (9ae0e42)
  • don't report pending namespace recovery as data loss in checkUpgradeStatus (f795d52)

11.1.1 (2026-09-11)

Bug Fixes

  • android: read saved key-cipher marker instead of toString() on a KeyCipher (#1256) (73f0ef5)

11.1.0 (2026-09-10)

Features

  • add checkUpgradeStatus() to report data lost on a direct major upgrade (#1243) (fc716ea)

Bug Fixes

  • android: move wrapped key when switching between sharedPreferencesName and storageNamespace (2482e34)
  • android: use flutter.compileSdkVersion (36) instead of pinning compileSdk (37) (#1236) (0530fe7), closes #1224
  • require flutter_secure_storage_platform_interface ^2.1.0 for checkUpgradeStatus (#1247) (0d3d6f2)

11.0.0 (2026-08-06)

Breaking changes

items deprecated in v10 have been removed. Any data saved using deprecated algorithms or features will be unusable after this upgrade. If you used a version prior to v10, upgrade to v10 first so existing data is migrated.

Android

  • Removed KeyCipherAlgorithm.RSA_ECB_PKCS1Padding. Upgrade to v10 first so existing data is migrated to RSA_ECB_OAEPwithSHA_256andMGF1Padding before upgrading to v11.
  • Removed StorageCipherAlgorithm.AES_CBC_PKCS7Padding. Upgrade to v10 first so existing data is migrated to AES_GCM_NoPadding before upgrading to v11.
  • Removed encryptedSharedPreferences parameter from AndroidOptions and AndroidOptions.biometric. The Jetpack Security (EncryptedSharedPreferences) backend is no longer supported; any remaining data was automatically migrated to custom cipher storage in v10.
  • Removed sharedPreferencesName from AndroidOptions. Use storageNamespace instead for full namespace isolation.
  • Raised minSdk to 24 and compileSdk to 37. Flutter 3.35 raised its own Android minimum to API 24, making API 23 support unverifiable with any supported Flutter version. The legacy AES-CBC cipher path that supported API 21-22 has been removed.

Features

  • android: add requireBiometricConfirmation option to AndroidOptions (7f5f7de)

Bug Fixes

  • android: catch Throwable on worker thread so keystore Errors don't crash the app (d5802ff)
  • android: don't swallow VM errors, catch Throwable on biometric thread too (d413d3f)
  • linux: handle missing default keyring (b39c7c1)
  • linux: fail closed on orphaned keyring data (2e720ff)
  • remove redundant ./ prefix from part directives (cc7018d)

10.3.1

Android

  • Fixed AEADBadTagException when biometric authentication is cancelled on first launch: a stale IV is now cleared and the cipher re-initialised in encrypt mode so the next authentication attempt succeeds.
  • Fixed NullPointerException when retrying an operation after a cancelled biometric prompt: preferences is now only assigned once cipher initialisation completes successfully, allowing a clean retry.

10.3.0

Android

  • Added AndroidBiometricType enum and biometricType option to AndroidOptions to control which authentication methods are accepted during biometric prompts (requires KeyCipherAlgorithm.AES_GCM_NoPadding).
    • AndroidBiometricType.biometricOrDeviceCredential (default) accepts Class 3 biometrics or device credentials (PIN/pattern/password), preserving previous behaviour.
    • AndroidBiometricType.strongBiometricOnly restricts authentication to Class 3 (strong) biometrics only; device credentials are explicitly rejected.
  • Fully enforced on Android 11+ (API 30+) via setAllowedAuthenticators on BiometricPrompt and setUserAuthenticationParameters on the KeyStore key. On earlier API levels the system may still permit device credentials.
  • Added biometricPromptNegativeButton option to AndroidOptions to customise the dismiss button label on the biometric prompt. Required when using strongBiometricOnly or on Android 10 and lower.

iOS / macOS

  • Fixed secStoreAvailabilitySink not being called when protected data availability changes.
  • Fixed kSecUseDataProtectionKeychain being added to Keychain queries unconditionally; it is now only set when useDataProtectionKeychain is explicitly enabled.

Windows

  • Fixed deleteAll and containsKey not acquiring the mutex lock, which could cause data races under concurrent access. If you are on Dart >=3.10.0, this fix is applied automatically. Otherwise, pin flutter_secure_storage_windows: ^4.2.2 in your pubspec.yaml to opt in and make sure your constraint is set for minimum of Dart >=3.10.0.

Linux

  • Fixed deleteKeyring storing the string "null" instead of an empty JSON object {}.
  • Fixed non-UTF-8 error messages from libsecret causing a FormatException on the Dart side; messages are now sanitised before being sent through the method channel.
  • Fixed locked or unavailable keyring now surfacing as a catchable PlatformException with code KeyringLocked.
  • Fixed JSON parse errors and other C++ exceptions now surfacing as a PlatformException with code StorageError instead of sending malformed bytes through the channel.

10.2.0

Android

  • Deprecated KeyCipherAlgorithm.RSA_ECB_PKCS1Padding. Existing data is automatically migrated to the default RSA_ECB_OAEPwithSHA_256andMGF1Padding when migrateOnAlgorithmChange is true.
  • Deprecated StorageCipherAlgorithm.AES_CBC_PKCS7Padding. Existing data is automatically migrated to the default AES_GCM_NoPadding when migrateOnAlgorithmChange is true.
  • Fixed Gradle space-assignment warnings in build.gradle.

iOS / macOS

  • Fixed iOS build by updating availability annotation for Secure Enclave methods from iOS 11.3 to iOS 13.0.

Windows

  • Fixed compatibility with win32 6.0.0 in flutter_secure_storage_windows 4.2.0. If you are on Dart >=3.10.0, this fix is applied automatically. Otherwise, pin flutter_secure_storage_windows: ^4.2.0 in your pubspec.yaml to opt in and make sure your constraint is set for minimum of Dart >=3.10.0.

10.1.0

Windows

  • Updated flutter_secure_storage_windows to 4.2.0 with compatibility fixes for win32 6.0.0.

Android

  • Added storageNamespace option to AndroidOptions for full namespace isolation across storage instances (SharedPreferences, KeyStore aliases, config/key storage). Use this instead of sharedPreferencesName when running multiple FlutterSecureStorage instances with different cipher configurations.
  • Deprecated sharedPreferencesName in favor of storageNamespace, which provides complete isolation rather than data-only isolation.
  • Added migrateWithBackup option to AndroidOptions for crash-resistant migration. When enabled, backup copies of encrypted data are created before migration starts, allowing recovery if migration fails or the app crashes mid-migration. Works in conjunction with migrateOnAlgorithmChange.
  • Made KeyCipherAlgorithm and StorageCipherAlgorithm public enums.

Fixes:

  • Fixed crash on biometric failure (not error).
  • Fixed null safety issue in MethodRunner that could cause a crash on Android.
  • Fixed config being overwritten on initialization.
  • Fixed default Android key cipher not aligning with the Flutter default.

iOS / macOS

  • Added useSecureEnclave option to IOSOptions and MacOsOptions to store keys in the device's Secure Enclave for hardware-backed security.

Fixes:

  • Fixed kSecAttrSynchronizable being silently dropped when no access control flags are set.
  • Fixed readAll not returning Secure Enclave items correctly.

10.0.0

This major release brings significant security improvements, platform updates, and modernization across all supported platforms.

Android

Due to the deprecation of Jetpack Security library, the Android implementation has been largely rewritten with custom secure ciphers, enhanced biometrics support, and migration tools.

Breaking Changes:

  • AndroidOptions().encryptedSharedPreferences is now deprecated due to Jetpack Crypto package deprecation
    • Migration will automatically happen due to migrateOnAlgorithmChange: true, which can also be set to false if not wanted.
  • ResetOnError will now automatically be true, because most errors are unrecoverable due to key storage problems. It can still be disabled with resetOnError: false
  • Default key cipher changed to RSA_ECB_OAEPwithSHA_256andMGF1Padding
  • Default storage cipher changed to AES_GCM_NoPadding
  • Minimum Android SDK changed from 19 to 23
  • Target SDK updated to 36
  • Migrated from deprecated Jetpack Crypto library to custom cipher implementation (Tink doesn't support biometrics)
  • Migrated to Java Version 17

New Features:

  • New named constructors: AndroidOptions(), AndroidOptions.biometric()
  • AndroidOptions().migrateOnAlgorithmChange automatically migrates data to new ciphers when enabled
  • Improved biometric authentication with graceful degradation when device has no security setup
  • Migration tools for transitioning from deprecated encryptedSharedPreferences
  • Enhanced error handling with proper exception messages for biometric unavailability

Fixes:

  • Fixed biometric authentication on devices without security (PIN/pattern/password) - now gracefully degrades when enforceBiometrics=false
  • Fixed storage cipher and key cipher pairing validation
  • Fixed migration checks for encrypted shared preferences
  • Fixed biometric permission handling
  • Fixed exception when reading data after boot

Other Changes:

  • Updated Gradle, Kotlin, and Tink dependencies
  • Refactored custom cipher implementations for better maintainability
  • Added delete key functions for proper reset handling
  • Migrated to new analyzer and code cleanup

iOS / macOS (darwin)

  • Merged iOS and macOS implementations into unified flutter_secure_storage_darwin package
  • Added support for Swift Package Manager
  • Remove keys regardless of synchronizable state or accessibility constraints
  • Change minimum iOS version from 9 to 12
  • Change minimum macOS version to 10.14
  • Use serial queue for execution of keychain operations
  • Added privacy manifest
  • Refactored code and added missing options to IOSOptions and MacOSOptions
  • Fixed warnings with Privacy Manifest
  • Fixed delete and deleteAll when synchronizable is set
  • Fixed migration when value is saved while key already exists with different accessibility option
  • Use accessibility option for all operations
  • Migrated to new analyzer and code cleanup

Web

  • Web is now compatible with WASM
  • Updated code style and migrated to very_good_analysis
  • Add check for secure context (operations only allowed with secure context)
  • Remove dart:io to support WASM build
  • Migrated away from html to web package
  • Removed js in favor of using js-interop
  • Added useSessionStorage parameter to WebOptions for saving in session storage instead of local storage
  • Updated web dependency support to <2.0.0
  • Migrated to new analyzer and code cleanup

Windows

  • Upgrades deprecated member usage of win32
  • Migrated to win32 version 5.5.4 to support Dart 3.4 / Flutter 3.22.0
  • Migrated to new analyzer and code cleanup
  • Write encrypted data to files instead of the Windows credential system

Linux

  • Fixed whitespace deprecation warning
  • Reverted json.dump with indentations due to problems
  • Fixed search with schemas fails in cold keyrings
  • Fixed erase called on null
  • Fixed memory management issue
  • Remove and replace libjsoncpp1 dependency
  • Migrated to new analyzer and code cleanup

Platform Interface

  • Remove dart:io to support WASM build of web
  • Migrated to new analyzer and code cleanup

General Improvements

  • Listener functionality via FlutterSecureStorage().registerListener()
  • All platforms updated to support Dart SDK <4.0.0
  • Comprehensive test coverage improvements
  • Documentation updates across all platforms

10.0.0-beta.5

Due to security issues regarding the handling of biometrics in v10.0.0-beta.4, together with the deprecation of Jetpack Security library, it took me some time to find a secure alternative. My apologies for the delay.

The Android part has been largely rewritten, reintroducing the customer cipher construction from before, but with secure ciphers, biometrics support, updated default ciphers and migration tools.

Breaking Changes:

  • AndroidOptions().encryptedSharedPreferences is now deprecated due to Jetpack Crypto package being deprecated For now you can still use deprecated encryptedSharedPreferences by setting encryptedSharedPreferences: true and migrateOnAlgorithmChange: false. If encryptedSharedPreferences is true and migrateOnAlgorithmChange is true, data will be automatically migrated to the new cipher, and encryptedSharedPreferences cannot be used anymore.
  • Google recommends using Tink library, but Tink does not support biometrics, so custom ciphers have been reintroduced
  • Default key cipher changed to RSA_ECB_OAEPwithSHA_256andMGF1Padding
  • Default storage cipher changed to AES_GCM_NoPadding

New Features:

  • New named constructors: AndroidOptions(), AndroidOptions.biometric()
  • AndroidOptions().migrateOnAlgorithmChange automatically migrates data to new ciphers when enabled
  • Improved biometric authentication with graceful degradation when device has no security setup
  • Migration tools for transitioning from deprecated encryptedSharedPreferences
  • Enhanced error handling with proper exception messages for biometric unavailability

Key Fixes:

  • Fixed biometric authentication on devices without security (PIN/pattern/password) - now gracefully degrades when enforceBiometrics=false
  • Fixed storage cipher and key cipher pairing validation
  • Fixed migration checks for encrypted shared preferences
  • Fixed biometric permission handling
  • Fixed default resetOnError behavior (now defaults to true)

Other Changes:

  • Target SDK 36
  • Updated Gradle, Kotlin, and Tink dependencies
  • Updated minimum SDK according to Flutter requirements
  • Refactored custom cipher implementations for better maintainability
  • Added delete key functions for proper reset handling

10.0.0-beta.4

  • [Apple] Merged ios and macos implementation into a new package flutter_secure_storage_darwin
  • [Apple] Refactored code and added missing options
  • [Apple] Added support for swift package manager
  • [Web] Update flutter_secure_storage_platform_interface to be compatible with WASM.

10.0.0-beta.3

  • [iOS] Fix delete and deleteAll when synchronizable is set.
  • [iOS] Update migration when value is saved while key already exists with different accessibility option.
  • [Android] Fix deprecation warning.

10.0.0-beta.2

  • [Web] Update flutter_secure_storage_platform_interface to be compatible with WASM.

10.0.0-beta.1

This new major release has some big changes. This plugin requires a minimum dart sdk of 3.3.0 or higher and a minimum flutter version of 3.19.0.

[Android]

  • By default, encryptedSharedPreferences will be enabled, and cannot be disabled. If there is still data saved by previous versions using encryptedSharedPreferences = false, it will be automatically transferred to encryptedSharedPreferences.
  • Migrated from deprecated Jetpack Crypto library to Google Tink Crypto library.
  • Migrated to Android SDK 35
  • Migrated to Java Version 17
  • Minimum Android SDK is changed from 19 to 23.
  • Migrated to new analyzer and clean-up code.
  • Lots of minor code improvements

[iOS]

  • Change minimum iOS version from 9 to 12
  • Use serial queue for execution of iOS keychain operations
  • Migrated to new analyzer and clean-up code.

[Web]

  • Web is now migrated to be compatible with WASM.
  • The parameter useSessionStorage is added to WebOptions, which you can use to save in session storage instead of local storage.
  • Migrated to new analyzer and clean-up code.

[Windows]

  • Migrates to win32 version 5.5.4 to support Dart 3.4 / Flutter 3.22.0.
  • Migrated to new analyzer and clean-up code.

[Platform Interface]

  • Migrated to new analyzer and clean-up code.

9.2.4

  • [Android] Fix errors when building for release by upgrading Tink to 1.9.0.
  • [iOS] Fix delete and deleteAll when synchronizable is set.
  • [iOS] Update migration when value is saved while key already exists with different accessibility option.

9.2.3

  • [iOS] Fix for issue #711: The specified item already exists in the keychain.
  • [Linux] Fix json.dump with indentations.
  • [Web] Update web dependency support to support <2.0.0 instead of <1.0.0.
  • [Web] Add wrapKey and wrapKeyIv parameters to webOptions. See readme for more information.
  • [macOS] Added useDataProtectionKeyChain parameter.

9.2.2

[iOS, macOS] Fixed an issue which caused the readAll and deleteAll to not work properly.

9.2.1

  • Fix async race condition bug in storage operations.
  • [macOS] Return nil on macOS if key is not found

9.2.0

New Features:

  • [iOS, macOS] Reintroduced isProtectedDataAvailable.
  • Listener functionality via FlutterSecureStorage().registerListener()

Bugs Fixed:

  • [iOS] Return nil on iOS read if key is not found
  • [macOS] Also set kSecUseDataProtectionKeychain on read for macos.

9.1.1

Reverts new feature because of breaking changes.

  • [iOS, macOS] Added isProtectedDataAvailable, A boolean value that indicates whether content protection is active.

9.1.0

New Features:

  • [iOS, macOS] Added isProtectedDataAvailable, A boolean value that indicates whether content protection is active.

Improvements:

  • [iOS, macOS] Use accessibility option for all operations
  • [iOS, macOS] Added privacy manifest
  • [iOS] Fixes error when no item exists
  • [Linux] Fixed search with schemas fails in cold keyrings
  • [Linux] Fixed erase called on null
  • [Android] Fixed native Android stacktraces in PlatformExceptions
  • [Android] Fixed exception when reading data after boot

9.0.0

Breaking changes:

  • [Windows] Migrated to FFI with win32 package.

8.1.0

  • [Android] Upgraded to Gradle 8.
  • [Android] Fixed resetOnError not working.
  • [Windows] Changed PathNotFoundException to FileSystemException to be backwards compatible with Flutter SDK 2.12.0.
  • [Windows] Applied lint suggestions.
  • [Linux] Remove and replace libjsoncpp1 dependency.
  • [Linux, macOS, Windows, Web] Update Dart SDK Constraint to support <4.0.0 instead of <3.0.0.

8.0.0

Breaking changes:

  • [macOS] The minimum macOS version supported is now 10.14.

Other changes:

  • [Android] Fixed an issue when Encrypted Shared Preferences failed, the fallback would not handle the data correctly.
  • [Windows] Write encrypted data to files instead of the windows credential system.
  • [Linux] Fixed an issue with memory management.

7.0.2

[macOS] Fix issue with plugin name.

7.0.1

[Android] Reverted double initialization of the SharedPreferences because this will break mixed usage of secureSharedPreference on Android.

7.0.0

Breaking changes:

  • [macOS] The minimum macOS version supported is now 10.13.

Other changes:

  • [Android] Fixed double initialization of the SharedPreferences which caused containsKey and other functions to not work properly.
  • [macOS] Upgraded codebase to swift which fixed containsKey always returning true.

6.1.0

  • [iOS] (From 6.1.0-beta.1) Migrated from objective C to Swift. This also fixes issues with containsKey and possibly other issues.
  • [Android] Upgrade security-crypto from 1.1.0-alpha03 to 1.1.0-alpha04
  • [Android] Fix deprecation warnings.
  • [All] Migrated from flutter_lints to lint and applied suggestions.

6.1.0-beta.1

  • [iOS] Migrated from objective C to Swift. This also fixes issues with containsKey and possibly other issues.

6.0.0

  • [Android] Upgrade to Android SDK 33.

5.1.2

This version reverts some breaking changes of update 5.1.0. These changes will become available in version 6.0.0

  • [Android] Revert upgrade to Android SDK 33.

5.1.1

  • Example app dependencies updated
  • Updated homepage

5.1.0

  • [Android] You can now select your own key prefix or database name.
  • [Android] Upgraded to Android SDK 33.
  • [Android] You can now select the keyCipherAlgorithm and storageCipherAlgorithm.
  • [Linux] Fixed an issue where no error was being reported if there was something wrong accessing the secret service.
  • [macOS] Fixed an memory-leak.
  • [macOS] You can now select the same options as for iOS.

5.0.2

  • [Android] Fixed bug where sharedPreference object was not yet initialized.

5.0.1

  • [Android] Added java 8 requirement for gradle build.

5.0.0

First stable release of flutter_secure_storage for multi-platform! Please see all beta release notes for changes.

This first release also fixes several stability issues on Android regarding encrypted shared preferences.

[5.0.0-beta.5]

  • [Linux, iOS & macOS] Add containsKey function.
  • [Linux] Fix for use of undeclared identifier 'flutter_secure_storage_linux_plugin_register_with_registrar'

[5.0.0-beta.4]

  • [Windows] Fixed application crashing when key doesn't exists.
  • [Web] Added prefix to local storage key when deleting, fixing items that wouldn't delete.

[5.0.0-beta.3]

  • [Android] Add possibility to reset data when an error occurs.
  • [Windows] Add readAll, deleteAll and containsKey functions.
  • [All] Refactor option defaults.

[5.0.0-beta.2]

  • [Android] Improved EncryptedSharedPreferences by not loading unused Cipher.
  • [Android] Removed deprecated classes
  • [Web] Improved containsKey function

[5.0.0-beta.1]

Initial BETA support for macOS, web & Windows. Development is still ongoing so expect some functions to not work correctly! Please read the readme.md for information about every platform.

  • Migrated to a federated project structure. #254. Thanks jhancock4d
  • Added support for encrypted shared preferences on Android. #259

[4.2.1]

  • Added kSecAttrSynchronizable support by setting IOSOptions.synchronizable #51
  • Changed deprecated jcenter to mavenCentral #246

[4.2.0]

[4.1.0]

  • Add support for Linux 185. Thanks talhabalaj
  • Improve first-time read speed on Android by not creating cipher when key is not present. Thanks PieterAelse
  • Make it possible to customize iOS account name(kSecAttrService). Thanks klyver

[4.0.0]

[3.3.5]

  • Fix thread safety issues in android code to close 161. Thanks koskimas

[3.3.4]

  • Fix Android hanging UI on StorageCipher initialization #116 by morrica
  • Fix crash only observed for v2 apps #124 by lidongze91
  • Fix crash when generating keys in android with RTL locales #132 by iassal
  • Fix returning the error as String rather than Exception #134 by wytesk133s
  • Fix Android crash onDetachedFromEngine when init fails #144 by iassal
  • Handle null value at write function #95 by ewertonrp
  • Add support for containsKey #139 by iassal

[3.3.3]

[3.3.2]

[3.3.1+2]

[3.3.1+1]

[3.3.1]

[3.3.0]

  • Added groupId for iOS keychain sharing. Thanks Maleandr.
  • Fix Gradle version in gradle-wrapper.properties. Thanks blasten.
  • Added minimum sdk requirement on AndroidManifest. Thanks lidongze91.

[3.2.1]

[3.2.0]

  • Breaking change. Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to also migrate if they're using the original support library. Thanks I-am-original.
  • Enable StrongBox on Android devices that support it. Thanks bbedward.

[3.1.3]

  • Fix Android 9.0 Pie KeyStore exception. Thanks hacker1024

[3.1.2]

  • Added recreating secretKey if its decoding failed. Fix for unwrap key. Thanks hnvn.

[3.1.1]

  • Suppress warning about unchecked operations when compiling for Android.

[3.1.0]

  • Added readAll and deleteAll.

[3.0.0]

  • Breaking change. Changed payloads encryption for Android from RSA to AES, AES secret key is encrypted with RSA.

[2.0.0]````

  • Breaking change. Changed key alias to fix Android 4.4.2 issue. The plugin isn't able to get previous stored data.

[1.0.0]

  • Bump version

[0.0.1]

  • Initial release

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add 'flutter_secure_storage:11.2.0'
pubspec.yaml
name: flutter_secure_storage
description: A Flutter plugin for securely storing sensitive data using encrypted storage.
version: 11.2.0
repository: https://github.com/mogol/flutter_secure_storage/tree/develop/flutter_secure_storage
resolution: workspace

environment:
  sdk: '>=3.8.0 <4.0.0'
  flutter: '>=3.19.0'

flutter:
  plugin:
    platforms:
      android:
        package: com.it_nomads.fluttersecurestorage
        pluginClass: FlutterSecureStoragePlugin
      ios:
        default_package: flutter_secure_storage_darwin
      macos:
        default_package: flutter_secure_storage_darwin
      linux:
        default_package: flutter_secure_storage_linux
      web:
        default_package: flutter_secure_storage_web
      windows:
        default_package: flutter_secure_storage_windows

dependencies:
  flutter:
    sdk: flutter
  # The design on https://flutter.dev/go/federated-plugins was to leave
  # implementation constraints as "any". We cannot do it right now as it fails pub publish
  # validation, so we set a ^ constraint.
  # https://github.com/flutter/flutter/issues/46264
  flutter_secure_storage_darwin: ^0.4.0
  flutter_secure_storage_linux: '>=3.0.1 <5.0.0'
  flutter_secure_storage_platform_interface: ^2.1.0
  flutter_secure_storage_web: ^2.1.1
  flutter_secure_storage_windows: ^4.2.2
  meta: ^1.16.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  mocktail: ^1.0.5
  plugin_platform_interface: ^2.1.8
  very_good_analysis: ^10.0.0

# We need to manually declare supported platforms, because pub.dev won't find them.
platforms:
  android:
  ios:
  linux:
  macos:
  web:
  windows:

Version history

VersionPublishedArchiveSHA-256
0.0.1On demandDownload95e215d9…c81650
1.0.0On demandDownloadff5e8bb7…962a15
2.0.0On demandDownload81dc18ce…c9ab99
3.0.0On demandDownload51f495a8…78b59c
3.1.0On demandDownload3e798440…858158
3.1.1On demandDownload2519977e…8c8827
3.1.2On demandDownloadeb4f04b0…316474
3.1.3On demandDownloadda395ea8…97f332
3.2.0On demandDownload82eeda0e…bc2eca
3.2.1On demandDownload1fdef76a…80a7c9
3.2.1+1On demandDownloadc2a1c2a3…8e4184
3.3.0On demandDownload8fe67a66…f8f5a4
3.3.1On demandDownload6e11423c…b99f14
3.3.1+1On demandDownload8e7a4867…15daa5
3.3.2On demandDownloadb46f6e7e…a83575
3.3.3On demandDownload6384e1cd…0668d7
3.3.4On demandDownload098e6740…afdb70
3.3.5On demandDownload5b4948fe…093360
4.0.0On demandDownload67698c59…283cf3
4.1.0On demandDownload75ba08d1…a3cfd8
4.2.0On demandDownloadf60815eb…42a41c
4.2.1On demandDownload9f3dd2ac…056df6
5.0.0-beta.1On demandDownload87c96ce9…efcd8d
5.0.0-beta.2On demandDownloadd3f289e3…a3edec
5.0.0-beta.3On demandDownloade163f5a5…c3bb08
5.0.0-beta.4On demandDownload017ce329…437e2b
5.0.0-beta.5On demandDownloadf8285e6d…34e6ff
5.0.0On demandDownload9173dd3d…54c3d4
5.0.1On demandDownloadb2c17355…b68a1a
5.0.2On demandDownload1b7c2f80…7d3d7f
5.1.0On demandDownloadbe8fc5db…278933
5.1.1On demandDownload97a777e0…8baea5
5.1.2On demandDownload5abe3d5c…30014a
6.0.0On demandDownloada12d0213…46949b
6.1.0-beta.1On demandDownload223e63f1…1d66ea
6.1.0On demandDownloadde957362…1abe8e
7.0.0On demandDownloadf5969df7…331f19
7.0.1On demandDownloadf2afec1f…550bc5
8.0.0On demandDownload98352186…f0a7c5
8.1.0On demandDownload22dbf16f…5fff8f
9.0.0On demandDownloadffdbb601…76d685
9.1.0On demandDownloadd422162d…10cecc
9.1.1On demandDownloadc0f40206…2360a4
9.2.0On demandDownloada45be8a2…3daa1f
9.2.1On demandDownload8496a89e…155864
9.2.2On demandDownload16516474…1e85d0
9.2.3On demandDownload1913841a…81b3e4
9.2.4On demandDownload9cad52d7…1d16ea
10.0.0-beta.1On demandDownloadadde7a2a…a8ccd7
10.0.0-beta.2On demandDownloadc0f1abb0…ffc22b
10.0.0-beta.3On demandDownload127f5ab0…6d8e4e
10.0.0-beta.4On demandDownloadf7eceb0b…954874
10.0.0-beta.5On demandDownload79d53f33…682ce0
10.0.0On demandDownloadda922f2a…9b2e40
10.1.0On demandDownload8b302d17…776d87
10.2.0On demandDownload6848263f…29de62
10.3.0On demandDownloadd2a6ac2d…47b261
10.3.1Cached · Upstream SHA-256 matchedDownload7686b1d6…7c868e
10.3.2On demandDownload2670c2a8…81822c
10.3.3On demandDownload6a79c298…435f50
10.3.4On demandDownloadfe638107…d2ca4b
11.0.0-beta.1On demandDownload380a129f…b87ac0
11.0.0On demandDownload15e8c8fe…ebace6
11.1.0On demandDownload4540927d…602c67
11.1.1On demandDownloadd87713a1…afddd2
11.2.0Cached · Upstream SHA-256 matchedDownloadd4e1fb6b…c95bb8

Dependencies

flutter { "sdk": "flutter" }

flutter_secure_storage_darwin "^0.4.0"

flutter_secure_storage_linux "\u003e=3.0.1 \u003c5.0.0"

flutter_secure_storage_platform_interface "^2.1.0"

flutter_secure_storage_web "^2.1.1"

flutter_secure_storage_windows "^4.2.2"

meta "^1.16.0"