一.基本知识

1.方法

SecItemAdd 增
SecItemUpdate 改
SecItemDelete 删
SecItemCopyMatching 查

2.权限

文档上说iOS的keyChain是一个相对独立的空间,当程序替换,删除时并不会删除keyChain的内容,这个要比Library/Cache好。刷机,恢复出厂应该就没有了。关于备份,只会备份数据,到那时不会备份设备的密钥,换句话说,即使拿到数据,也没有办法解密里面的内容。有人说似乎破解的手机就能破解keyChain,本人并不清楚,希望有大神能指教。但个人认为,keyChain只是沙盒的升级版,可以存放一些非私密的信息,即使破解也不影响其它用户,只影响那个破解了的设备。(比如针对该设备的一个密钥)。

可访问性一般来说,自己的程序只能访问自己的keychain,相同bundle的程序通过设置group可以互相共享同组的keychain,从而实现程序间可以共同访问一些数据。详细后面介绍一些我测试下来的经验。

3.如何查询keyChain

genericPasswordQuery = [[NSMutableDictionary alloc] init];
[genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];//1
[genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];//2
if (accessGroup != nil){[genericPasswordQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];//3
}
[genericPasswordQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];//4
[genericPasswordQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];//5
NSDictionary *tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];
NSMutableDictionary *outDictionary = nil;
if (SecItemCopyMatching((CFDictionaryRef)tempQuery, (CFTypeRef *)&outDictionary) == noErr){//6
//found and outDicitionary is not nil
}else{
//not found
}

1.设置Class值,每个Class对应的都有不同的参数类型

2.用户确定的参数,一般是程序中使用的类别,比如说是"Password"或"Account Info",作为search的主力条件

3.设置Group,如果不同程序都拥有这个组,那么不同程序间可以共享这个组的数据

4.只返回第一个匹配数据,查询方法使用,还有值kSecMatchLimitAll

5.返回数据为CFDicitionaryRef,查询方法使用

6.执行查询方法,判断返回值

eg:这个是none-ARC的代码哦!ARC情况下会有bridge提示。

4.类型转换

介绍增删改方法调用前,先介绍转换方法,如何将NSDictionary转换成KeyChain方法可以设置的Dicitionary,一般在写程序过程中,应该尽量避免直接访问KeyChain,一般会创建一个NSDictionary来同步对应的数据,所以两者需要做转换。

//data to secItem
- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert
{// Create a dictionary to return populated with the attributes and data.NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];//设置kSecClass[returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];//将Dictionary里的kSecValueData(一般就是这个keyChain里主要内容,比如说是password),NSString转换成NSDataNSString *passwordString = [dictionaryToConvert objectForKey:(id)kSecValueData];[returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];return returnDictionary;
}
//secItem to data
- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert
{NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];// Add the proper search key and class attribute.[returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];[returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];// Acquire the password data from the attributes.NSData *passwordData = NULL;if (SecItemCopyMatching((CFDictionaryRef)returnDictionary, (CFTypeRef *)&passwordData) == noErr){// 删除多余的kSecReturnData数据[returnDictionary removeObjectForKey:(id)kSecReturnData];// 对应前面的步骤,将数据从NSData转成NSStringNSString *password = [[[NSString alloc] initWithBytes:[passwordData bytes] length:[passwordData length]encoding:NSUTF8StringEncoding] autorelease];[returnDictionary setObject:password forKey:(id)kSecValueData];}else{NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");}[passwordData release]; return returnDictionary;
}

5.增删改

用代码来说明

- (void)writeToKeychain
{NSDictionary *attributes = NULL;NSMutableDictionary *updateItem = NULL;OSStatus result;//判断是增还是改if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr){// First we need the attributes from the Keychain.updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes];// Second we need to add the appropriate search key/values.[updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass];// Lastly, we need to set up the updated attribute list being careful to remove the class.NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData];//删除kSecClass update不能update该字段,否则会报错[tempCheck removeObjectForKey:(id)kSecClass];//参数1表示search的,参数2表示需要更新后的值result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);}else{//增加result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);}
}

删除很简单,就不写注释了

- (void)resetKeychainItem
{OSStatus junk = noErr;if (!keychainItemData){self.keychainItemData = [[NSMutableDictionary alloc] init];}else if (keychainItemData){NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];junk = SecItemDelete((CFDictionaryRef)tempDictionary);NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );}// Default attributes for keychain item.[keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];[keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];[keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];// Default data for keychain item.[keychainItemData setObject:@"" forKey:(id)kSecValueData];
}

二.Group的配置

配置Target的Code Signing Entitlements.

配置该文件

可以配置一个Array列表,表示该程序可以支持多个group

这样就可以在创建secItem时候添加kSecAttrAccessGroup了。

经过测试有以下经验同大家分享:

1.相同bundle下生成的程序都可以共享相同group的keyChain.

相同bundle解释下就是:比如:2个程序分别使用的provision对应bundle是com.jv.key1和com.jv.key2,那你配置文件肯定是{Identifer}.com.jv.{name},其中identifer是苹果生成的随机串号,可以在申请证书时看到,复制过来即可,name可以自己取,程序中指定属于哪个Group即可。

