Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,19 @@ Redux persist storage engine that provides an encryption layer over async storag
### What this project provides
This project provides an AES encryption layer (using a randomly generated secure key stored in keychain/keystore) over AsyncStorage for react-native projects


### To install in your project:
First install `react-native-keychain`. Then:

```ts
"peerDependencies": {
"@react-native-async-storage/async-storage": "*",
"react-native-keychain": "*",
"crypto-js": "^4.2.0",
"react-native-get-random-values": "^1.11.0",
"uuid": "^11.1.0"
}
```
First install above peerDependencies, Then:

```
yarn add 'https://github.com/chaudhryjunaid/redux-persist-encrypted-async-storage.git#master'
Expand Down
33 changes: 22 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
import { AsyncStorage } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Keychain from 'react-native-keychain';
import CryptoJSCore from 'crypto-js/core';
import AES from 'crypto-js/aes';

import uuidv4 from 'uuid/v4';
/**
* Important Note: Import 'react-native-get-random-values' before [crypto-js,uuid] to avoid crypto, uuid method errors
* https://github.com/uuidjs/uuid#getrandomvalues-not-supported
* [Error: getRandomValues() not supported.]
* [Error: Native crypto module could not be used to get secure random number.]
*/
import 'react-native-get-random-values';
import CryptoJS from 'crypto-js';
import { v4 as uuidv4 } from 'uuid';

let encryptionKey = null;
export default ({ service = 'com.redux-persist-encrypted-async-storage' } = {}) => {
export default ({
service = 'com.redux-persist-encrypted-async-storage',
} = {}) => {
const noop = () => null;

const getEncryptionKey = async () => {
if (encryptionKey == null) {
let { password: encryptionKeyValue } = await Keychain.getGenericPassword({ service });
let { password: encryptionKeyValue } = await Keychain.getGenericPassword({
service,
});

if (!encryptionKeyValue) {
encryptionKeyValue = uuidv4();
await Keychain.setGenericPassword('data', encryptionKeyValue, {
Expand All @@ -32,8 +42,8 @@ export default ({ service = 'com.redux-persist-encrypted-async-storage' } = {})
const encryptedValue = await AsyncStorage.getItem(key);
try {
const secretKey = await getEncryptionKey();
const bytes = AES.decrypt(encryptedValue, secretKey);
decryptedString = bytes.toString(CryptoJSCore.enc.Utf8);
const bytes = CryptoJS.AES.decrypt(encryptedValue, secretKey);
decryptedString = bytes.toString(CryptoJS.enc.Utf8);
} catch (err) {
throw new Error(`Could not decrypt state: ${err.message}`);
}
Expand All @@ -50,7 +60,7 @@ export default ({ service = 'com.redux-persist-encrypted-async-storage' } = {})
let encryptedValue = value;
if (value) {
const secretKey = await getEncryptionKey();
encryptedValue = AES.encrypt(value, secretKey).toString();
encryptedValue = CryptoJS.AES.encrypt(value, secretKey).toString();
}
await AsyncStorage.setItem(key, encryptedValue);
callback(null);
Expand All @@ -72,7 +82,8 @@ export default ({ service = 'com.redux-persist-encrypted-async-storage' } = {})

async getAllKeys(callback = noop) {
try {
const result = await AsyncStorage.getAllItems();
// should use getAllKeys() here, not getAllItems()
const result = await AsyncStorage.getAllKeys();

callback(null, result);
return result;
Expand Down
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "redux-persist-encrypted-async-storage",
"version": "1.0.0",
"version": "1.0.1",
"description": "Storage engine to provide encryption layer over async storage",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -30,11 +30,10 @@
"eslint-plugin-react": "^7.12.4"
},
"peerDependencies": {
"react-native": "*",
"react-native-keychain": "*"
},
"dependencies": {
"crypto-js": "^3.1.9-1",
"uuid": "^3.3.2"
"@react-native-async-storage/async-storage": "*",
"react-native-keychain": "*",
"crypto-js": "^4.2.0",
"react-native-get-random-values": "1.11.0",
"uuid": "^11.1.0"
}
}