react-native-security-suite 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -2
- package/README.md +40 -3
- package/android/build.gradle +85 -43
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +1 -3
- package/android/src/main/AndroidManifestDeprecated.xml +3 -0
- package/android/src/main/java/com/securitysuite/SecuritySuiteModule.java +202 -0
- package/android/src/main/java/com/securitysuite/SecuritySuitePackage.java +28 -0
- package/android/src/main/java/com/securitysuite/StorageEncryption.java +52 -0
- package/ios/DataHashingMethods.swift +196 -0
- package/ios/SecuritySuite-Bridging-Header.h +1 -0
- package/ios/SecuritySuite.mm +26 -0
- package/ios/SecuritySuite.swift +129 -0
- package/ios/SecuritySuite.xcodeproj/project.pbxproj +13 -17
- package/ios/SecuritySuite.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/SecuritySuite.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/SecuritySuite.xcodeproj/project.xcworkspace/xcuserdata/mohammadnavabi.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/SecuritySuite.xcodeproj/xcuserdata/mohammadnavabi.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/ios/StorageEncryption.swift +81 -0
- package/lib/commonjs/helpers.js +16 -0
- package/lib/commonjs/helpers.js.map +1 -0
- package/lib/commonjs/index.js +158 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/helpers.js +9 -0
- package/lib/module/helpers.js.map +1 -0
- package/lib/module/index.js +147 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/helpers.d.ts +2 -0
- package/lib/typescript/helpers.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +20 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/package.json +54 -33
- package/react-native-security-suite.podspec +18 -2
- package/src/helpers.ts +8 -0
- package/src/index.tsx +203 -3
- package/android/src/main/java/com/reactnativesecuritysuite/SecuritySuiteModule.java +0 -38
- package/android/src/main/java/com/reactnativesecuritysuite/SecuritySuitePackage.java +0 -28
- package/ios/SecuritySuite.m +0 -12
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { isJsonString } from './helpers';
|
|
2
5
|
|
|
3
6
|
const LINKING_ERROR =
|
|
4
7
|
`The package 'react-native-security-suite' doesn't seem to be linked. Make sure: \n\n` +
|
|
@@ -15,10 +18,207 @@ const SecuritySuite = NativeModules.SecuritySuite
|
|
|
15
18
|
throw new Error(LINKING_ERROR);
|
|
16
19
|
},
|
|
17
20
|
}
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const getPublicKey = (): Promise<string> => SecuritySuite.getPublicKey();
|
|
24
|
+
|
|
25
|
+
export const getSharedKey = (serverPublicKey: string): Promise<string> =>
|
|
26
|
+
SecuritySuite.getSharedKey(serverPublicKey);
|
|
27
|
+
|
|
28
|
+
export const encryptBySharedKey = (input: string): Promise<string> =>
|
|
29
|
+
input && typeof input === 'string' ? SecuritySuite.encrypt(input) : '';
|
|
30
|
+
|
|
31
|
+
export const decryptBySharedKey = (input: string) =>
|
|
32
|
+
input && typeof input === 'string' ? SecuritySuite.decrypt(input) : '';
|
|
33
|
+
|
|
34
|
+
export const getDeviceId = (): Promise<string> =>
|
|
35
|
+
new Promise((resolve: any, reject: any) => {
|
|
36
|
+
SecuritySuite.getDeviceId((result: string | null, error: string | null) => {
|
|
37
|
+
if (error !== null) reject(error);
|
|
38
|
+
else resolve(result);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const encrypt = (
|
|
43
|
+
input: string,
|
|
44
|
+
hardEncryption = true,
|
|
45
|
+
secretKey = null
|
|
46
|
+
): Promise<string> =>
|
|
47
|
+
new Promise((resolve: any, reject: any) => {
|
|
48
|
+
if (!input) resolve(input);
|
|
49
|
+
|
|
50
|
+
SecuritySuite.storageEncrypt(
|
|
51
|
+
input,
|
|
52
|
+
secretKey,
|
|
53
|
+
hardEncryption,
|
|
54
|
+
(result: string | null, error: string | null) => {
|
|
55
|
+
if (error !== null) reject(error);
|
|
56
|
+
else resolve(result);
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const decrypt = (
|
|
62
|
+
input: string,
|
|
63
|
+
hardEncryption = true,
|
|
64
|
+
secretKey = null
|
|
65
|
+
): Promise<string> =>
|
|
66
|
+
new Promise((resolve: any, reject: any) => {
|
|
67
|
+
if (!input) resolve(input);
|
|
68
|
+
|
|
69
|
+
SecuritySuite.storageDecrypt(
|
|
70
|
+
input,
|
|
71
|
+
secretKey,
|
|
72
|
+
hardEncryption,
|
|
73
|
+
(result: string | null, error: string | null) => {
|
|
74
|
+
if (error !== null) reject(error);
|
|
75
|
+
else resolve(result);
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const SecureStorage = {
|
|
81
|
+
setItem: async (key: string, value: string) => {
|
|
82
|
+
try {
|
|
83
|
+
const encryptedKey = await encrypt(key, false);
|
|
84
|
+
const encryptedValue = await encrypt(value);
|
|
85
|
+
return AsyncStorage.setItem(encryptedKey, encryptedValue);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
return e;
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
getItem: async (key: string) => {
|
|
91
|
+
try {
|
|
92
|
+
const encryptedKey = await encrypt(key, false);
|
|
93
|
+
const encryptedData = await AsyncStorage.getItem(encryptedKey);
|
|
94
|
+
return decrypt(encryptedData ?? '');
|
|
95
|
+
} catch (e) {
|
|
96
|
+
return e;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
mergeItem: async (key: string, value: string) => {
|
|
100
|
+
try {
|
|
101
|
+
const encryptedKey = await encrypt(key, false);
|
|
102
|
+
const encryptedData = await AsyncStorage.getItem(encryptedKey);
|
|
103
|
+
const data = await decrypt(encryptedData ?? '');
|
|
104
|
+
if (!isJsonString(data) || !isJsonString(value)) return null;
|
|
105
|
+
const mergedData = await JSON.stringify(
|
|
106
|
+
_.merge(JSON.parse(data), JSON.parse(value))
|
|
107
|
+
);
|
|
108
|
+
const encryptedValue = await encrypt(mergedData);
|
|
109
|
+
return AsyncStorage.setItem(encryptedKey, encryptedValue);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return e;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
removeItem: async (key: string) => {
|
|
115
|
+
try {
|
|
116
|
+
const encryptedKey = await encrypt(key, false);
|
|
117
|
+
return AsyncStorage.removeItem(encryptedKey);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return e;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
getAllKeys: async () => {
|
|
123
|
+
try {
|
|
124
|
+
const encryptedKeys = await AsyncStorage.getAllKeys();
|
|
125
|
+
return await Promise.all(
|
|
126
|
+
encryptedKeys.map(async (item: string): Promise<string> => {
|
|
127
|
+
const decryptedKey = await decrypt(item, false);
|
|
128
|
+
return decryptedKey ? decryptedKey : item;
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
} catch (e) {
|
|
132
|
+
return e;
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
multiSet: async (
|
|
136
|
+
keyValuePairs: Array<Array<string>>
|
|
137
|
+
): Promise<void | string[][]> => {
|
|
138
|
+
try {
|
|
139
|
+
const encryptedKeyValuePairs: any = await Promise.all(
|
|
140
|
+
keyValuePairs.map(async (item: Array<string>) => {
|
|
141
|
+
if (item.length === 2 && item[0] && item[1]) {
|
|
142
|
+
const encryptedKey = await encrypt(item[0], false);
|
|
143
|
+
const encryptedValue = await encrypt(item[1]);
|
|
144
|
+
return [encryptedKey, encryptedValue];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return null;
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
AsyncStorage.multiSet(encryptedKeyValuePairs);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.error('multiSet error: ', e);
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
multiGet: async (keys: Array<string>) => {
|
|
156
|
+
try {
|
|
157
|
+
if (!Array.isArray(keys)) return null;
|
|
158
|
+
const encryptedKeys = await Promise.all(
|
|
159
|
+
keys.map(
|
|
160
|
+
async (item: string): Promise<string> => await encrypt(item, false)
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
const encryptedItems = await AsyncStorage.multiGet(encryptedKeys);
|
|
164
|
+
return await Promise.all(
|
|
165
|
+
encryptedItems && encryptedItems.length
|
|
166
|
+
? encryptedItems.map(async (item: any): Promise<string[]> => {
|
|
167
|
+
const decryptedKey = await decrypt(item[0], false);
|
|
168
|
+
const decryptedalue = await decrypt(item[1]);
|
|
169
|
+
return [decryptedKey, decryptedalue];
|
|
170
|
+
})
|
|
171
|
+
: []
|
|
172
|
+
);
|
|
173
|
+
} catch (e) {
|
|
174
|
+
return e;
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
multiMerge: async (keyValuePairs: Array<Array<string>>) => {
|
|
178
|
+
try {
|
|
179
|
+
return keyValuePairs.map(async (item: Array<string>) => {
|
|
180
|
+
if (item.length === 2 && item[0] && item[1]) {
|
|
181
|
+
const encryptedKey = await encrypt(item[0], false);
|
|
182
|
+
const encryptedData = await AsyncStorage.getItem(item[0]);
|
|
183
|
+
const data = await decrypt(encryptedData ?? '');
|
|
184
|
+
if (!isJsonString(data) || !isJsonString(item[1])) return null;
|
|
185
|
+
const mergedData = await JSON.stringify(
|
|
186
|
+
_.merge(JSON.parse(data), JSON.parse(item[1]))
|
|
187
|
+
);
|
|
188
|
+
const encryptedValue = await encrypt(mergedData, false);
|
|
189
|
+
return AsyncStorage.setItem(encryptedKey, encryptedValue);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return null;
|
|
193
|
+
});
|
|
194
|
+
} catch (e) {
|
|
195
|
+
return e;
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
multiRemove: async (keys: Array<string>) => {
|
|
199
|
+
try {
|
|
200
|
+
if (!Array.isArray(keys)) return keys;
|
|
201
|
+
const encryptedKeys = await Promise.all(
|
|
202
|
+
keys.map(
|
|
203
|
+
async (item: string): Promise<string> => await encrypt(item, false)
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
return AsyncStorage.multiRemove(encryptedKeys);
|
|
207
|
+
} catch (e) {
|
|
208
|
+
return e;
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
clear: async () => {
|
|
212
|
+
try {
|
|
213
|
+
return AsyncStorage.clear();
|
|
214
|
+
} catch (e) {
|
|
215
|
+
return e;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
|
|
20
220
|
export function deviceHasSecurityRisk(): Promise<boolean> {
|
|
21
221
|
return SecuritySuite.deviceHasSecurityRisk();
|
|
22
222
|
}
|
|
23
223
|
|
|
24
|
-
export default SecuritySuite;
|
|
224
|
+
export default SecuritySuite;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
package com.reactnativesecuritysuite;
|
|
2
|
-
|
|
3
|
-
import androidx.annotation.NonNull;
|
|
4
|
-
|
|
5
|
-
import com.facebook.react.bridge.Promise;
|
|
6
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
8
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
9
|
-
import com.facebook.react.module.annotations.ReactModule;
|
|
10
|
-
import com.scottyab.rootbeer.RootBeer;
|
|
11
|
-
|
|
12
|
-
@ReactModule(name = SecuritySuiteModule.NAME)
|
|
13
|
-
public class SecuritySuiteModule extends ReactContextBaseJavaModule {
|
|
14
|
-
public static final String NAME = "SecuritySuite";
|
|
15
|
-
private ReactApplicationContext context;
|
|
16
|
-
|
|
17
|
-
public SecuritySuiteModule(ReactApplicationContext reactContext) {
|
|
18
|
-
super(reactContext);
|
|
19
|
-
context = reactContext;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@Override
|
|
23
|
-
@NonNull
|
|
24
|
-
public String getName() {
|
|
25
|
-
return NAME;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Example method
|
|
30
|
-
// See https://reactnative.dev/docs/native-modules-android
|
|
31
|
-
@ReactMethod
|
|
32
|
-
public void deviceHasSecurityRisk(Promise promise) {
|
|
33
|
-
RootBeer rootBeer = new RootBeer(context);
|
|
34
|
-
promise.resolve(rootBeer.isRooted());
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
public static native int nativeMultiply(int a, int b);
|
|
38
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
package com.reactnativesecuritysuite;
|
|
2
|
-
|
|
3
|
-
import androidx.annotation.NonNull;
|
|
4
|
-
|
|
5
|
-
import com.facebook.react.ReactPackage;
|
|
6
|
-
import com.facebook.react.bridge.NativeModule;
|
|
7
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
-
import com.facebook.react.uimanager.ViewManager;
|
|
9
|
-
|
|
10
|
-
import java.util.ArrayList;
|
|
11
|
-
import java.util.Collections;
|
|
12
|
-
import java.util.List;
|
|
13
|
-
|
|
14
|
-
public class SecuritySuitePackage implements ReactPackage {
|
|
15
|
-
@NonNull
|
|
16
|
-
@Override
|
|
17
|
-
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
|
|
18
|
-
List<NativeModule> modules = new ArrayList<>();
|
|
19
|
-
modules.add(new SecuritySuiteModule(reactContext));
|
|
20
|
-
return modules;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@NonNull
|
|
24
|
-
@Override
|
|
25
|
-
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
26
|
-
return Collections.emptyList();
|
|
27
|
-
}
|
|
28
|
-
}
|
package/ios/SecuritySuite.m
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#import <React/RCTBridgeModule.h>
|
|
2
|
-
|
|
3
|
-
@interface RCT_EXTERN_MODULE(SecuritySuite, NSObject)
|
|
4
|
-
|
|
5
|
-
RCT_EXTERN_METHOD(deviceHasSecurityRisk:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
|
|
6
|
-
|
|
7
|
-
+ (BOOL)requiresMainQueueSetup
|
|
8
|
-
{
|
|
9
|
-
return NO;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
@end
|