Cannot add synchronizable attribute to keychain

Using KeychainItemWrapper, how (or where) does one add the kSecAttrSynchronizable value to the keychain? Every way I try, results in SecItemAdd returning -25999 (errSecDuplicateItem). I have tried to add:


[keychain setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecAttrSynchronizable];


to the default attributes, at the time password & account are set, to the initWithIdentifier: accessGroup: after SecItemCopyMatching macro.


This can't be so hard to accomplish ....

Accepted Reply

While I can help you with the keychain API itself, I’m not familiar with KeychainItemWrapper so you’ll have to dig into that code to understand how it’s using the various SecItem calls.

In my experience the most common mistake made by folks dealing with the SecItem API is that they fail to understand which attributes contribute to uniqueness within a particular keychain item class. You can find that info in this old DevForums post.

IMPORTANT That post was created before

kSecAttrSynchronizable
existed; it should be included in all of those lists.

This is particularly tricky because some SecItem APIs take a query (

SecItemCopyMatching
,
SecItemDelete
), some take an attribute set (
SecItemAdd
), and some take both (
SecItemUpdate
). If you take the attribute set you intend to pass to
SecItemAdd
and pass it as a query to
SecItemCopyMatching
, you can get very confused.

You might want to read the following posts, where I dug into two examples of this confusion:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

It sounds like you have an existing item in the keychain that you want to change. Is that right? If so, you need to look at

SecItemUpdate
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

No, I want to set the key when the item is created.


KeychainItemWrapper (ARCified version from GITHub) works great to create a keychain item with password (data), account, comment and access group. I can see several other keys being automatically added. However, whenever and whereever I try to add the kSecAttrSynchronizable key, arriving in the writeToKeychain method, SecItemCopyMatching apparently no longer returns noErr.

While I can help you with the keychain API itself, I’m not familiar with KeychainItemWrapper so you’ll have to dig into that code to understand how it’s using the various SecItem calls.

In my experience the most common mistake made by folks dealing with the SecItem API is that they fail to understand which attributes contribute to uniqueness within a particular keychain item class. You can find that info in this old DevForums post.

IMPORTANT That post was created before

kSecAttrSynchronizable
existed; it should be included in all of those lists.

This is particularly tricky because some SecItem APIs take a query (

SecItemCopyMatching
,
SecItemDelete
), some take an attribute set (
SecItemAdd
), and some take both (
SecItemUpdate
). If you take the attribute set you intend to pass to
SecItemAdd
and pass it as a query to
SecItemCopyMatching
, you can get very confused.

You might want to read the following posts, where I dug into two examples of this confusion:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"