详细资料,请参看苹果官方文档Keychain Services Reference 。

ios中的keychain,用于保存用户的机密信息,对keychain的操作有4种,就是 增,删,改,查:

SecItemCopyMatching 查

Returns one or more keychain items that match a search query, or copies attributes of specific keychain items.

SecItemAdd 增
Adds one or more items to a keychain.

SecItemUpdate 改
Modifies items that match a search query.

SecItemDelete 删
Deletes items that match a search query.


每个操作,都需要定义相应的CFDictionary,下面看看如何定义。

操作函数需要的CFDictionary中的信息,介绍如下:

  1. A dictionary containing an item class key-value pair (“Keychain Item Class Keys and Values (page )) and optional attribute key-value pairs (“Attribute Item Keys and Values (page )) specifying the item's attribute values.

上边提到了2种key-value pair,一种是 item class key-value pair,一种是optional attribute key-value pair,首先要确定item所用的class,之后根据不同的class会用到不同的attribute。

item class key-value pair,它被描述成Keychain Item Class Keys and Values。它的key是kSecClass ,它的value有5种:

  1. kSecClassGenericPassword//存储普通的密码,
  2. kSecClassInternetPassword//存储网络密码
  3. kSecClassCertificate//存储证书,证书中包含共有密匙
  4. kSecClassKey//存储密匙,其实就是私有密匙
  5. kSecClassIdentity//存储Identity item,包括一个证书和一个密匙
  1. 5value都有相应的attributekey-value pair 可以使用,请参看官方文档。这些attribute key-value pair key都是固定的常量; 他们的value,有的是常量, 有的是NSString之类的变量,可以写入自定义内容。另外,这些attribute key-value pair 有的指定了检索的条件,有的指定了检索的返回值,等等,功能不同。
  1.  

  1. 下面看看如何添加一个普通密码到keychain
  1. - (void)addIdentityIntoKeyChain
  2. {
  3. OSStatus sanityCheck = noErr;
  4.  
  5. NSDictionary *dic = [NSDictionarydictionaryWithObjectsAndKeys:
  6.  
  7. (__bridge id)(kSecClassGenericPassword) ,kSecClass,
  8.  
  9. @"this a my description",kSecAttrDescription,
  10.  
  11. [@""dataUsingEncoding:NSUTF8StringEncoding], kSecValueData,
  12.  
  13. // [@"5678" dataUsingEncoding:NSUTF8StringEncoding], kSecValueRef,
  14.  
  15. nil];
  16.  
  17. NSLog(@"add dic is %@",dic);
  18.  
  19. CFDictionaryRef dicRef = ( __bridgeCFDictionaryRef)dic;
  20.  
  21. sanityCheck = SecItemAdd(dicRef, nil);
  22.  
  23. NSLog(@"%ld",sanityCheck);
  24.  
  25. }

再看看针对上面这个item的2种不同的查询,

第一种,查询具体的密码,即我们真正需要保存的东西

  1. - (void)getPass2
  2. {
  3. NSLog(@"pass 2===========");
  4.  
  5. NSDictionary *queryDictionary = [NSDictionarydictionaryWithObjectsAndKeys:
  6.  
  7. @"this a my description",kSecAttrDescription,
  8.  
  9. kCFBooleanTrue, kSecReturnData,
  10.  
  11. kSecClassGenericPassword, kSecClass,
  12.  
  13. nil];
  14.  
  15. CFTypeRef handle = NULL;
  16.  
  17. OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)queryDictionary, &handle);
  18.  
  19. NSLog(@"status is %ld",status);
  20.  
  21. if (status == noErr) {
  22.  
  23. NSData *data = (__bridge NSData *)handle;
  24.  
  25. NSString *str = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];
  26.  
  27. NSLog(@"str is %@",str);
  28.  
  29. }
  30.  
  31. }

