Adam Paulson
Adam Paulson

Reputation: 31

React Native redux-persist encryption key generation

I'm building a React Native app that is using redux-persist and redux-persist-transform-encrypt to store app state encrypted on the device. redux-persist-transform-encrypt uses CryptoJs to encrypt data via AES: CryptoJS.AES.encrypt('serialized app state', 'some-secret-key').

My question: (I'm a crypto novice) is there a best practice for generating some-secret-key? My plan is to generate this key randomly when the app boots for the first time and store it securely in the device keychain.

Upvotes: 3

Views: 2074

Answers (2)

Abhishek Chandel
Abhishek Chandel

Reputation: 199

You can use some uuid generator to generate random secret key. then store it in the keychain as @jimchao said. If you are using expo you can write something as follows:

import Expo from 'expo';

export const getFromSecureStore = (key, options) =>
  Expo.SecureStore.getItemAsync(key, options);

export const saveToSecureStore = (key, value, options) =>
  Expo.SecureStore.setItemAsync(key, value, options);

then use it as:

// while signing in

function* handleSignInRequest(action) {
  try {
    const resp = yield RequestService.post(
      action.payload.url,
      action.payload.body,
    );
    yield put({ type: SIGN_IN_SUCCEEDED, payload: resp.data });
    const { username, password } = action.payload.body;
    yield saveToSecureStore('username', username, {
      keychainAccessible: Expo.SecureStore.ALWAYS, // can be changed as per usage
    });
    yield saveToSecureStore('password', password, {
      keychainAccessible: Expo.SecureStore.ALWAYS,
    });
  } catch (error) {
    console.log('======>>  signin error', error);
    yield put({ type: SIGN_IN_FAILED, error: error.response });
  }
}

// at app start

async handleSignInAtBootstrap() {
    try {
      const username = await getFromSecureStore('username');
      const password = await getFromSecureStore('password');
      this.props.signInUser(username, password); //dispatch an action
    } catch (error) {
      console.log('======>>>', error);
    }
  }

here's Expo secure store docs to explore various configs

Upvotes: 0

Jimchao
Jimchao

Reputation: 1468

We use React Native Keychain to store the random generate key, to ensure the key is harder to get even if the attacker have access to file system:

let secretKey

async function getSecretKey() {
  let {password} = await Keychain.getGenericPassword()
  if (!password) {
    password = generateRandomKey()
    await Keychain.setGenericPassword(appName, password)
  }
  return password
}

const encrypt = async function(state) {
  if (!secretKey) {
    secretKey = await getSecretKey()
  }

  if (typeof state !== 'string') {
    state = stringify(state);
  }

  return CryptoJS.AES.encrypt(state, secretKey).toString()
}

Upvotes: 1

Related Questions