29

这个问题讨论了使用 crypt() 函数在 iPhone 上加密数据。作为替代方案,iPhone 上是否有钥匙串,如果有,我将使用什么代码来访问它以存储登录详细信息,然后在应用程序中为我们检索它们?

4

7 回答 7

45

另一件需要注意的事情:当使用 iPhone SDK 的旧版本(2.x、3.x)时,钥匙串 API 在模拟器中不起作用。这可以在测试时为您节省很多挫败感!

于 2008-10-15T03:41:55.257 回答
34

您可以使用一个钥匙串 - 对于代码,最好的办法是查看 Apple 的 GenericKeychain 示例应用程序:

通用钥匙串示例

于 2008-10-10T12:32:03.647 回答
8

我真的很喜欢Buzz Anderson 的 Keychain 抽象层,我热切地等待Jens Alfke 的 MYCrypto达到可用状态。后者在允许在 Mac OS X 和 iPhone 上使用相同的代码方面做得很好,尽管它的功能只是模仿钥匙串的一小部分。

于 2009-06-19T21:05:49.413 回答
8

这是我用来在钥匙串中存储键/值对的方法。确保将 Security.framework 添加到您的项目中

#import <Security/Security.h>

// -------------------------------------------------------------------------
-(NSString *)getSecureValueForKey:(NSString *)key {
    /*

     Return a value from the keychain

     */

    // Retrieve a value from the keychain
    NSDictionary *result;
    NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecReturnAttributes, nil] autorelease];
    NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, kCFBooleanTrue, nil] autorelease];
    NSDictionary *query = [[NSDictionary alloc] initWithObjects: objects forKeys: keys];

    // Check if the value was found
    OSStatus status = SecItemCopyMatching((CFDictionaryRef) query, (CFTypeRef *) &result);
    [query release];
    if (status != noErr) {
        // Value not found
        return nil;
    } else {
        // Value was found so return it
        NSString *value = (NSString *) [result objectForKey: (NSString *) kSecAttrGeneric];
        return value;
    }
}




// -------------------------------------------------------------------------
-(bool)storeSecureValue:(NSString *)value forKey:(NSString *)key {
    /*

     Store a value in the keychain

     */

    // Get the existing value for the key
    NSString *existingValue = [self getSecureValueForKey:key];

    // Check if a value already exists for this key
    OSStatus status;
    if (existingValue) {
        // Value already exists, so update it
        NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, nil] autorelease];
        NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, nil] autorelease];
        NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
        status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject:value forKey: (NSString *) kSecAttrGeneric]);
    } else {
        // Value does not exist, so add it
        NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrGeneric, nil] autorelease];
        NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, key, value, nil] autorelease];
        NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
        status = SecItemAdd((CFDictionaryRef) query, NULL);
    }

    // Check if the value was stored
    if (status != noErr) {
        // Value was not stored
        return false;
    } else {
        // Value was stored
        return true;
    }
}

值得注意的是,如果用户删除您的应用,这些键/值不会被删除。如果用户删除您的应用程序,然后重新安装它,键/值仍然可以访问。

于 2011-09-06T02:04:22.803 回答
5

还要记住,在生成 AppID 时,如果希望多个应用程序访问相同的 Keychain 信息,则必须生成通配符 AppID (#####.com.prefix.*)...

于 2008-10-11T17:14:10.360 回答
4

借助 GenericKeychain 示例的最新版本 1.2,Apple 提供了一个钥匙串包装器,该包装器也可以在 iPhone 模拟器上运行。查看这篇文章了解详情:http ://dev-metal.blogspot.com/2010/08/howto-use-keychain-in-iphone-sdk-to.html

于 2010-08-16T19:44:04.760 回答
0

这是来自Mr.Granoff https://github.com/granoff/Lockbox的另一个很好的包装类

于 2013-09-11T12:55:19.487 回答