Apple keychain store client identity, damit nur meine Anwendung darauf zugreifen kann

Zie

Ich muss die Client-Identität in einer OS X-Anwendung auf sichere Weise so speichern, dass nur meine Anwendung darauf zugreifen kann. Keine Aufforderung, nach Berechtigungen zu fragen.

Proble

Problem wurde sofort angezeigt, als ich versuchte, die Client-Identität zu speichern. Hier ist ein Codebeispiel (was ich bisher gebunden habe):

- (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);
    // status == -25299
    …
}

Ich bekomme ständig Code -25299 und Tool Expalint das Problem:

$ security error -25299
Error: 0xFFFF9D2D -25299 The specified item already exists in the keychain.

So versucht es, die globale Clientidentität zu überschreiben (ich habe nie eine Clientidentität für diese Anwendung geschrieben, daher sollte es keinen solchen Konflikt geben) und ich weiß nicht, was ich tun soll. Es muss nur für diese Anwendung privat sein.

Ich habe überprüft, was für den jeweiligen Ladecode passiert. Es lädt meine Entwickleridentität und ich möchte das nicht.

- (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;
}
Anmerkunge

Ich muss denselben Code für iOS verwenden, aber dies sollte kein Problem sein, da der iOS-Schlüsselbund standardmäßig nicht von Anwendungen gemeinsam genutzt wird.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage