iOS Keychain Services:只允许kSecAttrGeneric Key的特定值? [英] iOS Keychain Services: only specific values allowed for kSecAttrGeneric Key?

查看:231
本文介绍了iOS Keychain Services:只允许kSecAttrGeneric Key的特定值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用此Apple示例代码中提供的KeychainWrapper类: https ://developer.apple.com/library/content/samplecode/GenericKeychain/

I am trying to use the KeychainWrapper class provided in this Apple sample code: https://developer.apple.com/library/content/samplecode/GenericKeychain/

在示例应用程序中,该类具有此init方法,该方法以:

In the sample app, the class has this init method that starts as:

- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
{
    if (self = [super init])
    {
        // Begin Keychain search setup. The genericPasswordQuery leverages the special user
        // defined attribute kSecAttrGeneric to distinguish itself between other generic Keychain
        // items which may be included by the same application.
        genericPasswordQuery = [[NSMutableDictionary alloc] init];

        [genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
        [genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];

在示例应用程序中,它使用两个值作为标识符字符串。 密码和帐号。在我的代码中实现类时,我使用了一些自定义标识符,但代码不起作用。对SecItemAdd()的调用失败。经过一些测试后,似乎使用密码和帐号以外的值作为标识符不起作用。

In the sample app, it uses two values for the identifier string. "Password" and "Account Number". When implementing the class in my code, I used some custom identifiers and the code did not work. The call to SecItemAdd() failed. After some testing, it seems that using values other than "Password" and "Account Number" for the identifier does not work.

有谁知道允许的值和/或者如果可以为您的钥匙串项目设置自定义标识符?

Does anyone know what values are allowed and/or if it is possible to have custom identifiers for your keychain items?

推荐答案

好的,我在此博客帖子中找到了解决方案< a href =http://useyourloaf.com/blog/2010/4/28/keychain-duplicate-item-when-adding-password.html\"rel =nofollow noreferrer>添加密码时钥匙串重复项

Okay, I found the solution in this blog post Keychain duplicate item when adding password

总结一下,问题是GenericKeychain示例应用程序使用kSecAttrGeneric密钥中存储的值作为keychain项的标识符,而实际上并不是什么API用于确定唯一的钥匙串项。您需要使用唯一值设置的键是kSecAttrAccount键和/或kSecAttrService键。

To sum it up, the issue is that the GenericKeychain sample app uses the value stored in kSecAttrGeneric key as the identifier for the keychain item when in fact that is not what the API uses to determine a unique keychain item. The keys you need to set with unique values are the kSecAttrAccount key and/or the kSecAttrService key.

您可以重写KeychainItemWrapper的启动器,这样您就不需要更改更改这些行的任何其他代码:

You can rewrite the initilizer of KeychainItemWrapper so you don't need to change any other code by changing these lines:

更改:

[genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];

to:

[genericPasswordQuery setObject:identifier forKey:(id)kSecAttrAccount];

并更改:

[keychainItemData setObject:identifier forKey:(id)kSecAttrGeneric];

to:

[keychainItemData setObject:identifier forKey:(id)kSecAttrAccount];

或者,你可以做我做的事情并写一个新的启动器来获取两个识别键:

Or, you could do what I did and write a new initilizer that takes both of the identifying keys:

编辑:对于使用ARC的人(现在应该是你),请查看 nycynik的回答所有正确的桥接符号

For people using ARC (you should be nowadays) check nycynik's answer for all the correct bridging notation

- (id)initWithAccount:(NSString *)account service:(NSString *)service accessGroup:(NSString *) accessGroup;
{
    if (self = [super init])
    {
        NSAssert(account != nil || service != nil, @"Both account and service are nil.  Must specifiy at least one.");
        // Begin Keychain search setup. The genericPasswordQuery the attributes kSecAttrAccount and 
       // kSecAttrService are used as unique identifiers differentiating keychain items from one another
        genericPasswordQuery = [[NSMutableDictionary alloc] init];

        [genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

        [genericPasswordQuery setObject:account forKey:(id)kSecAttrAccount];
        [genericPasswordQuery setObject:service forKey:(id)kSecAttrService];

        // The keychain access group attribute determines if this item can be shared
        // amongst multiple apps whose code signing entitlements contain the same keychain access group.
        if (accessGroup != nil)
        {
#if TARGET_IPHONE_SIMULATOR
            // Ignore the access group if running on the iPhone simulator.
            // 
            // Apps that are built for the simulator aren't signed, so there's no keychain access group
            // for the simulator to check. This means that all apps can see all keychain items when run
            // on the simulator.
            //
            // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
            // simulator will return -25243 (errSecNoAccessForItem).
#else            
            [genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
        }

        // Use the proper search constants, return only the attributes of the first match.
        [genericPasswordQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
        [genericPasswordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];

        NSDictionary *tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];

        NSMutableDictionary *outDictionary = nil;

        if (! SecItemCopyMatching((CFDictionaryRef)tempQuery, (CFTypeRef *)&outDictionary) == noErr)
        {
            // Stick these default values into keychain item if nothing found.
            [self resetKeychainItem];

            //Adding the account and service identifiers to the keychain
            [keychainItemData setObject:account forKey:(id)kSecAttrAccount];
            [keychainItemData setObject:service forKey:(id)kSecAttrService];

            if (accessGroup != nil)
            {
#if TARGET_IPHONE_SIMULATOR
                // Ignore the access group if running on the iPhone simulator.
                // 
                // Apps that are built for the simulator aren't signed, so there's no keychain access group
                // for the simulator to check. This means that all apps can see all keychain items when run
                // on the simulator.
                //
                // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
                // simulator will return -25243 (errSecNoAccessForItem).
#else            
                [keychainItemData setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
            }
        }
        else
        {
            // load the saved data from Keychain.
            self.keychainItemData = [self secItemFormatToDictionary:outDictionary];
        }

        [outDictionary release];
    }

    return self;
}

希望这可以帮助其他人!

Hope this helps someone else out!

这篇关于iOS Keychain Services:只允许kSecAttrGeneric Key的特定值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