Skip to content

Instantly share code, notes, and snippets.

@stattrak-dragonlore
Created June 9, 2012 10:31
Show Gist options
  • Save stattrak-dragonlore/2900466 to your computer and use it in GitHub Desktop.
Save stattrak-dragonlore/2900466 to your computer and use it in GitHub Desktop.
Keychain wrapper
//
// 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
//
// 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