加密iOS Developer

iOS Keychain总结

2016-05-09  本文已影响1934人  NapoleonY

概要

iOS中一般用Keychain存储密码、私钥等需要加密的数据。参考apple 官网介绍

使用方法

先总的说下怎么使用,再具体说说原理。
我自己实现了几个基本的功能:查找、更新、删除、添加。后续会继续补充更多的功能。
已开源到github

  1. 在工程中添加Secutity.framework库。(TARGETS-General-Linked Frameworks and Libraries)
  2. 使用说明
#import "NYKeychain.h"//引入头文件
NSString *serviceName = xxx;//服务名
NSString *account = xxx;//账户名
//其中serviceName和account在程序内部自己定义的常量,keychain根据这两个量保存、查找、更新、替换密码
[NYKeychain setPassword:password forService:serviceName account:account];//保存、更新密码
[NYKeychain passwordForService:serviceName account:account];//查找
 [NYKeychain deletePasswordForService:serviceName account:account];//删除

原理

keychain相当于一个银行的金库,keychain item就相当于金库里的一个个的保险柜,保存在keychain Item里面的密码就相当于保险柜里面存放的金条。

keychain结构
Keychain 服务搜索字典

iOS中Keychain Services使用key-value dictionary来指定我们想要创建或者查找的keychain item属性。
一个典型的搜索字典包含以下四部分:

搜索dictionary

代码详解

与Keychain相关的操作最重要的就是dictionary。所有操作都是围绕配置这个dictionary。
在下面的代码中,首先配置了这个dictionary四个部分的前两个部分,即class key-value pair,一般属性。

- (NSMutableDictionary *)query
{
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3];
    //要保存的password类型
    [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
    if (self.service) {//AttrService 和AttrAccount是两个主要的属性
        [dictionary setObject:self.service forKey:(__bridge id)kSecAttrService];
    }
    if (self.account) {
        [dictionary setObject:self.account forKey:(__bridge id)kSecAttrAccount];
    }
    return dictionary;
}
使用Keychain item 搜索dictionary

apple提供了四个函数用来进行密码的查找、添加、更新、删除等操作。

SecItemAdd;
SecItemUpdate;
SecItemCopyMatching;
SecItemDelete;
 - (BOOL)fetch
{
    CFTypeRef result = NULL;
    NSMutableDictionary *query = [self query];
    //YES本来是一个值,@YES就变成了一个对象,可用[NSNumber numberWithBool];代替
    [query setObject:@YES forKey:(__bridge id)kSecReturnData];
    [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
    if (status != errSecSuccess) {
        return NO;
    }
    self.passwordData = (__bridge_transfer NSData *)result;
    return YES;
}

if this attribute is not provided, then case-sensitive string matching is performed

 - (BOOL)save
{
    NSMutableDictionary *query = nil;
    NSMutableDictionary *searchQuery = [self query];
    //添加前首先查找是否存在要添加的密码
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)searchQuery, nil);
    if (status == errSecSuccess) {//item 已经存在,更新它
        query = [[NSMutableDictionary alloc] init];
        [query setObject:self.passwordData forKey:(__bridge id)kSecValueData];
        status = SecItemUpdate((__bridge CFDictionaryRef)searchQuery, (__bridge         CFDictionaryRef)query);
    } else if (status == errSecItemNotFound) {//item未找到,创建它
        query = [self query];
        [query setObject:self.passwordData forKey:(__bridge id)kSecValueData];
        status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
    }
    return (status == errSecSuccess);
}
 - (BOOL)deleteItem
{
NSMutableDictionary *query = [self query];
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
return (status == errSecSuccess);
}

以上内容都是基础,懂了这些,Keychain相关的其它内容也就不难理解了。以后如果用到,会进一步增加其它复杂的功能。

上一篇 下一篇

猜你喜欢

热点阅读