goal
I need to store the client ID in an OS X application in a safe way so that only my application can access it. Do not request permission.
Problem
The problem arose immediately when I tried to store the client ID. Here is a sample code (which I attached to):
- (BOOL)saveClientIdentity:(SecIdentityRef)clientIdentity error:(NSError**) error { NSDictionary *attributes = @{ (__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, (__bridge id)kSecValueRef:(__bridge id)clientIdentity, (__bridge id)kSecAttrApplicationTag:[kMyKeychainAttrApplicationTag dataUsingEncoding: NSUTF8StringEncoding], (__bridge id)kSecAttrAccessGroup:kMyKeychainAttrAccessGroup }; OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
I constantly get the code -25299 and the tool fixes the problem:
$ security error -25299 Error: 0xFFFF9D2D -25299 The specified item already exists in the keychain.
Therefore, it is trying to override the global client identifier (I have never deleted the client identifier for this application, so there should not be such a conflict), and I do not do this. It should be closed only for this application.
I checked what happens for the corresponding download code. It loads my developer id, and I don't want this.
- (SecIdentityRef)clientIdentity { NSDictionary *attributes = @{ (__bridge id)kSecClass:(__bridge id)kSecClassIdentity, (__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly, (__bridge id)kSecAttrApplicationTag:[kMyKeychainAttrApplicationTag dataUsingEncoding: NSUTF8StringEncoding], (__bridge id)kSecAttrAccessGroup:kMyKeychainAttrAccessGroup }; CFTypeRef universalResult = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attributes, &universalResult); SecIdentityRef result = (SecIdentityRef)universalResult; if (result) { CFAutorelease(result); } if (status != noErr) { NSLog(@"Failed to load client identity: %@", NSErrorFromStatusErrorCode(status)); } return result; }
Notes
I need to use the same code for iOS, but there should not be a problem here, since by default the iOS keychain is not used between applications.