How to cache data securely in Flutter using cache_x package

cache_x | Flutter Package (pub.dev)

Caching is just a simple key-value pair data saving procedure. Usually for caching data locally in flutter we use shared_preferences package in flutter. Shared Preferences package under the hood uses localStorage on web, SharedPreferences on Android and NSUserDefaults on iOS.

But the problem is shared_preferences package stores plain text which is not secure at all. Especially if you are storing sensitive information in localStorage it can be read by client and its a problem if vulnerable to XSS. SharedPreferences and NSUserDefaults are also can be compromised on the client side since they are not secure storage and not encrypted.

cache_x package is a wrapper around shared_preferencescache_x uses SharedPreference as storage for caching data. Since we really can’t just save the original data because of security issues. cache_x uses AES encryption & decryption behind the scene when you are caching data or fetching data from the cache.

After using cache_x this is how the data will appear in the localStorage.

Screenshot from Example project of cache_x package
Image from Example project of cache_x | Tanvir Ahmed Khan

So now lets see how can we use cache_x package to securely store data locally.

First we have to add the cache_x package dependency in pubspec.yml

cache_x: ^latest

Get the version from the pub.dev.

Then in the Main Function of our App we have to initialize the CacheXCore with a strong password. Keep in mind the Password length must be 128/192/256 bits which means 16, 24 or 32 character.

void main() async {
WidgetsFlutterBinding.ensureInitialized();
String password = 'CBoaDQIQAgceGg8dFAkMDBEOECEZCxg=';
await CacheXCore().init(password: password);
}

As the CacheXCore is initialized properly now we can use the CacheXCore to save and retrieve any data.

CacheXCore instance is Singleton so once its initialized you can use it anywhere in the app you want.

CacheXCore.instance

There are 5 methods to save 5 type of data which are:

  • saveBool(String key, bool value)
  • saveDouble(String key, double value)
  • saveInt(String key, int value)
  • saveString(String key, String value)
  • saveStringList(String key, List<String> value)

And to retrieve the data there are methods which are:

  • getBool(String key)
  • getDouble(String key)
  • getInt(String key)
  • getString(String key)
  • getStringList(String key)
  • getKeys()

So if we want to save any String Data we can call the saveString() function like this:

await CacheXCore.instance.saveString(key: 'ft1', value: 'Tanvir');

and to retrieve the String data we can call the getString() function like this:

CacheXCore.instance.getString(key: 'ft1');

Here is the full example project that shows all the methods in action:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize password
  // Password length must be 128/192/256 bits
  // You can use the password of 16 character,24 character or 32 character.
  String password = 'CBoaDQIQAgceGg8dFAkMDBEOECEZCxg=';

  // Initialize CacheX with the password
  final cacheX = CacheXCore();
  await cacheX.init(password: password);

  // Saving values
  await cacheX.saveBool(key: '1', value: true);
  await cacheX.saveDouble(key: '2', value: 10.5);
  await cacheX.saveInt(key: '3', value: 30);
  await cacheX.saveString(key: '4', value: 'String');
  await cacheX.saveStringList(
    key: '5',
    value: [
      'String1',
      'String2',
      'String3',
    ],
  );

  // Getting values
  print(cacheX.getBool(
      key: '1',
      defaultValue: false,
    ));
  print(cacheX.getDouble(key: '2'));
  print(cacheX.getInt(key: '3'));
  print(cacheX.getString(key: '4'));
  print(cacheX.getStringList(key: '5'));
  print(cacheX.getKeys());
}

Important things to keep in mind

  • The password must be 128/192/256 bits. It means the password only can be 16 character,24 character or 32 character in length. Otherwise it will throw exception.
  • Provide defaultValue in the get methods or else the default value will be null. If the key is not found or the data is not the right type it return the defaultValue.
  • If you forget or lost the specified password all the data encrypted with the password will be unusable.
  • All the save methods will return Future<> so to get the value you have to use await
  • It will throw exception if there any.

Exceptions in the Package

  • CacheXException: If there any exception in the CacheXCore or the CacheXCore is not initialized properly it will throw CacheXException exception. The exception message starts with CacheXException:.
  • StorageException: If there any exception saving or getting data it will throw StorageException. The exception message starts with String StorageException:.
  • EncryptionException: If there any exception encrypting or decrypting the data it will throw EncryptionException. The exception message will start with String EncryptionException:.

Other Projects

TransitionXRounded ButtonCacheX

×

Hello!

Click any one of the options below to chat on WhatsApp or send me an email to ft@ftkhan.me

× How can I help you?