首页 > 代码库 > ios之keychain

ios之keychain

 

 https://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html#//apple_ref/doc/uid/TP30000897-CH204-TP9

 

 Keychain Services为一个或多个用户提供了一种安全的保存私密信息(密码,序列号,证书等)的方式。用户可以使用一个简单的密码解锁keychain,并且任何一个支持 Keychain Services的应用程序都可以用这个keychain来存储和检索密码等。

 Keychain Services Programming Guide  中介绍了Keychain Services、讨论了开发者经常使用的功能和数据结构,并且提供了一个例子来讲解如何在你的应用程序中使用keychain.

 

一、基本概念

keychain是一个安全的加密的container,用来为多个应用程序存储密码和提供安全服务。当keychain被锁定时,没有人可以访问它保护的内容。在osX中,用户可以解锁keychain,通过输入一个简单的主密码,为受信任的应用程序(users can unlock a keychain—thus providing trusted applications access to the contents—by entering a single master password)。在ios中,每个ios app都有一个独立的keychain,用户不需要来解锁keychain。在osX中,只要用户允许,任何可以访问keychain的应用程序都可以访问任何一个keychain item,在ios中,一个app只能访问它自己的keychain items。

 Keychain只能同时被一个用户locked;OS X里,某个用户的几个相互信任的Apps可以通过同一个master password来同享一个Keychain,这样该用户在使用这些Apps的时候,只需要unlock keychain container一次,系统为每个用户创建一个名叫login.keychain的default keychain也就是login keychain ;iOS 里,每个App只能使用自己的Keychain container,这样需要访问Keychain container时候,甚至不用Unlock keychain container操作;iPhone里,keychain container的权限是由对App签名的provisioning profile决定的,所以程序升级时候最好使用同一个provisioning profile.

Note: On iPhone, Keychain rights depend on the provisioning profile used to sign your application. Be sure to consistently use the same provisioning profile across different versions of your application.

注意:在iPhone上,keychain的权限只取决于用来给app签名的provisioning profile 。一定要确保在不同版本的应用程序上使用相同的配置概要文件provisioning profile。

 

 

从用户的角度来看,keychain提供的是透明的身份验证服务。也就是说,用户不需要为每一个在keychainl里存储了密码的应用程序单独的登录认证,在os x中,用户只需要输入一个主密码就可以访问到keychain里的所有内容。在ios中,用户甚至不需要输入keychain password。下图清楚的展示了用户、keychain和应用程序之间的关系,对ios来说,用户输入密码来解锁keychain的那一步直接被省略了。在ios中,一个app永远可以访问它自己的keychain items,但是不能访问到别的app的items。

 

默认情况下,在OS X每个登录账户只有一个keychain(新登录在OS X v10.3,这个keychain的名字是login.keychain);然而,一个用户或应用程序可以创建任意数量的keychain。如果login.keychain的密码和用户登录的账户密码相同,那么在登录期间,这个login.keychain是unlocked。在第一次创建时,login Keychain也就是default keychain.

 

keychain的结构

一个keychain可以包含多个keychain items,一个keychain item又可以包含多个attributes。

一个keychain item根据自身的数据类型决定了它是不是需要加密,例如一个存放password或者私有key的item是需要加密的;然后存放certificate的item是可以不加密的,因为certificate数据本身是已经加密了。

与KI相关的attributes取决于这个KI的类型,app最常用的KI类型有: Internet passwords 和 generic passwords。

 Internet passwords 包含的attributes有 security domain, protocol type 和 path。passwords和其他secrets是被加密存储在keychain的。

OS X里,加密的KI在locked时候被请求访问的时候,系统会弹出框让用户输入用户名密码;而非加密KI甚至在locked时,用户也可以随时访问。

iOS里,基本没有用户概念,相对的是程序App,每个App对自己的KIs是有绝对权利的,但是其他程序的KIs无权访问

 

iPhone Keychain Backups 备份

in iOS, an application always has access to its own keychain items and does not have access to any other application’s items. The system generates its own password for the keychain, and stores the key on the device in such a way that it is not accessible to any application. When a user backs up iPhone data, the keychain data is backed up but the secrets in the keychain remain encrypted in the backup. The keychain password is not included in the backup. Therefore, passwords and other secrets stored in the keychain on the iPhone cannot be used by someone who gains access to an iPhone backup. For this reason, it is important to use the keychain on iPhone to store passwords and other data (such as cookies) that can be used to log into secure web sites.

 在ios中,一个app总是可以访问它自己的 keychain items ,并且不允许访问其他app的items。系统为keychain自动生动生成password,并且以一种其它app访问不到的途径存储这个key。当用户备份iphone数据时,keychain里的数据也同时被备份了,只是keychain里存储的secrets等依然是被加密的。 keychain password 不在此备份中。所以说,存储在keychain的passwords和其他secrets不会被别的用户通过备份iphone数据而获得并使用。

 

Keychain Services Ease of Use 易用性

To create a keychain item and add it to a keychain in OS X, for example, you call one of two functions, depending on whether you want to add an Internet password or some other type of password: SecKeychainAddInternetPassword orSecKeychainAddGenericPassword. In your function call, you pass only those attributes for which there is no obvious default value. For example, you must specify the name of the service and the user’s account name, but you do not have to specify the creation date and creator, because the function can figure those out by itself. You also pass the data (usually a password) that you want to store in the keychain. You do not even have to specify a keychain; if you pass NULL for the keychain reference, the function uses the default keychain. If the keychain is locked, the function automatically displays a dialog prompting the user to unlock the keychain. The function also creates the access object for you, listing the calling application as the only trusted application.

创建一个keychain item并把它加入到keychain中,你需要调用 SecKeychainAddInternetPassword  或 SecKeychainAddGenericPassword 这两个函数之一,具体调哪个取决于你是想加入一个Internet password或者其他类型的password。

不管调哪个方法,你只需要传递以下几个attributes:service的name, 用户的账号名。你也可以把你要在keychain里存储的data (usually a password)传递进去。你甚至不需要指定keychain,如果你为keychain reference传入null,则使用默认的keychain。

 

The iOS Keychain Services API uses a different paradigm (see the following section, iOS Keychain Services Search Dictionaries). This API has a single function (SecItemAdd) for adding an item to a keychain.

ios api用了个范例,你只需要调用SecItemAdd方法即可把一个item添加到keychain。

 

IOS Keychain Services Search Dictionaries 搜索字典

iOS里,对KI进行操作(CRUD)是通过一个k-v的dictionary(一种数据结构)来实现的。具体这个k-v的dictionary里面该放哪些数据是由KI的类型决定的。

基本的一个search操作的dictionary由四个K-V组成:KI的类型(class,例如Internet passwords,加密的公私钥);KI的数据(data,例如标签(label),创建日期(date));用于优化搜索的数据,例如证书的issuing或者email地址;查询返回值类型,例如返回的KI放在一个dictionary里或者一个引用地址)。

Type of key

Key

Value

Item class

kSecClass

kSecClassGenericPassword

Attribute

kSecAttrAccount

"ImaUser"

Attribute

kSecAttrService

"Apple Store"

Search attribute

kSecMatchCaseInsensitive

kCFBooleanTrue

Return type

kSecReturnData

kCFBooleanTrue

 

ios之keychain