KeychainWrapperItem stopped working in iOS 7.1 - ios

I recently installed iOS 7.1 simulator and the new Xcode 5.1. My App worked in iOS 7 fine. I'm using the KeychainItemWrapper class from Apple.
After the update it crashed with the following message:
*** Assertion failure in -[KeychainItemWrapper writeToKeychain]
Specifically at line 299:
NSAssert( result == noErr, #"Couldn't update the Keychain Item." );
Error is hear -25300 (errSecItemNotFound)
I have specified the Keychain Access Group in my entitlements file. This error occurred only in the iOS 7.1 Simulator and not on a real iPhone or the 7.0 Simulator.
Does anyone know what changed with Keychain in 7.1 ?

Well KeychainItemWrapper is a old implementation full of bugs. I would recommend using another wrapper, or write your own.
That being said, I used to have many error but not this one. Basically what happens is while saving it checks that your item is already in the keychain, in order to add it or just update it. Here that check returns true even though the item is quite different, so it cannot update because SecItemUpdate believes it does not exist.
What you should do is reset your keychain, you have two options for this :
On the simulator Menu Simulator->Reset content and settings
Run this snippet somewhere in your code :
Based on Vegard answer here Reset An iPhone App's Keychain
-(void)resetKeychain {
[self deleteAllKeysForSecClass:kSecClassGenericPassword];
[self deleteAllKeysForSecClass:kSecClassInternetPassword];
[self deleteAllKeysForSecClass:kSecClassCertificate];
[self deleteAllKeysForSecClass:kSecClassKey];
[self deleteAllKeysForSecClass:kSecClassIdentity];
}
-(void)deleteAllKeysForSecClass:(CFTypeRef)secClass {
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:(__bridge id)secClass forKey:(__bridge id)kSecClass];
OSStatus result = SecItemDelete((__bridge CFDictionaryRef) dict);
NSAssert(result == noErr || result == errSecItemNotFound, #"Error deleting keychain data (%ld)", result);
}

Keychain continues to work under iOS 7.1. Your issue is related to Simulator itself. Simulator does not allow to store certain keys as far as I know, and this is consistent between iOS 7.0 and iOS 7.1.
If you run your app on a real device, the crash will disappear.

Related

iOS 10 Today extension can't read shared user defaults any more

I have an application that implements Today extension. Till iOS10 it was working fine, but now I see that it can't read keys stored in shared NSuserDefaults.
My Host app code:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
[sharedPrefs setObject:username forKey:#"username"];
[sharedPrefs setObject:#"Test" forKey:#"test"];
[sharedPrefs synchronize];
My extension code:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
NSString *str = [sharedPrefs valueForKey:#"test"];
And str var is always nil in extension. I have set up my App Groups in Capabilities for both Host app and extension app, and I have checked it against the settings on Apple developer portal. It is all OK. Can anyone please help, is there something different that I must do?
EDIT
Another thing that I have noticed is that I have a red exclamation mark on: "Add the Add Groups entitlement to your entitlement file", and when I fix the issue, the exclamation mark goes away, but when I close and reopen project it is there again. I have recreated provisional profiles, but still the same issue
It sounds like the issues is that your Entitlements file is missing the relevant line.
To diagnose where the issue is, start with your build settings:
Under Code Signing Entitlements there should be a file listed
Open that file and ensure that it has the App Groups key with the value that matches your kSharedGroupIdentifier
Ensure that the file is not marked read-only (this would potentially cause the "fix" to not work correctly)
Verify that all of the following match:
kSharedGroupIdentifier in both apps
kSharedGroupIdentifier and the value in your entitlements file for App Groups
Next, we can narrow the issue down to the specific key or the entire preferences domain as follows:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
if (sharedPrefs == nil) {
NSLog(#"Error loading shared user defaults!");
}
A nil value indicates that the suite name is invalid.
Rebooting the mac solved the issue for me.
Apple RNotes WWDC Seed: Running multiple iOS simulators can cause NSUserDefaults to not work Running an iOS 8 or 9 simulator followed by an iOS 10 simulator will cause NSUserDefaults to stop working in the simulator. This can be worked around by rebooting the host Mac.
I hope it will helps you,
Thanks.

SAMKeychain setPassword is failing

NSLog(#"SETTING VALUE %#", value);
[SAMKeychain setPassword:value forService:SERVICE_NAME account:key];
NSLog(#"READING VALUE %#", [SAMKeychain passwordForService:SERVICE_NAME account:key]);
I am always getting (null) after setting a value.
This wasn't happening before I updated XCode.
Does anyone has any idea what can be the problem?
The iOS 10 keychain has been buggy since the early beta of iOS 10. As a (hopefully temporary) workaround, enable the Shared Keychain entitlement in your app. This bug affects every keychain wrapper out there, and not only SAMKeychain.

Keychain error -34018, unable to delete current dictionary

I have an app that is written in Swift 2.3. The app uses the KeychainItemWrapper that makes accessing the Keychain simpler.
When I run the app in the iOS 9.3 simulator with Xcode, the app runs as expected and there are no issues reading/writing to the keychain.
The same exact app, without any changes in my code, crashes with the call to:
- (void)resetKeychainItem
With the line:
SecItemDelete((__bridge CFDictionaryRef)tempDictionary);
Thus making this NSAssert give me my error:
NSAssert( junk == noErr || junk == errSecItemNotFound, #"Problem deleting current dictionary." );
Researching this error by the code 34018 pointed me to other posts with users experiencing a bug with the keychain that was actually brought to the attention of the devs at Apple. It was made a high priority bug, and one post suggested iOS 9.3 had a fix for this (my app works on iOS 9.3!).
However, it is my understanding that Xcode 8 handles such things as code signing differently than previous versions. So I wonder if with iOS 10 if this is a possible new bug.
If anyone has any ideas or experience with this error on iOS 10/Xcode 8... please share your suggestions.

Adding keychain sharing to production app that already has users

We have an iOS app that has been released. The IDE is XCode6. I want to add keychain sharing to access the sessionID that exists in the app from an iOS 8 share extension.
Problem is whenever keychain sharing is turned on, the sessionID that already exists can no longer be accessed.
It can be accessed whenever keychain sharing is turned off.
This dictionary is passed into SecItemCopyMatching, which always returns -25300 (not found) whenever keychain sharing is enabled, no matter what the "Keychain Groups:" is.
[0] (null) #"svce" : #"SESSION_ID_KEY"
[1] (null) #"r_Data" : #"1"
[2] (null) #"m_Limit" : #"m_LimitOne"
[3] (null) #"class" : #"genp"
[4] (null) #"acct" : #"SESSION_ID_KEY"
[5] (null) #"pdmn" : #"ck"
Any idea why access to the key might not work? I tried setting kSecAttrAccessGroup with the bundle prefix and name and it still did not work on the simulator.
Hopefully I got your answer and the bounty :)
I had the same issue originally and came across this post, and I know you mentioned you tried with the bundle prefix and name. But let's run through a sanity check.
In the MyApp.entitlements and in MyApp Extension.entitlements I have the Keychain Access Groups set to $(AppIdentifierPrefix)com.company.MyApp (this is the default).
I accessed the value for ABCD1234 (aka AppIdentifierPrefix value) using this SO answer https://stackoverflow.com/a/20340883 however hardcoding may not be best practice here, so consider looking this a solution like this https://stackoverflow.com/a/11841898/2588957
Then note in my app all I added to make my current code to work is the following:
[keychainItem setObject:#"ABCD1234.com.company.MyApp" forKey:(__bridge id)kSecAttrAccessGroup]; before updating the item and I can now access the keychain item in my share extension.
I had a similar issue when implementing inter-app communication in iOS 7 a couple of months ago.
I found this remark on Apple's GenericKeyChain sample project:
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
So if you're testing on a Simulator you need to remove the "kSecAttrAccessGroup".
On a device it should work with this key.

App built with xcode 5 can't read password stored for app build with xcode 4.6.3

My password store doesn't seem to be compatible across different XCode builds.
I'm managing a password with SFHFKeychainUtils. If I build my app with XCode 4.6.3, then do a subsequent build with XCode 5.0, I am getting a (null) back from this call:
NSString *p = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:DEF_SERVICENAME error:&error];
and I stored it using this call:
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:DEF_SERVICENAME updateExisting:YES error:&error];
Has anyone experienced similar issues and have you found a solution for dealing with this? It will be bad if my updated app can't read the stored data from my current app.
This line is getting the exact same dictionary in both builds:
OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult);
I get the following error:
errSecItemNotFound = -25300, /* The specified item could not be found in the keychain. */

Resources