Cocoa:将一个项目添加到自定义OS X钥匙串,以便任何其他应用程序可以在没有提示的情况下访问它

时间:2014-05-29 14:31:01

标签: objective-c macos cocoa keychain

我创建了一个自定义钥匙串,然后我用这样的方式在其中保存了一个密码:

SecKeychainRef someKeychain; //keychain reference
SecKeychainItemRef someItem; //keychain key item reference

SecKeychainCreate([keychainPath UTF8String], (UInt32)strlen(keychainPass), keychainPass, FALSE, NULL, &someKeychain);
SecKeychainAddGenericPassword(someKeychain, (UInt32)strlen(someServiceName), someServiceName, (UInt32)strlen(someAccountName), someAccountName, (UInt32)strlen(encryptedPass), encryptedPass, &someItem);

我现在要做的是让任何知道someItem的应用程序都可以访问添加的keychainPass,而不会提示用户允许。所以我这样试了:

SecACLRef aclList;
SecAccessRef itemAccessRef;
uid_t userid = 0;
gid_t groupid;
CFArrayRef aclListArr;
SecACLRef newAcl;

SecKeychainItemCopyAccess(someItem, &itemAccessRef);
SecAccessCopyOwnerAndACL(itemAccessRef, &userid, &groupid, (UInt32*)kSecUseOnlyUID, &aclListArr);

SecACLCreateWithSimpleContents(itemAccessRef, NULL, (__bridge CFStringRef)@"someTagName", kSecKeychainPromptInvalid, &newAcl);

但是:

  1. 我不知道函数SecACLCreateWithSimpleContents是否是实现此目的的正确方法
  2. 如果是,我不知道如何将用它创建的ACLlist写回someItem
  3. 我不知道如何使用它返回的这些CFArrays(我是一个目标-c初学者)
  4. 我知道这是必要的,因为当我将新创建的钥匙串导入Keychain Access OS X应用程序并且我将someItem的属性标记为任何应用程序都可以访问时,提示消失了一切正常。我不知道的是如何以编程方式实现这一目标。我意识到这可能是一个愚蠢的问题,但我不知道该怎么做。

3 个答案:

答案 0 :(得分:0)

我来自iOS,但根据参考文档,它应该大致相同。

您需要将SecItemAdd与选项[kSecAttrAccessGroup)(https://developer.apple.com/library/mac/documentation/security/Reference/keychainservices/Reference/reference.html#//apple_ref/c/data/kSecAttrAccessGroup)一起使用。请查看SecItemAdd

的参考文档

这里有一个post,其中有一些关于如何使用SecItemAdd的示例代码。

答案 1 :(得分:0)

您需要做的是为项目和钥匙串设置访问控制列表

以下是创建访问参考的代码

#pragma mark - Keychain Access Methods

+ (SecAccessRef)createAccess:(NSString *)accessLabel
{
    OSStatus err;
    SecAccessRef access = nil;
    NSArray *trustedApplications = nil;

    SecTrustedApplicationRef myself;
    err = SecTrustedApplicationCreateFromPath(NULL, &myself);

    if (err)
        return nil;

    trustedApplications = [NSArray arrayWithObjects:(__bridge id)myself, nil];
    err = SecAccessCreate((__bridge CFStringRef)accessLabel,(__bridge CFArrayRef)trustedApplications, &access);

    if (err)
        return nil;

    return access;
}

您没有指定您的应用程序是否创建了钥匙串,但如果是,您可以在使用此代码创建应用程序时允许您的应用程序。

// Create Keychain
SecKeychainCreate(name, (UInt32)[password length], [password cStringUsingEncoding:NSUTF8StringEncoding], false, [self createAccess:keychainKey], NULL);

这将使您的应用程序可以访问该钥匙串中的任何项目。您还可以在创建单个项目时传入访问控制参考。

答案 2 :(得分:0)

您可以使用接受SecAccessRef参数的较旧的Security API方法,为新的钥匙串项目(在macOS下)实现“允许所有应用程序访问此项目”访问权限:

  • SecKeychainItemCreateFromContent()
  • SecKeyCreatePair() (在OS X 10.7中已弃用,但仍有效)

即:

  • 使用 SecAccessRef SecAccessCreate()
  • 创建SecAccessCreateWithOwnerAndACL()
  • 使用 {{1>使用SecAccessRef授权向Any添加单个ACL条目,不使用提示行为(SecKeychainPromptSelector = 0)和NULL可信应用程序列表}}
  • 使用上述API创建钥匙串项目时传递SecACLCreateWithSimpleContents()

我在这个问题上添加了一个较长的回答(重复?)问题:How to allow all applications to access keychain item without prompt