2.如果你在 addkey时,没有指定group,则会默认添加你keychain-access-groups里第一个group,如果你没有设置Entitlements,则默认使用对应的程序的bundle name,比如com.jv.key1,表示只能给自己程序使用。

3.如果你程序添加的group并不存在你的配置文件中,程序会奔溃,表示无法添加。因此你只能添加你配置文件中支持的keychain。

参考资料:

苹果文档:

Keychain Services Reference

Certificate, Key, and Trust Services Programming Guide

Keychain Services Programming Guide

iOS keyChain 研究相关推荐

  1. iOS GPUImage研究总结

    小专栏:GPUImage的源码解读,带你打造一个实用框架 Part one: 关于GPUImage 这里直接引用官方描述: The GPUImage framework is a BSD-licens ...

  2. ios keychain 不被清理_iOS签名机制和说明文件【ios企业签名吧】

    IOS签名机制和配置文件.iOS签名机制的作用:保证安装在手机上的应用程序经苹果公式验证和许可.无论是真机调试还是发布App,开发人员都必须经过一些复杂的步骤.以下广州贝壳技术将详细说明. 贝壳科技( ...

  3. iOS GPUImage研究序一:内置滤镜

    本片介绍关于GPUImage的125个内置过滤器:xoxo_x 著 本文参考:https://github.com/BradLarson/GPUImage#gpuimage 颜色调整 GPUImage ...

  4. iOS Keychain(钥匙串)原理及使用

    Keychain介绍 Keychain Services 是 macOS 和 iOS 都提供一种安全的存储敏感信息的工具,比如,网络密码:用户访问服务器或者网站,通用密码:用来保存应用程序或者数据库密 ...

  5. html5 ios keychain,iOS Keychain理解

    Keychain 介绍 Keychain Services 是 OS X 和 iOS 都提供一种安全地存储敏感信息的工具,比如,存储用户ID,密码,和证书等.存储这些信息可以免除用户重复输入用户名和密 ...

  6. iOS KeyChain使用

    最近项目需要存储用户的唯一标识符,但是由于如果用户重装APP,获取到的又会是一个新的UDID.查询了一系列资料下来,可以用Keychain进行存储UDID,然后就算重装了APP,也能从Keychain ...

  7. iOS Keychain和keychain share

    一.keychain介绍(摘抄别人的https://blog.hudongdong.com/ios/356.html) 根据苹果的介绍,iOS设备中的Keychain是一个安全的存储容器,可以用来为不 ...

  8. html5 ios keychain,iOS 用keychain钥匙串保存账号、设备UUID及APP间共享

    iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于NSUserDefaults.文件保存等一般方式,key ...

  9. html5 ios keychain,iOS10适配之Keychain读写失败

    Keychain iOS设备中的Keychain是一个安全的存储容器,可以用来为不同应用保存敏感信息比如用户名,密码,网络密码,认证令牌,UUID等 Bug 升级正式版Xcode8 运行了下最近的项目 ...

最新文章

  1. 两边放动物对战守城的游戏_集合啦!动物森友会定制周边;百战天虫 大混战发布...
  2. leetcode 337. House Robber III | 337. 打家劫舍 III(树形dp;什么情况下dp需要强制包含当前元素?)
  3. 搜索引擎技术之网络爬虫
  4. 鸿蒙系统麒麟970芯片支持,受鸿蒙系统影响,众多华为手机或要说再见,包括麒麟970机型!...
  5. 【2019杭电多校第六场1008=HDU6641】TDL(思维)
  6. 最全最新cpu显卡天梯图_2018 年新近详细CPU、显卡天梯图
  7. for循环及判断语句的20个经典习题
  8. Spark学习之路——9.Spark ML
  9. pythonai人脸识别_AI的强大!用Python实现一个简单的人脸识别
  10. canvas学习(html5)画画
  11. 主数据管理系统(MDM)的四种实现风格
  12. Clippper模拟量输出设置
  13. 计算机职业生涯规划书素材,2021大学生职业生涯规划书素材模板
  14. 基于国服DOTA2的反和谐vpk
  15. 【Linux进程间通信】一、什么是IPC
  16. 如何把PPT转换成pdf格式的文件
  17. 矩阵秩相关不等式的题目
  18. 随记(17)场景AOI、游戏场景
  19. 宜家推出供应链金融方案支持中小企业复工复产;汉高提出全新战略框架 | 美通企业日报...
  20. 团建游戏---迷失丛林

热门文章

  1. 法兰克机器人外部自动_(完整版)KUKA机器人外部自动配置方法
  2. 2021年,学UI设计还吃香吗?
  3. SVAC编解码技术标准:诞生、质疑与发展
  4. 《闻官军收河南河北》 杜甫
  5. 第一章 kotlin基础知识
  6. [推荐书籍]12本程序员必备书籍
  7. 好心情:跌落凡间的星星天使,爱终将弥补一切
  8. 前端面试题——计算机网络 高频
  9. 2019 秦皇岛CCPC赛后总结
  10. 2023年全国最新机动车签字授权人精选真题及答案10