Reputation: 295
I wanna save UUID in keychain with KeychainItemWrapper, so I add the following methods in MyKeychainManager.m :
#define keychain_idenentify @"com.myapp.bundle1"
+ (void)saveUUID:(NSString *)UUID{
if([MyKeychainManager getUUID].length > 0) {
return;
}
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc]initWithIdentifier:keychain_idenentify accessGroup:nil];
[keychain setObject:UUID forKey:(__bridge id)kSecAttrLabel];
}
+ (NSString *)getUUID {
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc]initWithIdentifier:keychain_idenentify accessGroup:nil];
NSString *uuidString = [keychain objectForKey:(__bridge id)kSecAttrLabel];
return uuidString;
}
But after I change the keychain_idenentify to com.otherApp.bundle, it crashed at
result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL); NSAssert( result == noErr, @"Couldn't add the Keychain Item." );
and the error is Error - 25299
Why is this and how to solve this? Which I should choose such as kSecAttrLabel? I changed it to kSecAttrService it works fun but I don't know is there any other potential bugs.
Any help will be appreciate.
Upvotes: 3
Views: 5934
Reputation: 21
I've spent a lot of days in struggling the same problem. At last , I'v found the cause of it that I pass by too easily.
That is an important constant of keychain. Take a look at the codes. (Assuming that I used keychain in my target for the first time)
KeychainItemWrapper *test1 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test10" accessGroup:nil];
[test1 setObject:(id)@"value1" forKey:(id)kSecValueData];
//Normally it works
KeychainItemWrapper *test2 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test20" accessGroup:nil];
//At this point , we meet the crash with the message of 'Couldn't add the Keychain Item.'
[test2 setObject:(id)@"value2" forKey:(id)kSecValueData];
Even if the name of 'initWithIdentifier' is different , the constant 'kSecAttrAccount' must be unique. Its default value is ""( that is empty). Once keychain wrapper is used , the 'kSecAttrAccount' of it is saved . So you need to pay much attention to the 'kSecAttrAccount' when you use the another 'initWithIdentifier'.
I can fix the crash of above codes by adding some codes.
KeychainItemWrapper *test1 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test10" accessGroup:nil];
[test1 setObject:@"test1" forKey:(id)kSecAttrAccount];
[test1 setObject:(id)@"value1" forKey:(id)kSecValueData];
KeychainItemWrapper *test2 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test20" accessGroup:nil];
[test2 setObject:@"test2" forKey:(id)kSecAttrAccount];
[test2 setObject:(id)@"value2" forKey:(id)kSecValueData];
For more information, if you use the accessGroup of KeychainItemWrapper, as I mention above , the kSecAttrAccount must be unique regardless of using accessGroup or not.
The following is an example.
KeychainItemWrapper *test = [[KeychainItemWrapper alloc] initWithIdentifier:@"test" accessGroup:"App_ID.SampleName"];
As you know , App_ID should be created at the apple developer and SampleName should be setup at the capabilities of KeyChain Sharing of your app target. The '.' between App_ID and SampleName must be added. This is a key point.
Please refer to the postings the other persons uploaded about how to set it.
Upvotes: 2
Reputation: 3765
This error means that an item with this identifier already exists (https://osstatus.com/search/results?platform=all&framework=all&search=-25299). Try deleting it from the keychain and then your code should work.
Upvotes: 5