Skip to content

Commit b77fd10

Browse files
release of v10.0.0
1 parent 9a1768d commit b77fd10

File tree

4 files changed

+187
-30
lines changed

4 files changed

+187
-30
lines changed

.github/workflows/stale-issues.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ on:
66
days-before-issue-stale:
77
description: "Days before marking an issue as stale"
88
required: false
9-
default: "60"
9+
default: "120"
1010
days-before-issue-close:
1111
description: "Days before closing a stale issue"
1212
required: false
13-
default: "60"
13+
default: "120"
1414
schedule:
1515
- cron: "30 1 * * *" # Runs daily at 1:30 AM UTC
1616

README.md

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,21 @@ A Flutter plugin to securely store sensitive data in a key-value pair format usi
1111

1212
## Features
1313

14-
- **Secure Data Storage**: Uses Keychain for iOS, Encrypted Shared Preferences via Tink for Android, and secure mechanisms on other supported platforms.
15-
- **Encryption**: Encrypts data before storing it in the underlying storage system.
16-
- **Cross-Platform**: Works seamlessly across multiple platforms.
17-
- **Customizable Options**: Set accessibility attributes, key expiration, and more.
14+
- **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.
15+
- **Encryption**: Encrypts data before storing it using platform-specific encryption (RSA OAEP + AES-GCM on Android by default).
16+
- **Cross-Platform**: Works seamlessly across Android, iOS, macOS, Windows, Linux, and Web.
17+
- **Biometric Authentication**: Optional biometric authentication support on Android (API 23+) and iOS/macOS.
18+
- **Customizable Options**: Configure encryption algorithms, accessibility attributes, biometric requirements, and more.
1819

1920
## Important notice for Android
20-
Beginning with version 10, all data will be transitioned to encryptedSharedPreferences. As a result, the useEncryptedSharedPreferences option will be deprecated.
21+
Version 10.0.0 introduces a major security update with custom cipher implementations. The deprecated Jetpack Security library's `encryptedSharedPreferences` is no longer recommended.
2122

22-
In version 11, the migration tool will no longer be available. To ensure users retain their data, it is essential to first upgrade to version 10 before proceeding to version 11.
23-
24-
Due to this update, the minimum required Android SDK will be 23.
23+
**Key Changes:**
24+
- New default ciphers: RSA OAEP (key cipher) + AES-GCM (storage cipher)
25+
- New `AndroidOptions()` and `AndroidOptions.biometric()` constructors
26+
- Automatic migration from old ciphers via `migrateOnAlgorithmChange` (enabled by default)
27+
- Minimum Android SDK is now 23 (Android 6.0+)
28+
- Enhanced biometric authentication with graceful degradation
2529

