react-native-nitro-storage 0.5.6 → 0.5.8
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/README.md +267 -362
- package/ios/IOSStorageAdapterCpp.mm +126 -80
- package/lib/commonjs/index.js +119 -1599
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +83 -1550
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/shared.js +102 -0
- package/lib/commonjs/shared.js.map +1 -0
- package/lib/commonjs/storage-core.js +1505 -0
- package/lib/commonjs/storage-core.js.map +1 -0
- package/lib/module/index.js +111 -1591
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +69 -1536
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/shared.js +82 -0
- package/lib/module/shared.js.map +1 -0
- package/lib/module/storage-core.js +1501 -0
- package/lib/module/storage-core.js.map +1 -0
- package/lib/typescript/index.d.ts +30 -133
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +31 -129
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/shared.d.ts +96 -0
- package/lib/typescript/shared.d.ts.map +1 -0
- package/lib/typescript/storage-core.d.ts +157 -0
- package/lib/typescript/storage-core.d.ts.map +1 -0
- package/package.json +7 -3
- package/react-native-nitro-storage.podspec +4 -0
- package/src/index.ts +260 -2519
- package/src/index.web.ts +133 -2326
- package/src/shared.ts +249 -0
- package/src/storage-core.ts +2349 -0
|
@@ -190,61 +190,27 @@ static NSMutableDictionary* allAccountsQuery(NSString* service, NSString* access
|
|
|
190
190
|
return query;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
static
|
|
194
|
-
|
|
195
|
-
disableKeychainInteraction(query);
|
|
196
|
-
CFTypeRef result = NULL;
|
|
197
|
-
std::vector<std::string> keys;
|
|
198
|
-
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
|
199
|
-
if (status == errSecInteractionNotAllowed) {
|
|
200
|
-
throw taggedStorageError(
|
|
201
|
-
"keychain_locked",
|
|
202
|
-
"NitroStorage: Keychain is locked (errSecInteractionNotAllowed). "
|
|
203
|
-
"The item is not accessible until the device is unlocked."
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
if (status == errSecSuccess && result) {
|
|
207
|
-
id items = (__bridge_transfer id)result;
|
|
208
|
-
NSArray* itemArray = nil;
|
|
209
|
-
if ([items isKindOfClass:[NSArray class]]) {
|
|
210
|
-
itemArray = (NSArray*)items;
|
|
211
|
-
} else if ([items isKindOfClass:[NSDictionary class]]) {
|
|
212
|
-
itemArray = @[(NSDictionary*)items];
|
|
213
|
-
}
|
|
214
|
-
if (itemArray) {
|
|
215
|
-
keys.reserve(itemArray.count);
|
|
216
|
-
for (NSDictionary* item in itemArray) {
|
|
217
|
-
NSString* account = item[(__bridge id)kSecAttrAccount];
|
|
218
|
-
if (account) {
|
|
219
|
-
keys.push_back(std::string([account UTF8String]));
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return keys;
|
|
193
|
+
static NSString* nsStringFromStdString(const std::string& value) {
|
|
194
|
+
return [NSString stringWithUTF8String:value.c_str()];
|
|
225
195
|
}
|
|
226
196
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
std::string groupStr;
|
|
231
|
-
int accessControlLevel;
|
|
232
|
-
{
|
|
233
|
-
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
234
|
-
groupStr = keychainAccessGroup_;
|
|
235
|
-
accessControlLevel = accessControlLevel_;
|
|
236
|
-
}
|
|
237
|
-
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
238
|
-
NSMutableDictionary* query = baseKeychainQuery(nsKey, kKeychainService, group);
|
|
197
|
+
static NSData* nsDataFromStdString(const std::string& value) {
|
|
198
|
+
return [nsStringFromStdString(value) dataUsingEncoding:NSUTF8StringEncoding];
|
|
199
|
+
}
|
|
239
200
|
|
|
201
|
+
static void setSecureValue(
|
|
202
|
+
NSString* nsKey,
|
|
203
|
+
NSData* data,
|
|
204
|
+
NSString* group,
|
|
205
|
+
int accessControlLevel
|
|
206
|
+
) {
|
|
207
|
+
NSMutableDictionary* query = baseKeychainQuery(nsKey, kKeychainService, group);
|
|
240
208
|
NSDictionary* updateAttributes = @{
|
|
241
209
|
(__bridge id)kSecValueData: data
|
|
242
210
|
};
|
|
243
211
|
|
|
244
212
|
OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)updateAttributes);
|
|
245
|
-
|
|
246
213
|
if (status == errSecSuccess) {
|
|
247
|
-
markSecureKeySet(key);
|
|
248
214
|
return;
|
|
249
215
|
}
|
|
250
216
|
|
|
@@ -252,20 +218,19 @@ void IOSStorageAdapterCpp::setSecure(const std::string& key, const std::string&
|
|
|
252
218
|
query[(__bridge id)kSecValueData] = data;
|
|
253
219
|
query[(__bridge id)kSecAttrAccessible] = (__bridge id)accessControlAttr(accessControlLevel);
|
|
254
220
|
const OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
|
|
255
|
-
if (addStatus
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
throw std::runtime_error(
|
|
264
|
-
"NitroStorage: Secure set failed with status " + std::to_string(addStatus)
|
|
221
|
+
if (addStatus == errSecSuccess) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (addStatus == errSecInteractionNotAllowed) {
|
|
225
|
+
throw taggedStorageError(
|
|
226
|
+
"keychain_locked",
|
|
227
|
+
"NitroStorage: Keychain is locked (errSecInteractionNotAllowed). "
|
|
228
|
+
"The item is not accessible until the device is unlocked."
|
|
265
229
|
);
|
|
266
230
|
}
|
|
267
|
-
|
|
268
|
-
|
|
231
|
+
throw std::runtime_error(
|
|
232
|
+
"NitroStorage: Secure set failed with status " + std::to_string(addStatus)
|
|
233
|
+
);
|
|
269
234
|
}
|
|
270
235
|
|
|
271
236
|
if (status == errSecInteractionNotAllowed) {
|
|
@@ -280,14 +245,7 @@ void IOSStorageAdapterCpp::setSecure(const std::string& key, const std::string&
|
|
|
280
245
|
);
|
|
281
246
|
}
|
|
282
247
|
|
|
283
|
-
std::optional<std::string>
|
|
284
|
-
NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
|
|
285
|
-
std::string groupStr;
|
|
286
|
-
{
|
|
287
|
-
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
288
|
-
groupStr = keychainAccessGroup_;
|
|
289
|
-
}
|
|
290
|
-
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
248
|
+
static std::optional<std::string> getSecureValue(NSString* nsKey, NSString* group) {
|
|
291
249
|
NSMutableDictionary* query = baseKeychainQuery(nsKey, kKeychainService, group);
|
|
292
250
|
query[(__bridge id)kSecReturnData] = @YES;
|
|
293
251
|
query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
|
|
@@ -310,15 +268,7 @@ std::optional<std::string> IOSStorageAdapterCpp::getSecure(const std::string& ke
|
|
|
310
268
|
return std::nullopt;
|
|
311
269
|
}
|
|
312
270
|
|
|
313
|
-
void
|
|
314
|
-
NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
|
|
315
|
-
std::string groupStr;
|
|
316
|
-
{
|
|
317
|
-
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
318
|
-
groupStr = keychainAccessGroup_;
|
|
319
|
-
}
|
|
320
|
-
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
321
|
-
|
|
271
|
+
static void deleteSecureValue(NSString* nsKey, NSString* group) {
|
|
322
272
|
NSMutableDictionary* secureQuery = baseKeychainQuery(nsKey, kKeychainService, group);
|
|
323
273
|
OSStatus secureStatus = SecItemDelete((__bridge CFDictionaryRef)secureQuery);
|
|
324
274
|
if (secureStatus == errSecInteractionNotAllowed) {
|
|
@@ -338,9 +288,77 @@ void IOSStorageAdapterCpp::deleteSecure(const std::string& key) {
|
|
|
338
288
|
"The item is not accessible until the device is unlocked."
|
|
339
289
|
);
|
|
340
290
|
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
static std::vector<std::string> keychainAccountsForService(NSString* service, NSString* accessGroup) {
|
|
294
|
+
NSMutableDictionary* query = allAccountsQuery(service, accessGroup);
|
|
295
|
+
disableKeychainInteraction(query);
|
|
296
|
+
CFTypeRef result = NULL;
|
|
297
|
+
std::vector<std::string> keys;
|
|
298
|
+
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
|
299
|
+
if (status == errSecInteractionNotAllowed) {
|
|
300
|
+
throw taggedStorageError(
|
|
301
|
+
"keychain_locked",
|
|
302
|
+
"NitroStorage: Keychain is locked (errSecInteractionNotAllowed). "
|
|
303
|
+
"The item is not accessible until the device is unlocked."
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
if (status == errSecSuccess && result) {
|
|
307
|
+
id items = (__bridge_transfer id)result;
|
|
308
|
+
NSArray* itemArray = nil;
|
|
309
|
+
if ([items isKindOfClass:[NSArray class]]) {
|
|
310
|
+
itemArray = (NSArray*)items;
|
|
311
|
+
} else if ([items isKindOfClass:[NSDictionary class]]) {
|
|
312
|
+
itemArray = @[(NSDictionary*)items];
|
|
313
|
+
}
|
|
314
|
+
if (itemArray) {
|
|
315
|
+
keys.reserve(itemArray.count);
|
|
316
|
+
for (NSDictionary* item in itemArray) {
|
|
317
|
+
NSString* account = item[(__bridge id)kSecAttrAccount];
|
|
318
|
+
if (account) {
|
|
319
|
+
keys.push_back(std::string([account UTF8String]));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return keys;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
void IOSStorageAdapterCpp::setSecure(const std::string& key, const std::string& value) {
|
|
328
|
+
NSString* nsKey = nsStringFromStdString(key);
|
|
329
|
+
NSData* data = nsDataFromStdString(value);
|
|
330
|
+
std::string groupStr;
|
|
331
|
+
int accessControlLevel;
|
|
332
|
+
{
|
|
333
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
334
|
+
groupStr = keychainAccessGroup_;
|
|
335
|
+
accessControlLevel = accessControlLevel_;
|
|
336
|
+
}
|
|
337
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
338
|
+
setSecureValue(nsKey, data, group, accessControlLevel);
|
|
339
|
+
markSecureKeySet(key);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
std::optional<std::string> IOSStorageAdapterCpp::getSecure(const std::string& key) {
|
|
343
|
+
NSString* nsKey = nsStringFromStdString(key);
|
|
344
|
+
std::string groupStr;
|
|
345
|
+
{
|
|
346
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
347
|
+
groupStr = keychainAccessGroup_;
|
|
348
|
+
}
|
|
349
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
350
|
+
return getSecureValue(nsKey, group);
|
|
351
|
+
}
|
|
341
352
|
|
|
342
|
-
|
|
343
|
-
|
|
353
|
+
void IOSStorageAdapterCpp::deleteSecure(const std::string& key) {
|
|
354
|
+
NSString* nsKey = nsStringFromStdString(key);
|
|
355
|
+
std::string groupStr;
|
|
356
|
+
{
|
|
357
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
358
|
+
groupStr = keychainAccessGroup_;
|
|
359
|
+
}
|
|
360
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
361
|
+
deleteSecureValue(nsKey, group);
|
|
344
362
|
markSecureKeyRemoved(key);
|
|
345
363
|
markBiometricKeyRemoved(key);
|
|
346
364
|
}
|
|
@@ -400,25 +418,53 @@ void IOSStorageAdapterCpp::setSecureBatch(
|
|
|
400
418
|
const std::vector<std::string>& keys,
|
|
401
419
|
const std::vector<std::string>& values
|
|
402
420
|
) {
|
|
421
|
+
std::string groupStr;
|
|
422
|
+
int accessControlLevel;
|
|
423
|
+
{
|
|
424
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
425
|
+
groupStr = keychainAccessGroup_;
|
|
426
|
+
accessControlLevel = accessControlLevel_;
|
|
427
|
+
}
|
|
428
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
403
429
|
for (size_t i = 0; i < keys.size() && i < values.size(); ++i) {
|
|
404
|
-
|
|
430
|
+
setSecureValue(
|
|
431
|
+
nsStringFromStdString(keys[i]),
|
|
432
|
+
nsDataFromStdString(values[i]),
|
|
433
|
+
group,
|
|
434
|
+
accessControlLevel
|
|
435
|
+
);
|
|
436
|
+
markSecureKeySet(keys[i]);
|
|
405
437
|
}
|
|
406
438
|
}
|
|
407
439
|
|
|
408
440
|
std::vector<std::optional<std::string>> IOSStorageAdapterCpp::getSecureBatch(
|
|
409
441
|
const std::vector<std::string>& keys
|
|
410
442
|
) {
|
|
443
|
+
std::string groupStr;
|
|
444
|
+
{
|
|
445
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
446
|
+
groupStr = keychainAccessGroup_;
|
|
447
|
+
}
|
|
448
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
411
449
|
std::vector<std::optional<std::string>> results;
|
|
412
450
|
results.reserve(keys.size());
|
|
413
451
|
for (const auto& key : keys) {
|
|
414
|
-
results.push_back(
|
|
452
|
+
results.push_back(getSecureValue(nsStringFromStdString(key), group));
|
|
415
453
|
}
|
|
416
454
|
return results;
|
|
417
455
|
}
|
|
418
456
|
|
|
419
457
|
void IOSStorageAdapterCpp::deleteSecureBatch(const std::vector<std::string>& keys) {
|
|
458
|
+
std::string groupStr;
|
|
459
|
+
{
|
|
460
|
+
std::lock_guard<std::mutex> lock(accessGroupMutex_);
|
|
461
|
+
groupStr = keychainAccessGroup_;
|
|
462
|
+
}
|
|
463
|
+
NSString* group = groupStr.empty() ? nil : [NSString stringWithUTF8String:groupStr.c_str()];
|
|
420
464
|
for (const auto& key : keys) {
|
|
421
|
-
|
|
465
|
+
deleteSecureValue(nsStringFromStdString(key), group);
|
|
466
|
+
markSecureKeyRemoved(key);
|
|
467
|
+
markBiometricKeyRemoved(key);
|
|
422
468
|
}
|
|
423
469
|
}
|
|
424
470
|
|