Updating key fails in simulator with ios 7.1B5 (works fine on device)
Opened this issue · 3 comments
Don't think this is an FXKeyChain issue but for info - updating a key fails with a -25300 error (errSecItemNotFound).
Sample code (as per radar which is a cut down version of FXKeyChain attached below)
/// ---------------------------------------------------------
//
// ViewController.m
// KeychainBugSample
//
// Created by Andy Qua on 12/02/2014.
// Copyright (c) 2014 Andy Qua. All rights reserved.
//
#import "ViewController.h"
/*******
* Sample demonstrating a bug with updating a value stored in the KeyChain.
* When running on Simulator this fails with a -25300 error (errSecItemNotFound)
* But works fine when running on device
*
* Note this is simplified keychain code and assumes that you will be saving and retrieving an NSString value
*******/
@interface ViewController ()
{
NSString *service;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
service = @"test";
NSString *key = @"MyKey";
NSString *text;
// Key shouldn't exist
text = [self stringForKey:key];
NSLog( @"Before add - value stored - [%@]", text );
// Set value
[self addString:@"Test" forKey:key];
// Make sure that value has been set correctly
text = [self stringForKey:key];
NSLog( @"After initial add - value stored - [%@]", text );
// Now Update the value - This will log error -25300 (keyNotFound)
[self updateString:@"This has changed" forKey:key];
// Make sure that value has been set correctly
text = [self stringForKey:key];
NSLog( @"After update value - [%@]", text );
// Clear outs data from keychain for next run
[self deleteDataForKey:key];
text = [self stringForKey:key];
NSLog( @"After delete value - [%@]", text );
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSString *)stringForKey:(id)key
{
//generate query
NSMutableDictionary *query = [NSMutableDictionary dictionary];
if ([service length]) query[(__bridge NSString *)kSecAttrService] = service;
query[(__bridge NSString *)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge NSString *)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
query[(__bridge NSString *)kSecReturnData] = (__bridge id)kCFBooleanTrue;
query[(__bridge NSString *)kSecAttrAccount] = [key description];
//recover data
CFDataRef data = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&data);
if (status != errSecSuccess && status != errSecItemNotFound)
{
NSLog(@"Failed to retrieve data for key '%@', error: %ld", key, (long)status);
}
NSData *dataObj = CFBridgingRelease(data);
NSString *text = [[NSString alloc] initWithData:dataObj encoding:NSUTF8StringEncoding];
return text;
}
- (BOOL) addString:(NSString *)string forKey:(NSString *)key
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *query = [NSMutableDictionary dictionary];
if ([service length]) query[(__bridge NSString *)kSecAttrService] = service;
query[(__bridge NSString *)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge NSString *)kSecAttrAccount] = [key description];
query[(__bridge NSString *)kSecValueData] = data;
OSStatus status = SecItemAdd ((__bridge CFDictionaryRef)query, NULL);
if (status != errSecSuccess)
{
NSLog(@"Failed to add data for key '%@', error: %ld", key, (long)status);
return NO;
}
return YES;
}
- (BOOL) updateString:(NSString *)string forKey:(NSString *)key
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *query = [NSMutableDictionary dictionary];
if ([service length]) query[(__bridge NSString *)kSecAttrService] = service;
query[(__bridge NSString *)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge NSString *)kSecAttrAccount] = [key description];
NSMutableDictionary *update = [@{(__bridge NSString *)kSecValueData: data} mutableCopy];
OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)update);
if (status != errSecSuccess)
{
NSLog(@"Failed to update data for key '%@', error: %ld", key, (long)status);
return NO;
}
return YES;
}
- (BOOL)deleteDataForKey:(id)key
{
//generate query
NSMutableDictionary *query = [NSMutableDictionary dictionary];
if ([service length]) query[(__bridge NSString *)kSecAttrService] = service;
query[(__bridge NSString *)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge NSString *)kSecAttrAccount] = [key description];
//delete existing data
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
if (status != errSecSuccess)
{
NSLog(@"Failed to delete data for key '%@', error: %ld", key, (long)status);
return NO;
}
return YES;
}
@end
/// ---------------------------------------------------------
Would be really awesome if you could add some formatting to that code!
Did you ever get a response from Apple on this? Is the issues still happening?
Hi Nick,
Bug was closed as a dupe but the issue had not been fixed in 7.1 - although haven't yet tested with latest version as worked around the issue for the moment.
Will do soon though
Andy
Sent from my iPhone
On 30 May 2014, at 10:56, Nick Lockwood notifications@github.com wrote:
Did you ever get a response from Apple on this? Is the issues still happening?
—
Reply to this email directly or view it on GitHub.