Back to articles

Secure Data Storage in React Native: Encryption Guide

A Complete Guide to Protecting User Privacy with Data Encryption

September 21, 2018
React Native logo with encryption overlay showing security implementation
react native
mobile applications
redux
tutorial
4 min read

Users’ need for privacy and data security keeps increasing daily and it will always be in demand. So how do we store data on a mobile device without worrying about security? In this article, we’ll go through an effortless and quick way to:

  • Set up persistent storage for our app and store any user data locally.

  • Encrypt the data to make it secure so users feel less worried about their privacy.

So, let’s get started!


Persisting the data

First, we’ll set up persistent storage for our app. For this, we’ll use an excellent and easy-to-use library called redux-persist. Most of you must be familiar with redux. For those unfamiliar, it is a simple way to manage and share data in your React and React Native apps across various components and views. You can read more about it in my article on redux and how to use it in React and React Native apps.

Open the terminal and type the following command on your project’s root directory:

npm i redux-persist

This command will install redux-persist, which will help us to retain our data from previous sessions.

note

We’ll use redux-promise as our middleware for the examples in this article. You can use any middleware, like redux-saga or redux-thunk, based on your requirements!

Now let’s set up our store to make it persistent — so that the next time our app loads up, we’ll have data saved from the previous session. On your main store.js, set up persistent storage like this:

import { combineReducers, createStore, applyMiddleware } from 'redux';
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';
import promise from 'redux-promise';

// Create the root reducer as you normally would.
const rootReducer = combineReducers({
  myPersistentData: dataReducer,
  someMorePresistentData: randomReducer,
});

/* 
Create the configuration object to be used for transforming our simple
root reducer into a property on persistent storage.
*/

const config = {
  key: '_myPersistentDataKey',
  storage,
};

// Make your reducer persistent with persistReducer()
const reducer = persistReducer(config, rootReducer);

const store = createStore(
  reducer,                      // Your persistent reducer
  {},                           // Initial store state
  applyMiddleware(promise),     // middleware(s)
);

// Convert your store to be persistent accross app sessions.
const persist = persistStore(store);

export default { store, persist };

In the main App.js file, modify the render function like this:

import { PersistGate } from "redux-persist/integration/react";
import { Provider } from "react-redux";

import store from "./store";
import MyRootComponent from "./src";

class App extends Component {
  constructor(props) {
    super(props);
    // ...
  }

  render() {
    return (
      <Provider store={store.store}>
        <PersistGate persistor={store.persist}>
          <MyRootComponent />
        </PersistGate>
      </Provider>
    );
  }
}

export default App;

That’s it! We’ve set up our redux state to be persistent! Easy.


Encrypting the persisted data

For this, we’ll use redux-persist-transform-encrypt. Run the following command on your project’s root directory:

npm i redux-persist-transform-encrypt

This will help us encrypt and decrypt user data across multiple sessions.

important

Since this was just an example of how to encrypt your data, we hard-coded our secret key into the source code, but you must never do that! Ideally, it would be injected during our build process.

Now, open the store.js file again and update it to look like this:

import { combineReducers, createStore, applyMiddleware } from 'redux';
import storage from 'redux-persist/lib/storage';
import { persistReducer, persistStore } from 'redux-persist';
import promise from 'redux-promise';
import createEncryptor from 'redux-persist-transform-encrypt'; // <----- Import createEncryptor

const rootReducer = combineReducers({
  myPersistentData: dataReducer,
  someMorePresistentData: randomReducer,
});

/*
 Configure your encryptor with the secret key
 NOTE: This secret key is required for access to data.
 If the key is incorrect or changed after storing data
 with some different key, it will return null.
*/
const encryptor = createEncryptor({
  secretKey: 'my-not-so-secret-encryption-key',
  onError: (error) => {
    console.warn('error occured on encryptor', error);
  },
});

const config = {
  key: '_myPersistentDataKey',
  storage,
  /* Add the encryptor as a transform property. This is will
  tell the persistent storage to encrypt data using the
  configuration given earlier,i.e., our secretKey. */
  transforms: [encryptor],  // <----- Add this line.
};

const reducer = persistReducer(config, rootReducer);

const store = createStore(
  reducer,
  {},
  applyMiddleware(promise),
);
const persist = persistStore(store);

export default { store, persist };

Awesome! We made the data in our store state persistent locally, along with encryption! 🎉 👏

Congrats now we’ve encrypted our locally persisted react native application data.


Happy hacking! Cheers! 🎉

You may also be interested in

React Native logo with file size reduction visualization showing Android build optimization

How to Shrink React Native Android App Size by 50%

September 20, 2018

Learn how to dramatically reduce your React Native Android app size using ProGuard and build configurations. Simple steps to compress bytecode and create architecture-specific APKs.

Read article
React hooks implementation for state management without Redux

Managing React application state - without using Redux!

May 19, 2019

In this article, we explore managing React application state using hooks. We leverage the React.useContext and React.useReducer hooks to create a Redux-like state management system without external dependencies.

Read article
React Native logo with Android emulator illustration

How to Install Android Emulator for React Native Without Android Studio | Mac, Linux & Windows

January 12, 2019

Learn how to install and set up Android Emulator for React Native development on Mac, Linux, and Windows without Android Studio. This step-by-step command-line guide helps you create virtual devices with minimal system resources and zero bloatware.

Read article
A visual guide to organizing complex React applications with Redux, Sagas, and Services for better state management and code maintainability

Redux Store Architecture in React Applications - Organizing Complex State Management

May 11, 2019

Learn how to architect complex React applications with Redux, Redux-Saga, and service layers. This guide provides a scalable structure for organizing reducers, actions, middlewares, and selectors in large React projects.

Read article
Like any other web application, React applications also require close attention to their architecture. Introduction of Hooks might have shown us new ways of abstractions in our React applications but what about so many applications that are still using older versions of React?

Scalable React Application Architecture: Best Practices for Directory Structure

April 11, 2019

Learn how to structure your React applications with a scalable and maintainable architecture. Discover practical directory organization patterns based on real-world experience.

Read article
Lighthouse audit automation dashboard showing performance metrics for a Progressive Web App

Automate Lighthouse Audits for Your Progressive Web App

June 29, 2019

Learn how to automate your Lighthouse audits with Mocha and Chai instead of manually performing audits on your Progressive Web Application. Run tests programmatically in CI/CD environments or locally to maintain consistent quality standards.

Read article