diff --git a/SSKeychain/SSKeychain.h b/SSKeychain/SSKeychain.h index 94fa0d0..d80949c 100644 --- a/SSKeychain/SSKeychain.h +++ b/SSKeychain/SSKeychain.h @@ -22,32 +22,32 @@ typedef NS_ENUM(OSStatus, SSKeychainErrorCode) { extern NSString *const kSSKeychainErrorDomain; /** Account name. */ -extern NSString *const kSSKeychainAccountKey; +extern NSString *kSSKeychainAccountKey; /** Time the item was created. The value will be a string. */ -extern NSString *const kSSKeychainCreatedAtKey; +extern NSString *kSSKeychainCreationDateKey; /** Item class. */ -extern NSString *const kSSKeychainClassKey; +extern NSString *kSSKeychainClassKey; /** Item description. */ -extern NSString *const kSSKeychainDescriptionKey; +extern NSString *kSSKeychainDescriptionKey; /** Item label. */ -extern NSString *const kSSKeychainLabelKey; +extern NSString *kSSKeychainLabelKey; /** Time the item was last modified. The value will be a string. */ -extern NSString *const kSSKeychainLastModifiedKey; +extern NSString *kSSKeychainModificationDateKey; /** Where the item was created. */ -extern NSString *const kSSKeychainWhereKey; +extern NSString *kSSKeychainServiceKey; /** Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system diff --git a/SSKeychain/SSKeychain.m b/SSKeychain/SSKeychain.m index 36337ba..e8c341c 100644 --- a/SSKeychain/SSKeychain.m +++ b/SSKeychain/SSKeychain.m @@ -9,13 +9,13 @@ #import "SSKeychain.h" NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain"; -NSString *const kSSKeychainAccountKey = @"acct"; -NSString *const kSSKeychainCreatedAtKey = @"cdat"; -NSString *const kSSKeychainClassKey = @"labl"; -NSString *const kSSKeychainDescriptionKey = @"desc"; -NSString *const kSSKeychainLabelKey = @"labl"; -NSString *const kSSKeychainLastModifiedKey = @"mdat"; -NSString *const kSSKeychainWhereKey = @"svce"; +NSString *kSSKeychainAccountKey; +NSString *kSSKeychainCreationDateKey; +NSString *kSSKeychainClassKey; +NSString *kSSKeychainDescriptionKey; +NSString *kSSKeychainLabelKey; +NSString *kSSKeychainModificationDateKey; +NSString *kSSKeychainServiceKey; #if __IPHONE_4_0 && TARGET_OS_IPHONE static CFTypeRef SSKeychainAccessibilityType = NULL; @@ -23,6 +23,17 @@ @implementation SSKeychain ++ (void)load { + kSSKeychainAccountKey = (__bridge id)kSecAttrAccount; + kSSKeychainCreationDateKey = (__bridge id)kSecAttrCreationDate; + kSSKeychainClassKey = (__bridge id)kSecClass; + kSSKeychainDescriptionKey = (__bridge id)kSecAttrDescription; + kSSKeychainLabelKey = (__bridge id)kSecAttrLabel; + kSSKeychainModificationDateKey = (__bridge id)kSecAttrModificationDate; + kSSKeychainServiceKey = (__bridge id)kSecAttrService; +} + + + (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account { return [self passwordForService:serviceName account:account error:nil]; } diff --git a/SSKeychain/SSKeychainQuery.m b/SSKeychain/SSKeychainQuery.m index b93c620..8b68417 100644 --- a/SSKeychain/SSKeychainQuery.m +++ b/SSKeychain/SSKeychainQuery.m @@ -35,20 +35,30 @@ - (BOOL)save:(NSError *__autoreleasing *)error { return NO; } - [self deleteItem:nil]; - NSMutableDictionary *query = [self query]; - [query setObject:self.passwordData forKey:(__bridge id)kSecValueData]; + [query setObject:@YES forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + + NSMutableDictionary *updates = [NSMutableDictionary dictionaryWithCapacity:2]; + [updates setObject:self.passwordData forKey:(__bridge id)kSecValueData]; if (self.label) { - [query setObject:self.label forKey:(__bridge id)kSecAttrLabel]; + [updates setObject:self.label forKey:(__bridge id)kSecAttrLabel]; } + #if __IPHONE_4_0 && TARGET_OS_IPHONE CFTypeRef accessibilityType = [SSKeychain accessibilityType]; if (accessibilityType) { - [query setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; + [updates setObject:(__bridge id)accessibilityType forKey:(__bridge id)kSecAttrAccessible]; } #endif - status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + + status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); + if (status == errSecSuccess) { + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)updates); + } else if (status == errSecItemNotFound) { + [query addEntriesFromDictionary:updates]; + status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); + } if (status != errSecSuccess && error != NULL) { *error = [[self class] errorWithCode:status]; @@ -207,12 +217,12 @@ - (NSMutableDictionary *)query { break; } case SSKeychainQuerySynchronizationModeAny: { - value = (__bridge id)(kSecAttrSynchronizableAny); + value = (__bridge id)kSecAttrSynchronizableAny; break; } } - [dictionary setObject:value forKey:(__bridge id)(kSecAttrSynchronizable)]; + [dictionary setObject:value forKey:(__bridge id)kSecAttrSynchronizable]; } #endif