Created
June 9, 2012 10:31
-
-
Save stattrak-dragonlore/2900466 to your computer and use it in GitHub Desktop.
Keychain wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Keychain.h | |
// OpenStack | |
// | |
// Based on KeychainWrapper in BadassVNC by Dylan Barrie | |
// | |
// Created by Mike Mayo on 10/1/10. | |
// The OpenStack project is provided under the Apache 2.0 license. | |
// | |
// http://overhrd.com/?p=208 | |
// https://raw.github.com/rackspace/rackspace-ios/master/Classes/Keychain.h | |
// | |
#import <Foundation/Foundation.h> | |
// This wrapper helps us deal with Keychain-related things | |
// such as storing API keys and passwords | |
@interface Keychain : NSObject { | |
} | |
+ (BOOL)setString:(NSString *)string forKey:(NSString *)key; | |
+ (NSString *)getStringForKey:(NSString *)key; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Keychain.m | |
// OpenStack | |
// | |
// Based on KeychainWrapper in BadassVNC by Dylan Barrie | |
// | |
// Created by Mike Mayo on 10/1/10. | |
// The OpenStack project is provided under the Apache 2.0 license. | |
// | |
// http://overhrd.com/?p=208 | |
// https://raw.github.com/rackspace/rackspace-ios/master/Classes/Keychain.m | |
// | |
// Modified by Zhiping Deng (ARC compatible) | |
// http://stackoverflow.com/questions/7941986/ios-5-0-keychain-access | |
#import "Keychain.h" | |
#import <Security/Security.h> | |
@implementation Keychain | |
+ (NSString *)appName { | |
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; | |
// Attempt to find a name for this application | |
NSString *appName = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; | |
if (!appName) { | |
appName = [bundle objectForInfoDictionaryKey:@"CFBundleName"]; | |
} | |
return appName; | |
} | |
+ (BOOL)setString:(NSString *)string forKey:(NSString *)key { | |
if (string == nil || key == nil) { | |
return NO; | |
} | |
key = [NSString stringWithFormat:@"%@ - %@", [Keychain appName], key]; | |
// First check if it already exists, by creating a search dictionary and requesting that | |
// nothing be returned, and performing the search anyway. | |
NSMutableDictionary *existsQueryDictionary = [NSMutableDictionary dictionary]; | |
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; | |
[existsQueryDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; | |
// Add the keys to the search dict | |
[existsQueryDictionary setObject:@"service" forKey:(__bridge id)kSecAttrService]; | |
[existsQueryDictionary setObject:key forKey:(__bridge id)kSecAttrAccount]; | |
OSStatus res = SecItemCopyMatching((__bridge CFDictionaryRef)existsQueryDictionary, NULL); | |
if (res == errSecItemNotFound) { | |
if (string != nil) { | |
NSMutableDictionary *addDict = existsQueryDictionary; | |
[addDict setObject:data forKey:(__bridge id)kSecValueData]; | |
res = SecItemAdd((__bridge CFDictionaryRef)addDict, NULL); | |
NSAssert1(res == errSecSuccess, @"Recieved %d from SecItemAdd!", res); | |
} | |
} else if (res == errSecSuccess) { | |
// Modify an existing one | |
// Actually pull it now of the keychain at this point. | |
NSDictionary *attributeDict = [NSDictionary dictionaryWithObject:data forKey:(__bridge id)kSecValueData]; | |
res = SecItemUpdate((__bridge CFDictionaryRef)existsQueryDictionary, (__bridge CFDictionaryRef)attributeDict); | |
NSAssert1(res == errSecSuccess, @"SecItemUpdated returned %d!", res); | |
} else { | |
NSAssert1(NO, @"Received %d from SecItemCopyMatching!", res); | |
} | |
return YES; | |
} | |
+ (NSString *)getStringForKey:(NSString *)key { | |
key = [NSString stringWithFormat:@"%@ - %@", [Keychain appName], key]; | |
NSMutableDictionary *existsQueryDictionary = [NSMutableDictionary dictionary]; | |
[existsQueryDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; | |
// Add the keys to the search dict | |
[existsQueryDictionary setObject:@"service" forKey:(__bridge id)kSecAttrService]; | |
[existsQueryDictionary setObject:key forKey:(__bridge id)kSecAttrAccount]; | |
// We want the data back! | |
CFDataRef data = NULL; | |
[existsQueryDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; | |
OSStatus res = SecItemCopyMatching((__bridge CFDictionaryRef)existsQueryDictionary, (CFTypeRef *)&data); | |
if (res == errSecSuccess) { | |
NSString *string = [[NSString alloc] initWithBytes:[(__bridge NSData *)data bytes] length:[(__bridge NSData *)data length] encoding:NSUTF8StringEncoding]; | |
return string; | |
} else { | |
NSAssert1(res == errSecItemNotFound, @"SecItemCopyMatching returned %d!", res); | |
} | |
return nil; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment