Save an Identity into app group Keychain

Hello everyone,

I am trying to save an identity into a group keychain. I am doing it this way, following the documentation:

Code Block
let queryAdd: [String: AnyObject] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: kSecImportItemIdentity as AnyObject,
kSecValueData as String: identity as SecIdentity,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked,
kSecAttrAccessGroup as String: accessGroup as AnyObject
]
let resultCode = SecItemAdd(queryAdd as CFDictionary, nil)
if resultCode != noErr {
print("Error saving to Keychain: \(resultCode)")
}

I am getting error (or resultCode) -50, which means password has not been save successfully.

As a no-team programmer, my accessGroup it's just the group Bundle identifier, registered in Signing & Capabilities -> Keychain Sharing. I don't know if maybe the reason of this code is because the group is not alright or something else it's happening, although it looks I am using the identity the right way.
I'll start off by saying that storing an identity in the Keychain can be challenging. Quinn should weigh in here with the finer points, but one of the reasons this is difficult is because the identity is split into 2 assets and saved separately. This is why saving with kSecAttrAccessGroup can be challenging. Moreover, updating can also be challenging because the certificate inside your identity has a unique contraint on it and if this that fails because of a duplicate then this will also prevent the save.

When encountering this, one thing to try would be to move to using very generic like:

Code Block
let indetityStatus = SecItemAdd([
kSecClass: kSecClassIdentity,
kSecValueRef: secIdentity
] as CFDictionary, nil)


And see where that gets you. And try building from that. You could also passing in a CFTypeRef instead of nil to save a reference to the added result as well. This is just a high level of where to start.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
You’re way off in the weeds, alas. An item class of kSecClassGenericPassword is for saving… well… passwords. Digital identities are not passwords. Rather, you should be using an item class of kSecClassIdentity.

However, that doesn’t really make sense in this context because, as Matt mentioned, identities are a compound object, made up of a certificate and a private key that matches the public key in that certificate. Generally you work with an identity via its ‘ref’ object, a SecIdentity in Swift. In that case you don’t need to set kSecClass because it’s implied by that object. Instead you just pass in the ref object using kSecValueRef. For example:

Code Block
let identity: SecIdentity = …
let err = SecItemAdd([
kSecValueRef: identity,
] as NSDictionary, nil)


I recommend that you try this first, and then move on to setting putting it in a shared keychain access group using kSecAttrAccessGroup.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Save an Identity into app group Keychain
 
 
Q