Keychain accessor

Below is some code that I wrote for saving, retrieving and deleting data entries for the iOS keychain.

@interface WBKeyChainAccessor : NSObject {

}

/**
 Searches iOS keychain for an entry with supplied identifer and returns data if found
 @param identifier supplied identifier
 @return NSData object of found entry (nil if not found)
 */
+ (NSData *) searchForKeyChainCopyMatching:(NSString *)identifier;

/**
 Creates iOS keychain entry with data and identifier
 @param dataObject data to be stored in iOS keychain
 @param identifier supplied identifer used as a key to retrieve and save data to iOS keychain
 @return Success indicator
 */
+ (BOOL) createKeyChainValue:(NSData *)dataObject forIdentifier:(NSString *)identifier;

/**
 Updates iOS keychain entry with data and identifier
 @param dataObject data to be stored in iOS keychain
 @param identifier supplied identifer used as a key to retrieve and save data to iOS keychain
 @return Success indicator
 */
+ (BOOL) updateKeychainValue:(NSData *)dataObject forIdentifier:(NSString *)identifier;

/**
 Deletes iOS keychain entry
 @param identifier supplied identifier used to search iOS keychain
 */
+ (void) deleteKeychainValue:(NSString *)identifier;

/**
 Searches iOS keychain for an entry with supplied identifer
 @param identifier supplied identifier
 @return Success indicator as to whether the entry exists in the keychain
 */
+ (BOOL) doesKeyChainEntryExistForIdentifier:(NSString *)identifier;

@end
#import "WBKeyChainAccessor.h"
#import <Security/Security.h>

@interface WBKeyChainAccessor (Private)

+ (NSMutableDictionary *) newSearchDictionary: (NSString *)identifier;

@end

@implementation WBKeyChainAccessor

static NSString * const SERVICE = @"com.springtiger.WBKeyChainAccessor";

#pragma mark - Retrieval

+ (NSMutableDictionary *) newSearchDictionary: (NSString *)identifier
{
    NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];

    [searchDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

    NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
    [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrGeneric];
    [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrAccount];
    [searchDictionary setObject:SERVICE forKey:(id)kSecAttrService];

    return searchDictionary;
}

+ (NSData *) searchForKeyChainCopyMatching:(NSString *)identifier
{
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];

    [searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];

    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

    NSData *result = nil;

    OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary, (CFTypeRef *)&result);

    [searchDictionary release];

    if (status == errSecSuccess) {
        return result;
    }

    return nil;

}

+ (BOOL) doesKeyChainEntryExistForIdentifier:(NSString *)identifier
{
    if ([self searchForKeyChainCopyMatching:identifier] != nil) {
        return YES;
    }else{
        return NO;
    }
}

#pragma mark - Creation

+ (BOOL) createKeyChainValue:(NSData *)dataObject forIdentifier:(NSString *)identifier
{
    NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];

    [dictionary setObject:dataObject forKey:(id)kSecValueData];

    OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
    [dictionary release];

    if(status == errSecSuccess){
        return YES;
    }

    return NO;

}

#pragma mark - Updating

+ (BOOL) updateKeychainValue:(NSData *)dataObject forIdentifier:(NSString *)identifier
{

    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
    NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];

    [updateDictionary setObject:dataObject forKey:(id)kSecValueData];

    OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary, (CFDictionaryRef)updateDictionary);

    [searchDictionary release];
    [updateDictionary release];

    if (status == errSecSuccess) {
        return YES;
    }else{

       return [self createKeyChainValue:dataObject forIdentifier:identifier];
    }
}

#pragma mark - Deletion

+ (void) deleteKeychainValue:(NSString *)identifier
{
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
    SecItemDelete((CFDictionaryRef)searchDictionary);
    [searchDictionary release];

}

@end