keychain service钥匙串服务是iOS提供的用于管理用户密码、密钥、证书、标识的服务,它相当于一个加密容器,app可以把相关的用户信息以钥匙条目的形式存储到其中,钥匙串服务会将所有存储到其中的条目进行加密,并保护起来,只允许创建这个条目的app访问它。
app要把用户信息(钥匙)添加到钥匙串服务(钥匙串)中,在必要时从钥匙串服务中取出用户信息,这些动作需要用到Keychain Services API。Keychain Services API的相关属性和方法声明在< Security/security.h >中。
一、操作钥匙条目的三个方法:
1、添加钥匙条目到钥匙串
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
2、修改钥匙条目
OSStatus SecItemUpdate(CFDictionaryRef query,CFDictionaryRef attributesToUpdate)
3、提取钥匙信息
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
二、添加钥匙条目到钥匙串
添加钥匙条目到钥匙串可以调用SecItemAdd方法,但前提是要先要将用户信息封装成钥匙条目secItem,才可以加入到钥匙串。钥匙条目实际上就是一个钥匙属性字典,将需要存储的用户信息加到这个字典中,再插入一些与钥匙属性相关的键值对,就形成了一个钥匙条目,然后就可以加入到钥匙串里了。这个字典的特殊在于,它有许多预定好的key,用户信息,以及钥匙条目的属性信息,加到该字典(调用setValue:forKey:)指定的key中。
下面来了解钥匙条目字典中都有哪些key。
1、与用户信息相关的key
kSecValueData ,这个key对应CFDataRef类型的value,把要存储的用户信息放到这里,这里的内容如果是秘钥或密码,钥匙串服务就会对它们进行加密存储。
2、与钥匙条目的属性相关的key
根据存储的用户信息的不同,钥匙串服务把钥匙条目分成了几类:普通密码(kSecClassGenericPassword)条目、互联网密码(kSecClassInternetPassword)条目、密钥(kSecClassKey)条目、证书(kSecClassCertificate)条目和标识(kSecClassIdentity)条目。不同类型的钥匙条目有各自的属性key。
(1)普通密码钥匙条目的key有:
kSecAttrAccessible
kSecAttrAccessControl
kSecAttrAccessGroup
kSecAttrCreationDate
kSecAttrModificationDate
kSecAttrDescription
kSecAttrComment
kSecAttrCreator
kSecAttrType
kSecAttrLabel
kSecAttrIsInvisible
kSecAttrIsNegative
kSecAttrAccount
kSecAttrService
kSecAttrGeneric
kSecAttrSynchronizable
(2)网络密码钥匙条目的key有:
kSecAttrAccessible
kSecAttrAccessControl
kSecAttrAccessGroup
kSecAttrCreationDate
kSecAttrModificationDate
kSecAttrDescription
kSecAttrComment
kSecAttrCreator
kSecAttrType
kSecAttrLabel
kSecAttrIsInvisible
kSecAttrIsNegative
kSecAttrAccount
kSecAttrSecurityDomain
kSecAttrServer
kSecAttrProtocol
kSecAttrAuthenticationType
kSecAttrPort
kSecAttrPath
kSecAttrSynchronizable
(3)证书钥匙条目的key有:
kSecAttrAccessible
kSecAttrAccessControl
kSecAttrAccessGroup
kSecAttrCertificateType
kSecAttrCertificateEncoding
kSecAttrLabel
kSecAttrSubject
kSecAttrIssuer
kSecAttrSerialNumber
kSecAttrSubjectKeyID
kSecAttrPublicKeyHash
kSecAttrSynchronizable
(4)秘钥条目的key有:
kSecAttrAccessible
kSecAttrAccessControl
kSecAttrAccessGroup
kSecAttrKeyClass
kSecAttrLabel
kSecAttrApplicationLabel
kSecAttrIsPermanent
kSecAttrApplicationTag
kSecAttrKeyType
kSecAttrKeySizeInBits
kSecAttrEffectiveKeySize
kSecAttrCanEncrypt
kSecAttrCanDecrypt
kSecAttrCanDerive
kSecAttrCanSign
kSecAttrCanVerify
kSecAttrCanWrap
kSecAttrCanUnwrap
kSecAttrSynchronizable
(5)标识钥匙条目的key有:
钥匙串服务中所说的标识identity就是证书(公钥)和秘钥(私钥)的结合。因此标识钥匙条目的属性字典中的key是证书钥匙条目的key加上密钥钥匙条目的key。
(6)部分key的意义,及其对应value的类型
三、从钥匙串中查询钥匙条目
要从钥匙串中查询钥匙条目,需要调用这个方法SecItemCopyMatching
方法,查询的本质其实是匹配,也就说需要先提供有关钥匙条目的相关信息,拿着这些信息到钥匙串中进行匹配,如果能找到有匹配的,就相当于查询到了钥匙条目,然后将它取出。
1、提供有关钥匙条目的相关信息
有关要查询的钥匙条目的信息,是以一个字典的形式提供给SecItemCopyMatching
方法的(第一个参数)。因此要查询钥匙条目,第一件事是新建一个字典(姑且称作查询字典),并插入有关钥匙条目的信息。该字典也是有许多预定义的key的,有些key对应的value是必须要设置的。
查询字典的预定义key有许多,一个查询字典通常包括以下key:
(1)若干钥匙条目的属性key
也就是上面说到的,创建一个钥匙条目时可以用的各种key。
(2)若干与匹配条件相关的key
如果给这种key设置了value就相当于多了一条匹配条件,钥匙条目字典的某个键值对要符合这个条件才匹配。不设置则不生效。
(3)若干与查询结果类型相关的key
2、获取查询结果
提供了查询字典,接下来就是获取查询结果,需要有一个CFTypeRef类型变量来承接查询结果(传入SecItemCopyMatching方法的第二个参数)。
在结果字典中,可以通过指定key来获取到有关钥匙条目的信息
三、实际应用
使用钥匙串服务的一般思路是&#x