2630
## Important notice for Web
2731
flutter_secure_storage only works on HTTPS or localhost environments. [Please see this issue for more information.](https://github.com/juliansteenbakker/flutter_secure_storage/issues/320#issuecomment-976308930)
@@ -50,7 +54,31 @@ Then run:
5054

5155
### Create an Instance
5256

53-
`final storage = FlutterSecureStorage();`
57+
```dart
58+
// Default secure storage - Uses RSA OAEP + AES-GCM (recommended)
59+
final storage = FlutterSecureStorage();
60+
61+
// Or with explicit Android options
62+
final storage = FlutterSecureStorage(
63+
aOptions: AndroidOptions(),
64+
);
65+
66+
// Biometric storage with graceful degradation
67+
final storage = FlutterSecureStorage(
68+
aOptions: AndroidOptions.biometric(
69+
enforceBiometrics: false, // Works without biometrics
70+
biometricPromptTitle: 'Authenticate to access data',
71+
),
72+
);
73+
74+
// Strict biometric enforcement (requires device security)
75+
final storage = FlutterSecureStorage(
76+
aOptions: AndroidOptions.biometric(
77+
enforceBiometrics: true, // Requires biometric/PIN/pattern
78+
biometricPromptTitle: 'Authentication Required',
79+
),
80+
);
81+
```
5482

5583
### Write Data
5684

@@ -95,21 +123,51 @@ By setting `accessibility`, you can control when secure values are accessible, e
95123

96124
#### Disabling Auto Backup
97125

98-
_Note_ By default Android backups data on Google Drive. It can cause exception java.security.InvalidKeyException:Failed to unwrap key.
99-
You need to
126+
_Note_ By default Android backups data on Google Drive. It can cause exception `java.security.InvalidKeyException: Failed to unwrap key`.
127+
You need to:
100128

101-
- [disable autobackup](https://developer.android.com/guide/topics/data/autobackup#EnablingAutoBackup), [details](https://github.com/juliansteenbakker/flutter_secure_storage/issues/13#issuecomment-421083742)
102-
- [exclude sharedprefs](https://developer.android.com/guide/topics/data/autobackup#IncludingFiles) `FlutterSecureStorage` used by the plugin, [details](https://github.com/juliansteenbakker/flutter_secure_storage/issues/43#issuecomment-471642126)
129+
- [Disable autobackup](https://developer.android.com/guide/topics/data/autobackup#EnablingAutoBackup), [details](https://github.com/juliansteenbakker/flutter_secure_storage/issues/13#issuecomment-421083742)
130+
- [Exclude sharedprefs](https://developer.android.com/guide/topics/data/autobackup#IncludingFiles) used by `FlutterSecureStorage`, [details](https://github.com/juliansteenbakker/flutter_secure_storage/issues/43#issuecomment-471642126)
103131

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

106134
```xml
107135
<application
108-
android:allowBackup="false"
109-
...>
136+
android:allowBackup="false"
137+
...>
110138
</application>
111139
```
112140

141+
#### Encryption Options (Version 10.0.0+)
142+
143+
Version 10 introduces new cipher options and biometric support. Choose the configuration that fits your security requirements:
144+
145+
| Constructor | Key Cipher | Storage Cipher | Biometric Support | Description |
146+
|------------------------------------------------------|---------------------------------------|-------------------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
147+
| `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. |
148+
| `AndroidOptions.biometric(enforceBiometrics: false)` | AES/GCM/NoPadding | AES/GCM/NoPadding | Optional | KeyStore-based with optional biometric authentication. Gracefully degrades if biometrics unavailable. |
149+
| `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. |
150+
151+
#### Custom Cipher Combinations (Advanced)
152+
153+
For advanced users, all combinations below are supported using the `AndroidOptions()` constructor with custom parameters:
154+
155+
| Key Cipher Algorithm | Storage Cipher Algorithm | Implementation | Biometric Support |
156+
|-----------------------------------------|--------------------------|-----------------|------------------------------------|
157+
| `RSA_ECB_PKCS1Padding` | `AES_CBC_PKCS7Padding` | RSA-wrapped AES | No |
158+
| `RSA_ECB_PKCS1Padding` | `AES_GCM_NoPadding` | RSA-wrapped AES | No |
159+
| `RSA_ECB_OAEPwithSHA_256andMGF1Padding` | `AES_CBC_PKCS7Padding` | RSA-wrapped AES | No |
160+
| `RSA_ECB_OAEPwithSHA_256andMGF1Padding` | `AES_GCM_NoPadding` | RSA-wrapped AES | No |
161+
| `AES_GCM_NoPadding` | `AES_CBC_PKCS7Padding` | KeyStore AES | Optional (via `enforceBiometrics`) |
162+
| `AES_GCM_NoPadding` | `AES_GCM_NoPadding` | KeyStore AES | Optional (via `enforceBiometrics`) |
163+
164+
**Notes:**
165+
- **RSA key ciphers** wrap the AES encryption key with RSA. No biometric support.
166+
- **AES key cipher** stores the key directly in Android KeyStore. Supports optional biometric authentication.
167+
- **`enforceBiometrics` parameter** (default: `false`):
168+
- `false`: Gracefully degrades if biometrics unavailable
169+
- `true`: Strictly requires device security (PIN/pattern/biometric), throws exception if unavailable
170+
113171
#### Biometric Authentication
114172

115173
Flutter Secure Storage supports biometric authentication (fingerprint, face recognition, etc.) on Android API 23+.
@@ -135,22 +193,19 @@ For backward compatibility with devices running Android 6.0 - 8.1 (API 23-27), y
135193
You can enable biometric authentication using the `AndroidOptions.biometric()` constructor:
136194

137195
```dart
196+
// Optional biometric authentication (graceful degradation)
138197
final storage = FlutterSecureStorage(
139198
aOptions: AndroidOptions.biometric(
199+
enforceBiometrics: false, // Default - works without biometrics
140200
biometricPromptTitle: 'Unlock to access your data',
141201
biometricPromptSubtitle: 'Use fingerprint or face unlock',
142202
),
143203
);
144-
```
145-
146-
##### Enforcing Biometric Authentication
147204
148-
By default, biometric authentication is optional and will gracefully degrade if the device doesn't have biometrics enrolled. To enforce biometric authentication and throw an error if unavailable:
149-
150-
```dart
205+
// Strict biometric enforcement (requires device security)
151206
final storage = FlutterSecureStorage(
152207
aOptions: AndroidOptions.biometric(
153-
enforceBiometrics: true, // Throw error if biometrics unavailable
208+
enforceBiometrics: true, // Requires biometric/PIN/pattern
154209
biometricPromptTitle: 'Biometric authentication required',
155210
),
156211
);
@@ -161,10 +216,24 @@ final storage = FlutterSecureStorage(
161216
##### Requirements
162217

163218
- **API Level**: Android 6.0 (API 23) minimum for basic encryption
164-
- **API Level**: Android 9.0 (API 28) minimum for biometric authentication
219+
- **API Level**: Android 9.0 (API 28) minimum for enforced biometric authentication
165220
- **Device Security**: Device must have a PIN, pattern, password, or biometric enrolled (when using `enforceBiometrics: true`)
166221
- **Permissions**: `USE_BIOMETRIC` permission in AndroidManifest.xml
167222

223+
#### Migration from Version 9.x
224+
225+
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.
226+
227+
To disable automatic migration:
228+
229+
```dart
230+
final storage = FlutterSecureStorage(
231+
aOptions: AndroidOptions(
232+
migrateOnAlgorithmChange: false,
233+
),
234+
);
235+
```
236+
168237
### macOS & iOS
169238

170239
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`.

flutter_secure_storage/CHANGELOG.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,91 @@
1+
## 10.0.0
2+
This major release brings significant security improvements, platform updates, and modernization across all supported platforms.
3+
4+
### Android
5+
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.
6+
7+
**Breaking Changes:**
8+
- `AndroidOptions().encryptedSharedPreferences` is now deprecated due to Jetpack Crypto package deprecation
9+
- Migration will automatically happen due to `migrateOnAlgorithmChange: true`, which can also be set to false if not wanted.
10+
- ResetOnError will now automatically be true, because most errors are unrecoverable due to key storage problems. It can still be disabled with `resetOnError: false`
11+
- Default key cipher changed to `RSA_ECB_OAEPwithSHA_256andMGF1Padding`
12+
- Default storage cipher changed to `AES_GCM_NoPadding`
13+
- Minimum Android SDK changed from 19 to 23
14+
- Target SDK updated to 36
15+
- Migrated from deprecated Jetpack Crypto library to custom cipher implementation (Tink doesn't support biometrics)
16+
- Migrated to Java Version 17
17+
18+
**New Features:**
19+
- New named constructors: `AndroidOptions()`, `AndroidOptions.biometric()`
20+
- `AndroidOptions().migrateOnAlgorithmChange` automatically migrates data to new ciphers when enabled
21+
- Improved biometric authentication with graceful degradation when device has no security setup
22+
- Migration tools for transitioning from deprecated encryptedSharedPreferences
23+
- Enhanced error handling with proper exception messages for biometric unavailability
24+
25+
**Fixes:**
26+
- Fixed biometric authentication on devices without security (PIN/pattern/password) - now gracefully degrades when `enforceBiometrics=false`
27+
- Fixed storage cipher and key cipher pairing validation
28+
- Fixed migration checks for encrypted shared preferences
29+
- Fixed biometric permission handling
30+
- Fixed exception when reading data after boot
31+
32+
**Other Changes:**
33+
- Updated Gradle, Kotlin, and Tink dependencies
34+
- Refactored custom cipher implementations for better maintainability
35+
- Added delete key functions for proper reset handling
36+
- Migrated to new analyzer and code cleanup
37+
38+
### iOS / macOS (darwin)
39+
- Merged iOS and macOS implementations into unified `flutter_secure_storage_darwin` package
40+
- Added support for Swift Package Manager
41+
- Remove keys regardless of synchronizable state or accessibility constraints
42+
- Change minimum iOS version from 9 to 12
43+
- Change minimum macOS version to 10.14
44+
- Use serial queue for execution of keychain operations
45+
- Added privacy manifest
46+
- Refactored code and added missing options to IOSOptions and MacOSOptions
47+
- Fixed warnings with Privacy Manifest
48+
- Fixed delete and deleteAll when synchronizable is set
49+
- Fixed migration when value is saved while key already exists with different accessibility option
50+
- Use accessibility option for all operations
51+
- Migrated to new analyzer and code cleanup
52+
53+
### Web
54+
- Web is now compatible with WASM
55+
- Updated code style and migrated to very_good_analysis
56+
- Add check for secure context (operations only allowed with secure context)
57+
- Remove dart:io to support WASM build
58+
- Migrated away from `html` to `web` package
59+
- Removed `js` in favor of using js-interop
60+
- Added `useSessionStorage` parameter to WebOptions for saving in session storage instead of local storage
61+
- Updated web dependency support to <2.0.0
62+
- Migrated to new analyzer and code cleanup
63+
64+
### Windows
65+
- Upgrades deprecated member usage of win32
66+
- Migrated to `win32` version 5.5.4 to support Dart 3.4 / Flutter 3.22.0
67+
- Migrated to new analyzer and code cleanup
68+
- Write encrypted data to files instead of the Windows credential system
69+
70+
### Linux
71+
- Fixed whitespace deprecation warning
72+
- Reverted json.dump with indentations due to problems
73+
- Fixed search with schemas fails in cold keyrings
74+
- Fixed erase called on null
75+
- Fixed memory management issue
76+
- Remove and replace libjsoncpp1 dependency
77+
- Migrated to new analyzer and code cleanup
78+
79+
### Platform Interface
80+
- Remove dart:io to support WASM build of web
81+
- Migrated to new analyzer and code cleanup
82+
83+
### General Improvements
84+
- Listener functionality via `FlutterSecureStorage().registerListener()`
85+
- All platforms updated to support Dart SDK <4.0.0
86+
- Comprehensive test coverage improvements
87+
- Documentation updates across all platforms
88+
189
## 10.0.0-beta.5
290
Due to security issues regarding the handling of biometrics in v10.0.0-beta.4, together with the deprecation
391
of Jetpack Security library, it took me some time to find a secure alternative. My apologies for the delay.

flutter_secure_storage/pubspec.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: flutter_secure_storage
22
description: A Flutter plugin for securely storing sensitive data using encrypted storage.
3-
version: 10.0.0-beta.5
3+
version: 10.0.0
44
repository: https://github.com/mogol/flutter_secure_storage/tree/develop/flutter_secure_storage
55

66
environment:
@@ -31,11 +31,11 @@ dependencies:
3131
# implementation constraints as "any". We cannot do it right now as it fails pub publish
3232
# validation, so we set a ^ constraint.
3333
# https://github.com/flutter/flutter/issues/46264
34-
flutter_secure_storage_darwin: ^0.1.0
35-
flutter_secure_storage_linux: ^2.0.0
34+
flutter_secure_storage_darwin: ^0.2.0
35+
flutter_secure_storage_linux: ^3.0.0
3636
flutter_secure_storage_platform_interface: ^2.0.1
37-
flutter_secure_storage_web: ^2.0.0
38-
flutter_secure_storage_windows: ^4.0.0
37+
flutter_secure_storage_web: ^2.1.0
38+
flutter_secure_storage_windows: ^4.1.0
3939
meta: ^1.3.0
4040

4141
dev_dependencies:

0 commit comments

Comments
 (0)