magic_9527
magic_9527

Reputation: 295

Couldn't add the Keychain Item. Error - 25299 after change the identifier with KeychainItemWrapper?

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

Answers (2)

Jake
Jake

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

swift-lynx
swift-lynx

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

Related Questions