react-native-security-suite
Version:
Comprehensive security suite for React Native apps - Root/Jailbreak detection, SSL pinning, encryption, secure storage, screenshot protection, and network monitoring
192 lines (189 loc) • 6.93 kB
JavaScript
;
import { NativeModules, Platform } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { isJsonString, jsonParse } from "./helpers.js";
export * from "./SecureView.js";
/*
* SSL Pinnning start
*/
const LINKING_ERROR = `The package 'react-native-security-suite' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
ios: "- You have run 'pod install'\n",
default: ''
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n';
const SecuritySuite = NativeModules.SecuritySuite ? NativeModules.SecuritySuite : new Proxy({}, {
get() {
throw new Error(LINKING_ERROR);
}
});
export const getPublicKey = () => SecuritySuite.getPublicKey();
export const getSharedKey = serverPublicKey => SecuritySuite.getSharedKey(serverPublicKey);
export const encryptBySharedKey = input => input && typeof input === 'string' ? SecuritySuite.encrypt(input) : '';
export const decryptBySharedKey = input => input && typeof input === 'string' ? SecuritySuite.decrypt(input) : '';
export const getDeviceId = () => new Promise((resolve, reject) => {
SecuritySuite.getDeviceId((result, error) => {
if (error !== null) reject(error);else resolve(result);
});
});
export const encrypt = (input, hardEncryption = true, secretKey = null) => new Promise((resolve, reject) => {
if (!input) resolve(input);
SecuritySuite.storageEncrypt(input, secretKey, hardEncryption, (result, error) => {
if (error !== null) reject(error);else resolve(result);
});
});
export const decrypt = (input, hardEncryption = true, secretKey = null) => new Promise((resolve, reject) => {
if (!input) resolve(input);
SecuritySuite.storageDecrypt(input, secretKey, hardEncryption, (result, error) => {
if (error !== null) reject(error);else resolve(result);
});
});
export const SecureStorage = {
setItem: async (key, value) => {
try {
const encryptedKey = await encrypt(key, false);
const encryptedValue = await encrypt(value);
return AsyncStorage.setItem(encryptedKey, encryptedValue);
} catch (e) {
console.error('setItem error: ', e);
}
},
getItem: async key => {
try {
const encryptedKey = await encrypt(key, false);
const encryptedData = await AsyncStorage.getItem(encryptedKey);
return decrypt(encryptedData ?? '');
} catch (e) {
console.error('getItem error: ', e);
return '';
}
},
mergeItem: async (key, value) => {
try {
const encryptedKey = await encrypt(key, false);
const encryptedData = await AsyncStorage.getItem(encryptedKey);
const data = await decrypt(encryptedData ?? '');
if (!isJsonString(data) || !isJsonString(value)) return;
const mergedData = await JSON.stringify(Object.assign(JSON.parse(data), JSON.parse(value)));
const encryptedValue = await encrypt(mergedData);
return AsyncStorage.setItem(encryptedKey, encryptedValue);
} catch (e) {
console.error('mergeItem error: ', e);
}
},
removeItem: async key => {
try {
const encryptedKey = await encrypt(key, false);
return AsyncStorage.removeItem(encryptedKey);
} catch (e) {
console.error('removeItem error: ', e);
}
},
getAllKeys: async () => {
try {
const encryptedKeys = await AsyncStorage.getAllKeys();
return await Promise.all(encryptedKeys.map(async item => {
const decryptedKey = await decrypt(item, false);
return decryptedKey ? decryptedKey : item;
}));
} catch (e) {
console.error('getAllKeys error: ', e);
return [];
}
},
multiSet: async keyValuePairs => {
try {
const encryptedKeyValuePairs = await Promise.all(keyValuePairs.map(async item => {
if (item.length === 2 && item[0] && item[1]) {
const encryptedKey = await encrypt(item[0], false);
const encryptedValue = await encrypt(item[1]);
return [encryptedKey, encryptedValue];
}
return null;
}));
AsyncStorage.multiSet(encryptedKeyValuePairs);
} catch (e) {
console.error('multiSet error: ', e);
}
},
multiGet: async keys => {
try {
if (!Array.isArray(keys)) return [];
const encryptedKeys = await Promise.all(keys.map(async item => await encrypt(item, false)));
const encryptedItems = await AsyncStorage.multiGet(encryptedKeys);
return await Promise.all(encryptedItems && encryptedItems.length ? encryptedItems.map(async item => {
const decryptedKey = await decrypt(item[0], false);
const decryptedalue = await decrypt(item[1]);
return [decryptedKey, decryptedalue];
}) : []);
} catch (e) {
console.error('multiGet error: ', e);
return [];
}
},
multiMerge: async keyValuePairs => {
try {
keyValuePairs.map(async item => {
if (item.length === 2 && item[0] && item[1]) {
const encryptedKey = await encrypt(item[0], false);
const encryptedData = await AsyncStorage.getItem(item[0]);
const data = await decrypt(encryptedData ?? '');
if (!isJsonString(data) || !isJsonString(item[1])) return null;
const mergedData = await JSON.stringify(Object.assign(JSON.parse(data), JSON.parse(item[1])));
const encryptedValue = await encrypt(mergedData, false);
return AsyncStorage.setItem(encryptedKey, encryptedValue);
}
return null;
});
} catch (e) {
console.error('multiMerge error: ', e);
}
},
multiRemove: async keys => {
try {
if (!Array.isArray(keys)) return keys;
const encryptedKeys = await Promise.all(keys.map(async item => await encrypt(item, false)));
return AsyncStorage.multiRemove(encryptedKeys);
} catch (e) {
console.error('multiRemove error: ', e);
}
},
clear: async () => {
try {
return AsyncStorage.clear();
} catch (e) {
console.error('clear error: ', e);
}
}
};
export function fetch(url, options, loggerIsEnabled = false) {
return new Promise((resolve, reject) => {
SecuritySuite.fetch(url, {
...options,
loggerIsEnabled
}, (result, error) => {
try {
if (error === null) {
resolve({
...result,
json: () => jsonParse(result.response)
});
} else {
const errorJson = jsonParse(error.error);
reject({
json: () => errorJson,
error: error?.error ?? error,
status: error?.status ?? '',
url: error?.url ?? '',
...errorJson
});
}
} catch (e) {
console.error('SSL Pinnning fetch error: ', e);
}
});
});
}
export function deviceHasSecurityRisk() {
return SecuritySuite.deviceHasSecurityRisk();
}
export default SecuritySuite;
//# sourceMappingURL=index.js.map