第二种,查询这个item的各种属性,不查询具体的密码

  1. - (NSString *)getPasswordFromKeyChain
  2.  
  3. {
  4.  
  5. NSLog(@"pass 1===========");
  6.  
  7. NSDictionary *queryDictionary = [NSDictionarydictionaryWithObjectsAndKeys:
  8.  
  9. @"this a my description",kSecAttrDescription,
  10.  
  11. kCFBooleanTrue, kSecReturnAttributes,
  12.  
  13. kSecClassGenericPassword, kSecClass,
  14.  
  15. nil];
  16.  
  17. CFTypeRef handle = NULL;
  18.  
  19. OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)queryDictionary, &handle);
  20.  
  21. NSLog(@"status is %ld",status);
  22.  
  23. if (status == noErr) {
  24.  
  25. NSDictionary *dic = (__bridge_transfer NSDictionary*) handle ;
  26.  
  27. NSLog(@"dic is %@",dic);
  28.  
  29. }
  30.  
  31. return@"";
  32.  
  33. }

请查看具体的输出,来理解这2中查询的不同。

  1. -- ::15.338 KeyChainTest[:] add dic is {
  2. class = genp;
  3. desc = "this a my description";
  4. "v_Data" = <>;
  5. }
  6. -- ::15.356 KeyChainTest[:] -
  7. -- ::15.359 KeyChainTest[:] pass ===========
  8. -- ::15.369 KeyChainTest[:] status is
  9. -- ::15.376 KeyChainTest[:] dic is {
  10. acct = "";
  11. agrp = "BDN8QNY54S.com.Kings.test.KeyChainTest";
  12. cdat = "2013-10-16 06:02:54 +0000";
  13. desc = "this a my description";
  14. mdat = "2013-10-16 06:02:54 +0000";
  15. pdmn = ak;
  16. svce = "";
  17. }
  18. -- ::15.381 KeyChainTest[:] pass ===========
  19. -- ::15.389 KeyChainTest[:] status is
  20. -- ::15.393 KeyChainTest[:] str is

另外,在keychain的使用中,还经常涉及一个问题,就是2个程序共享机密信息。这常常发生在以下情况:大型公司专门写了一个用户认证程序,指定的机器可以装上这个程序,用这个程序时要求输入帐号和密码,验证通过后,程序会从服务器取公司的证书和用户的私有密匙,并将他们加入到程序的keychain中 。之后该公司写的其他程序,如果需要帐号和密码,或者证书进行服务器验身份证时,就可以用刚才提到的用户认证程序在keychain中保存的信息。

ios程序默认的keychain是不能够和其他程序共享的,如果想共享自己的信息,那么需要加入到一个Keychain Access Groups中,xcode5在工程设定中可以添加。主要注意的是这个Keychain Access Groups的名字是有限制的,必须和你的provisioning profile向一致,这就保证不可能访问到其他公司的机密信息。

转一些别人的心得:

1.相同bundle下生成的程序都可以共享相同group的keyChain.(我对这一条的理解不太一样,我感觉是这样的:bundle Name 分别是 com.companyName.A 和 com.companyName.B,那么这两个程序的keychain group name 就必须是 com.companyName.xxxx)

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

2.如果你在 addkey时,没有指定group,则会默认添加你keychain-access-groups里第一个group(这是keychain group中经常写2个group的原因,简历一个自己的group,防止污染主要的keychain group),如果你没有设置Entitlements,则默认使用对应的程序的bundle name,比如com.jv.key1,表示只能给自己程序使用。

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

