iOS设备中的Keychain是一个安全的存储容器。通常情况下,可以用NSUserDefaults存储数据信息,但是对于一些私密信息,比如账号、密码等等,就需要使用更为安全的keychain了。苹果自己用keychain来保存Wi-Fi网络密码,VPN凭证等等。它是一个sqlite数据库,位于/private/var/Keychains/keychain-2.db,其保存的所有数据都是加密过的。模拟器下keychain文件路径:~/Library/Application Support/iPhone Simulator/4.3/Library/Keychains

从ios 3.0开始,跨程序分享keychain变得可行。

keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效,数据还在。

关于备份,只会备份数据,到那时不会备份设备的密钥,换句话说,即使拿到数据,也没有办法解密里面的内容。

比较复杂的数据,使用苹果官方发布的KeychainItemWrapper或者SFHFKeychainUtils会很方便。如果是比较简单的,就不用苹果提供的类了,自己写个简单的类来实现就好了。

自己封装:自定义一个类

.h文件

定义了三个方法,存、取、删。并且定义了几个字符串用来做key。

#import <Foundation/Foundation.h>
#define KEY_PASSWORD  @"com.ll.app.password"
#define KEY_USERNAME  @"com.ll.app.username"
#define KEY_USERNAME_PASSWORD  @"com.ll.app.usernamepassword"
@interface LLKeyChain : NSObject
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)delete:(NSString *)service;
@end

 

 

.m文件
引入文件 #import <Security/Security.h>
#import "LLKeyChain.h"
#import <Security/Security.h>
@implementation LLKeyChain
+(NSMutableDictionary *)getKeychainQuery:(NSString *)service{
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,(id)kSecClass,service,(id)kSecAttrService,service,(id)kSecAttrAccount,(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible, nil];
}
+(void)save:(NSString *)service data:(id)data{
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
    
}
+(id)load:(NSString *)service{
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef*)&keyData)==noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData*)keyData];
        }
        @catch (NSException *exception) {
            NSLog(@"unarchive of %@ failed :%@",service,exception);
        }
        @finally {
            
        }
    }
    if (keyData) {
        CFRelease(keyData);
    }
    return ret;
}
+(void)delete:(NSString *)service{
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef) keychainQuery);
}

keychain相关参数说明:http://blog.sina.com.cn/s/blog_7ea0400d0101fksj.html

注意:区别一个item要用到kSecAttrAccount和kSecAttrService

具体使用:

//查找
    NSMutableDictionary *dict = (NSMutableDictionary *)[LLKeyChain load:KEY_USERNAME_PASSWORD];
    NSLog(@"username:%@----password:%@",[dict objectForKey:KEY_USERNAME],[dict objectForKey:KEY_PASSWORD]);
    //存储
    NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
    [usernamepasswordKVPairs setObject:@"ll" forKey:KEY_USERNAME];
    [usernamepasswordKVPairs setObject:@"123456" forKey:KEY_PASSWORD];
    [LLKeyChain save:KEY_USERNAME_PASSWORD  data:usernamepasswordKVPairs];
    //删除
    [LLKeyChain delete:KEY_USERNAME_PASSWORD];