Skip to content

Commit c6cbbbf

Browse files
author
Roman Barzyczak
committed
Add possibility to set accessible attribute for iOS
1 parent eac08e5 commit c6cbbbf

File tree

8 files changed

+2465
-881
lines changed

8 files changed

+2465
-881
lines changed

android/src/main/java/com/reactlibrary/securekeystore/RNSecureKeyStoreModule.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.security.PrivateKey;
2828
import java.security.PublicKey;
2929
import java.util.Calendar;
30+
import android.support.annotation.Nullable;
31+
import com.facebook.react.bridge.ReadableMap;
3032

3133
import javax.crypto.Cipher;
3234
import javax.crypto.CipherInputStream;
@@ -51,7 +53,7 @@ public String getName() {
5153
}
5254

5355
@ReactMethod
54-
public void set(String alias, String input, Promise promise) {
56+
public void set(String alias, String input, @Nullable ReadableMap options, Promise promise) {
5557
try {
5658
setCipherText(alias, input);
5759
promise.resolve("stored ciphertext in app storage");

example/app/app.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ import {
1212
View
1313
} from 'react-native';
1414

15-
import RNSecureKeyStore from "react-native-secure-key-store";
15+
import RNSecureKeyStore, {ACCESSIBLE} from "react-native-secure-key-store";
1616

1717
export default class example extends Component {
1818
render() {
1919

20-
RNSecureKeyStore.set("key1", "value1")
20+
RNSecureKeyStore.set("key1", "value1", {accessible: ACCESSIBLE.ALWAYS_THIS_DEVICE_ONLY})
2121
.then((res) => {
2222
console.log(res);
2323
}, (err) => {
2424
console.log(err);
2525
});
2626

27-
RNSecureKeyStore.set("key2", "value2")
27+
RNSecureKeyStore.set("key2", "value2", {accessible: ACCESSIBLE.ALWAYS_THIS_DEVICE_ONLY})
2828
.then((res) => {
2929
console.log(res);
3030
}, (err) => {

example/ios/example.xcodeproj/project.pbxproj

Lines changed: 92 additions & 56 deletions
Large diffs are not rendered by default.

example/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
"test": "jest"
88
},
99
"dependencies": {
10-
"react": "16.0.0-alpha.6",
11-
"react-native": "0.44.0",
10+
"react": "16.3.0-alpha.1",
11+
"react-intl": "^2.4.0",
12+
"react-native": "^0.55.4",
1213
"react-native-secure-key-store": "../../react-native-secure-key-store"
1314
},
1415
"devDependencies": {

example/yarn.lock

Lines changed: 2318 additions & 805 deletions
Large diffs are not rendered by default.

index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11

22
import { NativeModules } from 'react-native';
33

4+
export const ACCESSIBLE = {
5+
WHEN_UNLOCKED: 'AccessibleWhenUnlocked',
6+
AFTER_FIRST_UNLOCK: 'AccessibleAfterFirstUnlock',
7+
ALWAYS: 'AccessibleAlways',
8+
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY: 'AccessibleWhenPasscodeSetThisDeviceOnly',
9+
WHEN_UNLOCKED_THIS_DEVICE_ONLY: 'AccessibleWhenUnlockedThisDeviceOnly',
10+
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY:
11+
'AccessibleAfterFirstUnlockThisDeviceOnly',
12+
ALWAYS_THIS_DEVICE_ONLY: 'AccessibleAlwaysThisDeviceOnly',
13+
};
14+
415
const { RNSecureKeyStore } = NativeModules;
516

617
export default RNSecureKeyStore;

ios/RNSecureKeyStore.m

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ - (NSString *)searchKeychainCopyMatching:(NSString *)identifier {
5252
return value;
5353
}
5454

55-
- (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier {
55+
- (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier options: (NSDictionary * __nullable)options {
56+
CFStringRef accessible = accessibleValue(options);
5657
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
5758

5859
NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
5960
[dictionary setObject:valueData forKey:(id)kSecValueData];
60-
61+
dictionary[(__bridge NSString *)kSecAttrAccessible] = (__bridge id)accessible;
62+
6163
OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
6264

6365
if (status == errSecSuccess) {
@@ -66,13 +68,14 @@ - (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifi
6668
return NO;
6769
}
6870

69-
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
71+
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier options:(NSDictionary * __nullable)options {
7072

73+
CFStringRef accessible = accessibleValue(options);
7174
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
7275
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
7376
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
7477
[updateDictionary setObject:passwordData forKey:(id)kSecValueData];
75-
78+
updateDictionary[(__bridge NSString *)kSecAttrAccessible] = (__bridge id)accessible;
7679
OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,
7780
(CFDictionaryRef)updateDictionary);
7881

@@ -119,17 +122,18 @@ - (void)handleAppUninstallation
119122
return error;
120123
}
121124

122-
RCT_EXPORT_METHOD(set:(NSString *)key value:(NSString *)value
125+
RCT_EXPORT_METHOD(set: (NSString *)key value:(NSString *)value
126+
options: (NSDictionary *)options
123127
resolver:(RCTPromiseResolveBlock)resolve
124128
rejecter:(RCTPromiseRejectBlock)reject)
125129
{
126130
@try {
127131
[self handleAppUninstallation];
128-
BOOL status = [self createKeychainValue: value forIdentifier: key];
132+
BOOL status = [self createKeychainValue: value forIdentifier: key options: options];
129133
if (status) {
130134
resolve(@"key stored successfully");
131135
} else {
132-
BOOL status = [self updateKeychainValue: value forIdentifier: key];
136+
BOOL status = [self updateKeychainValue: value forIdentifier: key options: options];
133137
if (status) {
134138
resolve(@"key updated successfully");
135139
} else {
@@ -183,4 +187,24 @@ - (void)handleAppUninstallation
183187
}
184188
}
185189

190+
CFStringRef accessibleValue(NSDictionary *options)
191+
{
192+
if (options && options[@"accessible"] != nil) {
193+
NSDictionary *keyMap = @{
194+
@"AccessibleWhenUnlocked": (__bridge NSString *)kSecAttrAccessibleWhenUnlocked,
195+
@"AccessibleAfterFirstUnlock": (__bridge NSString *)kSecAttrAccessibleAfterFirstUnlock,
196+
@"AccessibleAlways": (__bridge NSString *)kSecAttrAccessibleAlways,
197+
@"AccessibleWhenPasscodeSetThisDeviceOnly": (__bridge NSString *)kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
198+
@"AccessibleWhenUnlockedThisDeviceOnly": (__bridge NSString *)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
199+
@"AccessibleAfterFirstUnlockThisDeviceOnly": (__bridge NSString *)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
200+
@"AccessibleAlwaysThisDeviceOnly": (__bridge NSString *)kSecAttrAccessibleAlwaysThisDeviceOnly
201+
};
202+
NSString *result = keyMap[options[@"accessible"]];
203+
if (result) {
204+
return (__bridge CFStringRef)result;
205+
}
206+
}
207+
return kSecAttrAccessibleAfterFirstUnlock;
208+
}
209+
186210
@end

package.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-secure-key-store",
3-
"version": "1.0.9",
3+
"version": "2.0.0",
44
"description": "React Native Library for securely storing keys to iOS and Android devices in KeyChain and KeyStore respectively.",
55
"main": "index.js",
66
"scripts": {
@@ -21,13 +21,10 @@
2121
},
2222
"repository": {
2323
"type": "git",
24-
"url":
25-
"git+https://github.com/pradeep1991singh/react-native-secure-key-store.git"
24+
"url": "git+https://github.com/pradeep1991singh/react-native-secure-key-store.git"
2625
},
2726
"bugs": {
28-
"url":
29-
"https://github.com/pradeep1991singh/react-native-secure-key-store/issues"
27+
"url": "https://github.com/pradeep1991singh/react-native-secure-key-store/issues"
3028
},
31-
"homepage":
32-
"https://github.com/pradeep1991singh/react-native-secure-key-store#readme"
29+
"homepage": "https://github.com/pradeep1991singh/react-native-secure-key-store#readme"
3330
}

0 commit comments

Comments
 (0)