iOS keyChain 的使用的更多相关文章

  1. iOS - keychain 详解及变化

    keychain介绍 iOS keychain 是一个相对独立的空间,保存到keychain钥匙串中的信息不会因为卸载/重装app而丢失, .相对于NSUserDefaults.plist文件保存等一 ...

  2. iOS Keychain钥匙串,应用间数据共享打造iOS上的全家桶

    Demo先行:https://github.com/rayshen/GIKeychainGroupDemo 该demo里有2个工程,你先运行任何一个会存储一个值,再运行另一个会访问之前的app存储的值 ...

  3. iOS keyChain

    keychain在ios中是保存在sqlite数据库中的. 这个数据库文件的位置: 真机: /private/var/Keychains/keychain-2.db 虚拟机: /Users/USER- ...

  4. (转)iOS keychain API及其封装

    一. Keychain API KeyChain中item的结构为: 1.增加keychain Item OSStatus SecItemAdd (CFDictionaryRef attributes ...

  5. iOS keyChain(钥匙串)的简单使用

    通常在开发中我们需要长久的保存某些值比如用户的账号密码等,对于隐私度很高的数据来说保证数据的安全性是尤为重要的.ios中的keyChain是一种很好的选择. 首先去开发者网站(https://deve ...

  6. iOS Keychain,SSKeychain,使用 理解 原理

    https://www.cnblogs.com/m4abcd/p/5242254.html Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用! 当然是使用第三方库啦:sskeyc ...

  7. 聊聊iOS Keychain

    某天,小熊碰见这样一个错误 Couldn't update the Keychain Item问题处理 ,网上搜索了下网上很多解决方案,依然百撕不得骑姐.后来参考下面两篇文章.才发现是用法不正确,网上 ...

  8. iOS keychain入门

    学了很久的iOS,一直都是明文保存用户名和密码在本地,手机一般都是自己用的,而且非越狱手机东西也不怎么能拿到数据,所以也就没在乎那么多,当然,这是不科学的.悄悄的说,这块一直不是我写的~~~ 用户隐私 ...

  9. [iOS Keychain本地长期键值存储]

    目前本地存储方式大致有:Sqlite,Coredata,NSUserdefaults.但他们都是在删除APP后就会被删除,如果长期使用存储,可以使用Keychain钥匙串来实现. CHKeychain ...

随机推荐

  1. XStream使用总结

    最近做webService报文转换的公共接口使用到了XSream工具库,写个小总结备忘... XStream是一个可以将javaBean与XML双向转换的java类库,本文内容基于xstream-1. ...

  2. [Angularjs]系列——学习与实践

    写在前面 这个系列是来这家公司到现在,边用边学,以及在工作中遇到的问题进行的总结.深入的东西不多,大多是实际开发中用到的东西. 这里做一个目录,方便查看. 系列文章 [Angularjs]ng-sel ...

  3. tar命令的详细解释

    tar命令的详细解释 标签: linuxfileoutputbashinputshell 2010-05-04 12:11 235881人阅读 评论(12) 收藏 举报  分类: linux/unix ...

  4. oracle中时间运算

    Oracle两个函数相减,默认得到的是天数,按日期格式,精准到响应的精度,如用sysdate(2015/12/7 10:17:52),时间差精确到秒. 在此基础上,oracle两个时间相减默认天数*2 ...

  5. [原] Jenkins Android 自动打包配置

    一.Jenkins自动打包配置 目标:1. 自动打包:2. 自动上传:3. 友好下载 1. Jenkins简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作. 减少重复劳 ...

  6. iSCSI配置流程

    Windows群集两个节点:分别在SQL01和SQL02设置连接共享磁盘: 此前已经在存储服务器通过StarWind创建了三个虚拟磁盘:Quemon+data+backup:starwind安装请参考 ...

  7. Javascript实现AutoComplete自动匹配功能

    功能分析: 避免客户端频繁的访问服务器,因此客户端需要一个timer,监听键盘按键间隔时间,300-600毫秒能够接受. 服务端对要查找的数据源如果不大的话,应该尽量缓存在服务端内存中,而不是每次查找 ...

  8. C++ Const引用详解

    (1)       在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用. 1 int ival ...

  9. Back to Edit Distance(LCS + LIS)

    Given 2 permutations of integers from 1 to N, you need to find the minimum number of operations nece ...

  10. 第2月第3天 egorefresh

    egorefresh是很老的下拉刷新,它是一个uiview,在uitableview 下拉的时候显示不同的界面. egorefresh和uitableview的耦合度很高,uitableview滚动和 ...