iOS keyChain 的使用
详细资料,请参看苹果官方文档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中的信息,介绍如下:
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种:
kSecClassGenericPassword,//存储普通的密码,
kSecClassInternetPassword,//存储网络密码
kSecClassCertificate,//存储证书,证书中包含共有密匙
kSecClassKey,//存储密匙,其实就是私有密匙
kSecClassIdentity,//存储Identity item,包括一个证书和一个密匙
这5种value都有相应的attribute的key-value pair 可以使用,请参看官方文档。这些attribute key-value pair 的key都是固定的常量; 他们的value,有的是常量, 有的是NSString之类的变量,可以写入自定义内容。另外,这些attribute key-value pair 有的指定了检索的条件,有的指定了检索的返回值,等等,功能不同。
下面看看如何添加一个普通密码到keychain中
- (void)addIdentityIntoKeyChain
{
OSStatus sanityCheck = noErr; NSDictionary *dic = [NSDictionarydictionaryWithObjectsAndKeys: (__bridge id)(kSecClassGenericPassword) ,kSecClass, @"this a my description",kSecAttrDescription, [@""dataUsingEncoding:NSUTF8StringEncoding], kSecValueData, // [@"5678" dataUsingEncoding:NSUTF8StringEncoding], kSecValueRef, nil]; NSLog(@"add dic is %@",dic); CFDictionaryRef dicRef = ( __bridgeCFDictionaryRef)dic; sanityCheck = SecItemAdd(dicRef, nil); NSLog(@"%ld",sanityCheck); }
再看看针对上面这个item的2种不同的查询,
第一种,查询具体的密码,即我们真正需要保存的东西
- (void)getPass2
{
NSLog(@"pass 2==========="); NSDictionary *queryDictionary = [NSDictionarydictionaryWithObjectsAndKeys: @"this a my description",kSecAttrDescription, kCFBooleanTrue, kSecReturnData, kSecClassGenericPassword, kSecClass, nil]; CFTypeRef handle = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)queryDictionary, &handle); NSLog(@"status is %ld",status); if (status == noErr) { NSData *data = (__bridge NSData *)handle; NSString *str = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"str is %@",str); } }
第二种,查询这个item的各种属性,不查询具体的密码
- (NSString *)getPasswordFromKeyChain
{
NSLog(@"pass 1===========");
NSDictionary *queryDictionary = [NSDictionarydictionaryWithObjectsAndKeys:
@"this a my description",kSecAttrDescription,
kCFBooleanTrue, kSecReturnAttributes,
kSecClassGenericPassword, kSecClass,
nil];
CFTypeRef handle = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)queryDictionary, &handle);
NSLog(@"status is %ld",status);
if (status == noErr) {
NSDictionary *dic = (__bridge_transfer NSDictionary*) handle ;
NSLog(@"dic is %@",dic);
}
return@"";
}
请查看具体的输出,来理解这2中查询的不同。
-- ::15.338 KeyChainTest[:] add dic is {
class = genp;
desc = "this a my description";
"v_Data" = <>;
}
-- ::15.356 KeyChainTest[:] -
-- ::15.359 KeyChainTest[:] pass ===========
-- ::15.369 KeyChainTest[:] status is
-- ::15.376 KeyChainTest[:] dic is {
acct = "";
agrp = "BDN8QNY54S.com.Kings.test.KeyChainTest";
cdat = "2013-10-16 06:02:54 +0000";
desc = "this a my description";
mdat = "2013-10-16 06:02:54 +0000";
pdmn = ak;
svce = "";
}
-- ::15.381 KeyChainTest[:] pass ===========
-- ::15.389 KeyChainTest[:] status is
-- ::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 的使用的更多相关文章
- iOS - keychain 详解及变化
keychain介绍 iOS keychain 是一个相对独立的空间,保存到keychain钥匙串中的信息不会因为卸载/重装app而丢失, .相对于NSUserDefaults.plist文件保存等一 ...
- iOS Keychain钥匙串,应用间数据共享打造iOS上的全家桶
Demo先行:https://github.com/rayshen/GIKeychainGroupDemo 该demo里有2个工程,你先运行任何一个会存储一个值,再运行另一个会访问之前的app存储的值 ...
- iOS keyChain
keychain在ios中是保存在sqlite数据库中的. 这个数据库文件的位置: 真机: /private/var/Keychains/keychain-2.db 虚拟机: /Users/USER- ...
- (转)iOS keychain API及其封装
一. Keychain API KeyChain中item的结构为: 1.增加keychain Item OSStatus SecItemAdd (CFDictionaryRef attributes ...
- iOS keyChain(钥匙串)的简单使用
通常在开发中我们需要长久的保存某些值比如用户的账号密码等,对于隐私度很高的数据来说保证数据的安全性是尤为重要的.ios中的keyChain是一种很好的选择. 首先去开发者网站(https://deve ...
- iOS Keychain,SSKeychain,使用 理解 原理
https://www.cnblogs.com/m4abcd/p/5242254.html Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用! 当然是使用第三方库啦:sskeyc ...
- 聊聊iOS Keychain
某天,小熊碰见这样一个错误 Couldn't update the Keychain Item问题处理 ,网上搜索了下网上很多解决方案,依然百撕不得骑姐.后来参考下面两篇文章.才发现是用法不正确,网上 ...
- iOS keychain入门
学了很久的iOS,一直都是明文保存用户名和密码在本地,手机一般都是自己用的,而且非越狱手机东西也不怎么能拿到数据,所以也就没在乎那么多,当然,这是不科学的.悄悄的说,这块一直不是我写的~~~ 用户隐私 ...
- [iOS Keychain本地长期键值存储]
目前本地存储方式大致有:Sqlite,Coredata,NSUserdefaults.但他们都是在删除APP后就会被删除,如果长期使用存储,可以使用Keychain钥匙串来实现. CHKeychain ...
随机推荐
- 浅谈JavaScript原型对象与相关设计模式
引言 本文先从介绍JavaScript中基本的几种设计模式开始,最后引出原型对象,然后对原型对象有一个较全面的介绍. 1.创建对象的几种设计模式 A.工厂模式 我们知道在JavaScript中创建对象 ...
- codevs2171 棋盘覆盖
题目描述 Description 给出一张n*n(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖. 输入描述 Input Description 第一 ...
- PHP文件的上传与下载
文件上传: 1.单个与多个文件上传 2.上传表单的属性设置 3.PHP配置文件中相关文件上传的设置 4.PHP处理上传的文件数据 php.ini配置: file_uploads = on; 默认on ...
- STM32F103xx bxCAN(Basic Extended CAN) 滤波机制
一.背景 最近一个项目需要使用STM32F103xx实现CAN通信,而CAN总线的消息滤波在各个MCU上有不同机制, 譬如,SJA1000为标识符位屏蔽滤波机制,NXP的LPC17xx系列为标识符列表 ...
- 【PHP面向对象(OOP)编程入门教程】16.__toString()方法
我们前面说过在类里面声明“__”开始的方法名的方法(PHP给我们提供的),都是在某一时刻不同情况下自动调用执行的方 法,“__toString()”方法也是一样自动被调用的,是在直接输出对象引用时自动 ...
- 【C语言入门教程】2.1 数据类型(5种基本数据类型),聚合类型与修饰符
C语言有5种基本的数据类型,分别为 字符型.整型.单精度浮点型.双精度浮点型.空类型. 在不同的操作系统或硬件平台中,这些数据类型的值域范围和所占用的内存是有差异的.这种差异影响了C语言的可移植性能, ...
- 使用PHP的五个小技巧
PHP的一些小技巧,比较基础,总结一下,老鸟换个姿势飘过去就是. 1. str_replace str_replace是非常常常常常用的php函数,用于字符串替换,经常看到某些php新人为了替换一批字 ...
- Python制作统计图形
转载自:http://www.dcharm.com/?p=15 Python一般使用Matplotlib制作统计图形,用它自己的说法是‘让简单的事情简单,让复杂的事情变得可能’.(你说国外的“码农”咋 ...
- sja1000芯片can驱动程序
应用层使用socketCan的方法:http://pan.baidu.com/s/1ntsvbb7#path=%252Floongson1%252Ftools%252Fcan 功能:对can驱动程序的 ...
- ThinkPHP框架表单验证
对注册到test表的表单进行验证 在注册之前要对表单进行验证: 用户名非空验证,两次输入密码必须一致即相等验证,年龄在18~50之间即范围验证,邮箱格式正则验证. 自动验证是ThinkPHP模型层提供 ...