Permalink
Browse files

Merge pull request #9 from erikr/master

Add support for using a custom kSecAttrAccessible for all setter methods.
  • Loading branch information...
2 parents 178ae71 + 84ec4bd commit 10c1665c61accc3583f717e5ffb02f14f212cf36 @granoff committed Jan 19, 2013
Showing with 29 additions and 4 deletions.
  1. +3 −0 Lockbox.h
  2. +21 −4 Lockbox.m
  3. +5 −0 README.md
View
@@ -8,12 +8,15 @@
@interface Lockbox : NSObject
+(BOOL)setString:(NSString *)value forKey:(NSString *)key;
++(BOOL)setString:(NSString *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility;
+(NSString *)stringForKey:(NSString *)key;
+(BOOL)setArray:(NSArray *)value forKey:(NSString *)key;
++(BOOL)setArray:(NSArray *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility;
+(NSArray *)arrayForKey:(NSString *)key;
+(BOOL)setSet:(NSSet *)value forKey:(NSString *)key;
++(BOOL)setSet:(NSSet *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility;
+(NSSet *)setForKey:(NSString *)key;
@end
View
@@ -9,6 +9,7 @@
#import <Security/Security.h>
#define kDelimeter @"-|-"
+#define DEFAULT_ACCESSIBILITY kSecAttrAccessibleWhenUnlocked
#if __has_feature(objc_arc)
#define ID __bridge id
@@ -51,7 +52,7 @@ +(NSString *)_hierarchicalKey:(NSString *)key
return [_bundleId stringByAppendingFormat:@".%@", key];
}
-+(BOOL)setObject:(NSString *)obj forKey:(NSString *)key
++(BOOL)setObject:(NSString *)obj forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
{
OSStatus status;
@@ -71,6 +72,7 @@ +(BOOL)setObject:(NSString *)obj forKey:(NSString *)key
NSMutableDictionary *dict = [self _service];
[dict setObject: hierKey forKey: (ID) kSecAttrService];
+ [dict setObject: accessibility forKey: (ID) kSecAttrAccessible];
[dict setObject: [obj dataUsingEncoding:NSUTF8StringEncoding] forKey: (ID) kSecValueData];
#if __has_feature(objc_arc)
@@ -138,7 +140,12 @@ +(NSString *)objectForKey:(NSString *)key
+(BOOL)setString:(NSString *)value forKey:(NSString *)key
{
- return [self setObject:value forKey:key];
+ return [self setString:value forKey:key accessibility:DEFAULT_ACCESSIBILITY];
+}
+
++(BOOL)setString:(NSString *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
+{
+ return [self setObject:value forKey:key accessibility:accessibility];
}
+(NSString *)stringForKey:(NSString *)key
@@ -148,8 +155,13 @@ +(NSString *)stringForKey:(NSString *)key
+(BOOL)setArray:(NSArray *)value forKey:(NSString *)key
{
+ return [self setArray:value forKey:key accessibility:DEFAULT_ACCESSIBILITY];
+}
+
++(BOOL)setArray:(NSArray *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
+{
NSString *components = [value componentsJoinedByString:kDelimeter];
- return [self setObject:components forKey:key];
+ return [self setObject:components forKey:key accessibility:accessibility];
}
+(NSArray *)arrayForKey:(NSString *)key
@@ -164,7 +176,12 @@ +(NSArray *)arrayForKey:(NSString *)key
+(BOOL)setSet:(NSSet *)value forKey:(NSString *)key
{
- return [self setArray:[value allObjects] forKey:key];
+ return [self setSet:value forKey:key accessibility:DEFAULT_ACCESSIBILITY];
+}
+
++(BOOL)setSet:(NSSet *)value forKey:(NSString *)key accessibility:(CFTypeRef)accessibility
+{
+ return [self setArray:[value allObjects] forKey:key accessibility:accessibility];
}
+(NSSet *)setForKey:(NSString *)key
View
@@ -24,10 +24,13 @@ One caveat here is that the keychain is really not meant to store large chunks o
There are three pairs of methods, but method pairs for other container classes would not be hard to implement:
+ `+setString:forKey:`
++ `+setString:forKey:accessibility:`
+ `+stringForKey:`
+ `+setArray:forKey:`
++ `+setArray:forKey:accessibility:`
+ `+arrayForKey:`
+ `+setSet:forKey:`
++ `+setSet:forKey:accessibility:`
+ `+setForKey:`
All the `setXxx` methods return `BOOL`, indicating if the keychain operation succeeded or failed. The `xxxForKey` methods return a non-`nil` value on success, or `nil` on failure.
@@ -36,6 +39,8 @@ The `setXxx` methods will overwrite values for keys that already exist in the ke
In all the methods you can use a simple key name, like "MyKey", but know that under the hood Lockbox is prefixing that key with your apps bundle id. So the actual key used to store and retrieve the data looks more like "com.mycompany.myapp.MyKey". This ensures that your app, and only your app, has access to your data.
+The methods with a `accessibility` argument take a [Keychain Item Accessibility Constant](http://developer.apple.com/library/ios/#DOCUMENTATION/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH4g-SW318). You can use this to control the when your keychain item should be readable. For example, passing `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` will make it accessible only while the device is unlocked, and will not migrate this item to a new device or installation. The methods without a specific `accessibility` will use `kSecAttrAccessibleWhenUnlocked`, the default in recent iOS versions.
+
## Requirements
To use this class you will need to add the `Security` framework to your project.

0 comments on commit 10c1665

Please sign in to comment.