iOS使用keychain存储密码

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];

KeychainItemWrapper和SFHFKeychainUtils具体使用参照:http://blog.csdn.net/tan243203681/article/details/50896299

 

posted @ 2015-03-08 15:59  LiLM  阅读(758)  评论(0编辑  收藏  举报