首页 文章

共享密钥链中的私有数据

提问于
浏览
2

我正在努力使用iOS钥匙串,我似乎无法找到任何好的文档 .

无论如何,我有两个应用程序,基本上我想要做的是在密钥链中共享一些数据并保持一些数据私有,以便其他应用程序无法访问它 .

我试图实现Apple提供的KeychainItemWrapper,但这根本行不通 . 我没有共享数据的问题,但如果我没有设置访问组,数据仍然是共享的 . 我使用的设备不是模拟器,这可能会导致同样的问题 .

这是我的代码

应用1:

KeychainItemWrapper *item = [[KeychainItemWrapper alloc] initWithIdentifier:@"SharedKeyChainApp" accessGroup:nil];
[item setObject:@"MyAccount" forKey:(__bridge id)kSecAttrAccount];
[item setObject:@"SecureValue" forKey:(__bridge id)kSecValueData];

应用2:

KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"SharedKeyChainApp" accessGroup:nil];
NSString *data = [keychain objectForKey:(__bridge id)kSecValueData];
NSLog(@"data is : %@",data); //Prints "data is : SecureValue"

如果我在一个或另一个应用程序中删除我的钥匙串组的项目属性,它将不会打印任何内容 . 但显然我不能再在这两个应用程序之间共享数据了 .

谢谢

1 回答

  • 1

    如果它是共享钥匙串,那么它就是共享的 . 其中任何可以访问钥匙串的应用程序都可以访问其中的所有数据 .

    你可以:

    • 创建2个钥匙串 . 一个共享和一个私人 . 可共享的东西是共享的,私有的东西是私有的 .

    • 加密您不想与他人共享的数据 .

    我可能会选择第一个 . 恕我直言, KeychainItemWrapper 作为抓取和使用代码非常差 . 它附加了一个我编写的快速而脏的代码,并使用密钥链功能进行测试而不使用 KeychainItemWrapper . 在这种情况下,我正在使用"app"和"Security"中的项目来创建一些共享和非共享项目 . 您只需要一些测试代码,并且可以在Targets-> Capabilities-> Keychain Sharing下进行共享 .

    - (void)viewDidLoad {
        [super viewDidLoad];
    
    //    [self removeKeychainItem];
    //    [self addKeychainItem];
        [self searchForKeychainItems];
    }
    
    - (void)searchForKeychainItems {
        [self log:@"\n\n  EXISTING KEYCHAIN ITEM(S)"];
    
        NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll,
                                (__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,       // returns password
                                (__bridge id)kSecReturnAttributes: (__bridge id)kCFBooleanTrue, // returns rest of data
    //                            (__bridge id)kSecAttrAccessGroup: @"AAAAAAAAAA.com.foo.Security"
    //                            (__bridge id)kSecAttrAccessGroup: @"AAAAAAAAAA.com.foo.app"
                            };
    
        OSStatus resultCode;
        CFArrayRef *searchResults = nil;
        resultCode = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&searchResults);
    
        NSArray *foo = CFBridgingRelease(searchResults);
        [self log:[NSString stringWithFormat:@"Search result code: %d", (int)resultCode]];
        [self log:[NSString stringWithFormat:@"Search Results: %@", foo]];
        NSDictionary *keychainItem = foo[0];
        NSString *password = [[NSString alloc] initWithData:[keychainItem objectForKey:(__bridge id)kSecValueData] encoding:NSUTF8StringEncoding];
        [self log:[NSString stringWithFormat:@"password is `%@`", password]];
    }
    
    - (void)addKeychainItem {
        [self log:@"\n\n  ADDING KEYCHAIN ITEM"];
    
        NSDictionary *genericDataDictionary = @{@"authState": @"1",
                                                @"lastAuthDate": @"2/11/2014",
                                                @"otherCrap": @"poo"};
        NSData *encodedGenericData = [NSKeyedArchiver archivedDataWithRootObject:genericDataDictionary];
        NSData *encodedPassword = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
    
        NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecAttrCreator: @"MyCom",
                                (__bridge id)kSecAttrComment: @"keychain tests",
                                (__bridge id)kSecAttrService: @"Credentials",
                                (__bridge id)kSecAttrAccount: @"username",
                                (__bridge id)kSecValueData: encodedPassword,
                            (__bridge id)kSecAttrGeneric: encodedGenericData,
                            (__bridge id)kSecAttrAccessGroup: @"AAAAAAAAAA.com.foo.Security"
                            };
    
        OSStatus result;
        result = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
        NSLog(@"Add status code: %d", (int)result);
    }
    
    - (void)removeKeychainItem {
        [self log:@"\n\n  REMOVING KEYCHAIN ITEM"];
    
        NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    //                            (__bridge id)kSecAttrCreator: @"MyCom",
    //                            (__bridge id)kSecAttrService: @"Credentials",
                                (__bridge id)kSecAttrComment: @"New Keychain standards Test Item",
    //                            (__bridge id)kSecAttrAccount: @"username",
    //                            (__bridge id)kSecValueData: [@"password" dataUsingEncoding:NSUTF8StringEncoding],
    //                            (__bridge id)kSecAttrGeneric: encodedGenericData
                                //                            (__bridge id)kSecAttrAccessGroup: @"AAAAAAAAAA.com.foo.Security"
                                };
    
        OSStatus resultsCode;
        resultsCode = SecItemDelete((__bridge CFDictionaryRef)query);
        NSLog(@"Delete results code: %d", (int)resultsCode);
    }
    
    - (void)log:(NSString *)text {
        self.textView.text = [[self.textView.text stringByAppendingString:text] stringByAppendingString:@"\n"];
    }
    

相关问题